aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNingSun <ning.sun@intel.com>2018-02-08 08:34:03 -0800
committerNingSun <ning.sun@intel.com>2018-02-08 09:14:52 -0800
commit0c89b3ccba7c9b7332ab67ae1936aff51ca62367 (patch)
tree70c1b1d160d4c6d0a83395ca9a87c1264d0d3439
parent945613b4db4e07f75d2bc7463db580ddfaa700fd (diff)
Initial sshsm project structure
Issue-ID: AAF-94 Change-Id: I5e82fff418e7567b161acf9b98013a9b85ffc5b4 Signed-off-by: NingSun <ning.sun@intel.com>
-rw-r--r--.gitreview5
-rw-r--r--Adapter/README3
-rw-r--r--README.md17
-rw-r--r--SoftHSMv2/.appveyor.yml63
-rw-r--r--SoftHSMv2/.gitignore80
-rw-r--r--SoftHSMv2/.travis.yml13
-rw-r--r--SoftHSMv2/FIPS-NOTES.md56
-rw-r--r--SoftHSMv2/LICENSE28
-rw-r--r--SoftHSMv2/Makefile.am65
-rw-r--r--SoftHSMv2/NEWS292
-rw-r--r--SoftHSMv2/OSX-NOTES.md182
-rw-r--r--SoftHSMv2/README.md149
-rw-r--r--SoftHSMv2/WIN32-NOTES.md311
-rw-r--r--SoftHSMv2/aes_wrap_key_with_pad/README7
-rw-r--r--SoftHSMv2/aes_wrap_key_with_pad/botan-diff340
-rw-r--r--SoftHSMv2/autogen.sh3
-rw-r--r--SoftHSMv2/configure.ac226
-rw-r--r--SoftHSMv2/m4/acx_64bit.m429
-rw-r--r--SoftHSMv2/m4/acx_botan.m472
-rw-r--r--SoftHSMv2/m4/acx_botan_aes_gcm.m437
-rw-r--r--SoftHSMv2/m4/acx_botan_ecc.m451
-rw-r--r--SoftHSMv2/m4/acx_botan_gnump.m427
-rw-r--r--SoftHSMv2/m4/acx_botan_gost.m452
-rw-r--r--SoftHSMv2/m4/acx_botan_rawpss.m437
-rw-r--r--SoftHSMv2/m4/acx_botan_rfc5649.m447
-rw-r--r--SoftHSMv2/m4/acx_cppunit.m421
-rw-r--r--SoftHSMv2/m4/acx_crypto_backend.m4168
-rw-r--r--SoftHSMv2/m4/acx_dlopen.m415
-rw-r--r--SoftHSMv2/m4/acx_non_paged_memory.m457
-rw-r--r--SoftHSMv2/m4/acx_openssl.m460
-rw-r--r--SoftHSMv2/m4/acx_openssl_ecc.m437
-rw-r--r--SoftHSMv2/m4/acx_openssl_fips.m450
-rw-r--r--SoftHSMv2/m4/acx_openssl_gost.m465
-rw-r--r--SoftHSMv2/m4/acx_openssl_rfc5649.m451
-rw-r--r--SoftHSMv2/m4/acx_p11kit.m436
-rw-r--r--SoftHSMv2/m4/acx_pedantic.m412
-rw-r--r--SoftHSMv2/m4/acx_prefixhack.m423
-rw-r--r--SoftHSMv2/m4/acx_sqlite3.m440
-rw-r--r--SoftHSMv2/m4/acx_strict.m412
-rw-r--r--SoftHSMv2/m4/acx_visibility.m414
-rw-r--r--SoftHSMv2/m4/acx_yield.m410
-rw-r--r--SoftHSMv2/m4/ax_cxx_compile_stdcxx_11.m4146
-rw-r--r--SoftHSMv2/prepdist.sh19
-rw-r--r--SoftHSMv2/softhsm2.module.in4
-rw-r--r--SoftHSMv2/src/Makefile.am3
-rw-r--r--SoftHSMv2/src/bin/Makefile.am10
-rw-r--r--SoftHSMv2/src/bin/common/Makefile.am3
-rw-r--r--SoftHSMv2/src/bin/common/findslot.cpp372
-rw-r--r--SoftHSMv2/src/bin/common/findslot.h42
-rw-r--r--SoftHSMv2/src/bin/common/getpw.cpp207
-rw-r--r--SoftHSMv2/src/bin/common/getpw.h40
-rw-r--r--SoftHSMv2/src/bin/common/library.cpp145
-rw-r--r--SoftHSMv2/src/bin/common/library.h42
-rw-r--r--SoftHSMv2/src/bin/dump/Makefile.am24
-rw-r--r--SoftHSMv2/src/bin/dump/common.h506
-rw-r--r--SoftHSMv2/src/bin/dump/softhsm2-dump-db.118
-rw-r--r--SoftHSMv2/src/bin/dump/softhsm2-dump-db.cpp968
-rw-r--r--SoftHSMv2/src/bin/dump/softhsm2-dump-file.118
-rw-r--r--SoftHSMv2/src/bin/dump/softhsm2-dump-file.cpp537
-rw-r--r--SoftHSMv2/src/bin/dump/tables.h554
-rw-r--r--SoftHSMv2/src/bin/keyconv/Makefile.am26
-rw-r--r--SoftHSMv2/src/bin/keyconv/base64.c311
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp227
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp261
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.163
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp351
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h134
-rw-r--r--SoftHSMv2/src/bin/migrate/Makefile.am20
-rw-r--r--SoftHSMv2/src/bin/migrate/softhsm2-migrate.167
-rw-r--r--SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp798
-rw-r--r--SoftHSMv2/src/bin/migrate/softhsm2-migrate.h68
-rw-r--r--SoftHSMv2/src/bin/util/Makefile.am40
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp704
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-botan.h142
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp790
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-ossl.h142
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.1259
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.cpp1318
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.h77
-rw-r--r--SoftHSMv2/src/bin/win32/getopt.cpp520
-rw-r--r--SoftHSMv2/src/bin/win32/getopt.h101
-rw-r--r--SoftHSMv2/src/bin/win32/getpassphase.cpp35
-rw-r--r--SoftHSMv2/src/lib/Makefile.am52
-rw-r--r--SoftHSMv2/src/lib/P11Attributes.cpp2514
-rw-r--r--SoftHSMv2/src/lib/P11Attributes.h1264
-rw-r--r--SoftHSMv2/src/lib/P11Objects.cpp1807
-rw-r--r--SoftHSMv2/src/lib/P11Objects.h398
-rw-r--r--SoftHSMv2/src/lib/SoftHSM.cpp11178
-rw-r--r--SoftHSMv2/src/lib/SoftHSM.h436
-rw-r--r--SoftHSMv2/src/lib/access.cpp101
-rw-r--r--SoftHSMv2/src/lib/access.h42
-rw-r--r--SoftHSMv2/src/lib/common/Configuration.cpp176
-rw-r--r--SoftHSMv2/src/lib/common/Configuration.h117
-rw-r--r--SoftHSMv2/src/lib/common/HandleFactory.h121
-rw-r--r--SoftHSMv2/src/lib/common/Makefile.am28
-rw-r--r--SoftHSMv2/src/lib/common/MutexFactory.cpp192
-rw-r--r--SoftHSMv2/src/lib/common/MutexFactory.h133
-rw-r--r--SoftHSMv2/src/lib/common/Serialisable.h52
-rw-r--r--SoftHSMv2/src/lib/common/SimpleConfigLoader.cpp352
-rw-r--r--SoftHSMv2/src/lib/common/SimpleConfigLoader.h63
-rw-r--r--SoftHSMv2/src/lib/common/fatal.cpp64
-rw-r--r--SoftHSMv2/src/lib/common/fatal.h52
-rw-r--r--SoftHSMv2/src/lib/common/log.cpp109
-rw-r--r--SoftHSMv2/src/lib/common/log.h85
-rw-r--r--SoftHSMv2/src/lib/common/osmutex.cpp242
-rw-r--r--SoftHSMv2/src/lib/common/osmutex.h47
-rw-r--r--SoftHSMv2/src/lib/common/softhsm2.conf.5.in86
-rw-r--r--SoftHSMv2/src/lib/common/softhsm2.conf.in10
-rw-r--r--SoftHSMv2/src/lib/crypto/AESKey.cpp67
-rw-r--r--SoftHSMv2/src/lib/crypto/AESKey.h51
-rw-r--r--SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.cpp221
-rw-r--r--SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h184
-rw-r--r--SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.cpp41
-rw-r--r--SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.h66
-rw-r--r--SoftHSMv2/src/lib/crypto/AsymmetricParameters.h59
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanAES.cpp354
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanAES.h60
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp308
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanCryptoFactory.h105
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDES.cpp153
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDES.h63
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDH.cpp408
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDH.h80
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDHKeyPair.cpp70
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDHKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.cpp310
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.h117
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDHPublicKey.cpp146
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDHPublicKey.h77
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDSA.cpp760
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDSA.h86
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.cpp70
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.cpp243
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.h86
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.cpp162
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.h78
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDH.cpp356
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDH.h79
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.cpp71
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.cpp259
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.h87
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.cpp151
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.h79
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDSA.cpp465
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDSA.h84
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.cpp71
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.cpp255
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.h87
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.cpp151
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.h79
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOST.cpp535
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOST.h82
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.cpp71
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.cpp201
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.h94
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.cpp201
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.h86
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOSTR3411.cpp47
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanGOSTR3411.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.cpp133
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.h64
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanMAC.cpp154
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanMAC.h107
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanMD5.cpp45
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanMD5.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.cpp310
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.h74
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRNG.cpp87
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRNG.h66
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRSA.cpp1219
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRSA.h90
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.cpp70
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.cpp304
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.h89
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.cpp131
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.h75
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA1.cpp45
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA1.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA224.cpp45
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA224.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA256.cpp45
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA256.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA384.cpp45
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA384.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA512.cpp45
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSHA512.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.cpp593
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.h83
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanUtil.cpp146
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanUtil.h68
-rw-r--r--SoftHSMv2/src/lib/crypto/Botan_ecb.cpp153
-rw-r--r--SoftHSMv2/src/lib/crypto/Botan_ecb.h107
-rw-r--r--SoftHSMv2/src/lib/crypto/Botan_rounding.h68
-rw-r--r--SoftHSMv2/src/lib/crypto/CryptoFactory.cpp102
-rw-r--r--SoftHSMv2/src/lib/crypto/CryptoFactory.h97
-rw-r--r--SoftHSMv2/src/lib/crypto/DESKey.cpp115
-rw-r--r--SoftHSMv2/src/lib/crypto/DESKey.h55
-rw-r--r--SoftHSMv2/src/lib/crypto/DHParameters.cpp111
-rw-r--r--SoftHSMv2/src/lib/crypto/DHParameters.h81
-rw-r--r--SoftHSMv2/src/lib/crypto/DHPrivateKey.cpp120
-rw-r--r--SoftHSMv2/src/lib/crypto/DHPrivateKey.h81
-rw-r--r--SoftHSMv2/src/lib/crypto/DHPublicKey.cpp118
-rw-r--r--SoftHSMv2/src/lib/crypto/DHPublicKey.h74
-rw-r--r--SoftHSMv2/src/lib/crypto/DSAParameters.cpp108
-rw-r--r--SoftHSMv2/src/lib/crypto/DSAParameters.h78
-rw-r--r--SoftHSMv2/src/lib/crypto/DSAPrivateKey.cpp134
-rw-r--r--SoftHSMv2/src/lib/crypto/DSAPrivateKey.h83
-rw-r--r--SoftHSMv2/src/lib/crypto/DSAPublicKey.cpp132
-rw-r--r--SoftHSMv2/src/lib/crypto/DSAPublicKey.h76
-rw-r--r--SoftHSMv2/src/lib/crypto/ECParameters.cpp78
-rw-r--r--SoftHSMv2/src/lib/crypto/ECParameters.h64
-rw-r--r--SoftHSMv2/src/lib/crypto/ECPrivateKey.cpp106
-rw-r--r--SoftHSMv2/src/lib/crypto/ECPrivateKey.h82
-rw-r--r--SoftHSMv2/src/lib/crypto/ECPublicKey.cpp104
-rw-r--r--SoftHSMv2/src/lib/crypto/ECPublicKey.h75
-rw-r--r--SoftHSMv2/src/lib/crypto/GOSTPrivateKey.cpp75
-rw-r--r--SoftHSMv2/src/lib/crypto/GOSTPrivateKey.h79
-rw-r--r--SoftHSMv2/src/lib/crypto/GOSTPublicKey.cpp75
-rw-r--r--SoftHSMv2/src/lib/crypto/GOSTPublicKey.h72
-rw-r--r--SoftHSMv2/src/lib/crypto/HashAlgorithm.cpp76
-rw-r--r--SoftHSMv2/src/lib/crypto/HashAlgorithm.h80
-rw-r--r--SoftHSMv2/src/lib/crypto/MacAlgorithm.cpp128
-rw-r--r--SoftHSMv2/src/lib/crypto/MacAlgorithm.h101
-rw-r--r--SoftHSMv2/src/lib/crypto/Makefile.am126
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLAES.cpp275
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLAES.h64
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLCMAC.cpp84
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLCMAC.h55
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLComp.cpp415
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLComp.h98
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp388
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h116
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDES.cpp165
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDES.h64
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDH.cpp430
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDH.h80
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.cpp70
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.cpp239
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.h85
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.cpp175
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.h77
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDSA.cpp695
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDSA.h86
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.cpp70
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.cpp256
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.h86
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.cpp193
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.h78
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECDH.cpp375
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECDH.h79
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECDSA.cpp457
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECDSA.h80
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECKeyPair.cpp71
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.cpp187
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.h85
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECPublicKey.cpp131
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLECPublicKey.h76
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.cpp244
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.h77
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.cpp133
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.h66
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.cpp220
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.h77
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp575
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.h81
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOST.cpp658
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOST.h85
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.cpp71
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.cpp184
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.h88
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.cpp162
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.h80
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.cpp48
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLHMAC.cpp109
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLHMAC.h92
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLMD5.cpp46
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLMD5.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRNG.cpp52
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRNG.h53
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRSA.cpp1554
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRSA.h87
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.cpp70
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.cpp320
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.h90
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.cpp155
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.h76
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA1.cpp46
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA1.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA224.cpp46
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA224.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA256.cpp46
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA256.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA384.cpp46
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA384.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA512.cpp46
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLSHA512.h48
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLUtil.cpp199
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLUtil.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/PrivateKey.h72
-rw-r--r--SoftHSMv2/src/lib/crypto/PublicKey.h65
-rw-r--r--SoftHSMv2/src/lib/crypto/RNG.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/RSAParameters.cpp94
-rw-r--r--SoftHSMv2/src/lib/crypto/RSAParameters.h74
-rw-r--r--SoftHSMv2/src/lib/crypto/RSAPrivateKey.cpp186
-rw-r--r--SoftHSMv2/src/lib/crypto/RSAPrivateKey.h91
-rw-r--r--SoftHSMv2/src/lib/crypto/RSAPublicKey.cpp105
-rw-r--r--SoftHSMv2/src/lib/crypto/RSAPublicKey.h72
-rw-r--r--SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.cpp229
-rw-r--r--SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.h148
-rw-r--r--SoftHSMv2/src/lib/crypto/SymmetricKey.cpp109
-rw-r--r--SoftHSMv2/src/lib/crypto/SymmetricKey.h78
-rw-r--r--SoftHSMv2/src/lib/crypto/odd.h72
-rw-r--r--SoftHSMv2/src/lib/crypto/test/AESTests.cpp1182
-rw-r--r--SoftHSMv2/src/lib/crypto/test/AESTests.h78
-rw-r--r--SoftHSMv2/src/lib/crypto/test/DESTests.cpp1164
-rw-r--r--SoftHSMv2/src/lib/crypto/test/DESTests.h65
-rw-r--r--SoftHSMv2/src/lib/crypto/test/DHTests.cpp245
-rw-r--r--SoftHSMv2/src/lib/crypto/test/DHTests.h65
-rw-r--r--SoftHSMv2/src/lib/crypto/test/DSATests.cpp338
-rw-r--r--SoftHSMv2/src/lib/crypto/test/DSATests.h65
-rw-r--r--SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp268
-rw-r--r--SoftHSMv2/src/lib/crypto/test/ECDHTests.h65
-rw-r--r--SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp301
-rw-r--r--SoftHSMv2/src/lib/crypto/test/ECDSATests.h65
-rw-r--r--SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp304
-rw-r--r--SoftHSMv2/src/lib/crypto/test/GOSTTests.h76
-rw-r--r--SoftHSMv2/src/lib/crypto/test/HashTests.cpp269
-rw-r--r--SoftHSMv2/src/lib/crypto/test/HashTests.h73
-rw-r--r--SoftHSMv2/src/lib/crypto/test/MacTests.cpp687
-rw-r--r--SoftHSMv2/src/lib/crypto/test/MacTests.h83
-rw-r--r--SoftHSMv2/src/lib/crypto/test/Makefile.am39
-rw-r--r--SoftHSMv2/src/lib/crypto/test/RNGTests.cpp85
-rw-r--r--SoftHSMv2/src/lib/crypto/test/RNGTests.h59
-rw-r--r--SoftHSMv2/src/lib/crypto/test/RSATests.cpp682
-rw-r--r--SoftHSMv2/src/lib/crypto/test/RSATests.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/test/chisq.c144
-rw-r--r--SoftHSMv2/src/lib/crypto/test/cryptotest.cpp91
-rw-r--r--SoftHSMv2/src/lib/crypto/test/ent.c110
-rw-r--r--SoftHSMv2/src/lib/crypto/test/ent.h56
-rw-r--r--SoftHSMv2/src/lib/crypto/test/iso8859.c25
-rw-r--r--SoftHSMv2/src/lib/crypto/test/iso8859.h23
-rw-r--r--SoftHSMv2/src/lib/crypto/test/randtest.c190
-rw-r--r--SoftHSMv2/src/lib/crypto/test/randtest.h13
-rw-r--r--SoftHSMv2/src/lib/data_mgr/ByteString.cpp365
-rw-r--r--SoftHSMv2/src/lib/data_mgr/ByteString.h131
-rw-r--r--SoftHSMv2/src/lib/data_mgr/Makefile.am17
-rw-r--r--SoftHSMv2/src/lib/data_mgr/RFC4880.cpp110
-rw-r--r--SoftHSMv2/src/lib/data_mgr/RFC4880.h54
-rw-r--r--SoftHSMv2/src/lib/data_mgr/SecureAllocator.h203
-rw-r--r--SoftHSMv2/src/lib/data_mgr/SecureDataManager.cpp537
-rw-r--r--SoftHSMv2/src/lib/data_mgr/SecureDataManager.h154
-rw-r--r--SoftHSMv2/src/lib/data_mgr/SecureMemoryRegistry.cpp142
-rw-r--r--SoftHSMv2/src/lib/data_mgr/SecureMemoryRegistry.h73
-rw-r--r--SoftHSMv2/src/lib/data_mgr/salloc.cpp126
-rw-r--r--SoftHSMv2/src/lib/data_mgr/salloc.h56
-rw-r--r--SoftHSMv2/src/lib/data_mgr/test/ByteStringTests.cpp356
-rw-r--r--SoftHSMv2/src/lib/data_mgr/test/ByteStringTests.h71
-rw-r--r--SoftHSMv2/src/lib/data_mgr/test/Makefile.am27
-rw-r--r--SoftHSMv2/src/lib/data_mgr/test/RFC4880Tests.cpp116
-rw-r--r--SoftHSMv2/src/lib/data_mgr/test/RFC4880Tests.h56
-rw-r--r--SoftHSMv2/src/lib/data_mgr/test/SecureDataMgrTests.cpp207
-rw-r--r--SoftHSMv2/src/lib/data_mgr/test/SecureDataMgrTests.h56
-rw-r--r--SoftHSMv2/src/lib/data_mgr/test/datamgrtest.cpp91
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/Handle.cpp50
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/Handle.h62
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp239
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/HandleManager.h94
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/Makefile.am17
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp178
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h58
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/test/Makefile.am26
-rw-r--r--SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp65
-rw-r--r--SoftHSMv2/src/lib/main.cpp1187
-rw-r--r--SoftHSMv2/src/lib/object_store/DB.cpp926
-rw-r--r--SoftHSMv2/src/lib/object_store/DB.h188
-rw-r--r--SoftHSMv2/src/lib/object_store/DBObject.cpp1493
-rw-r--r--SoftHSMv2/src/lib/object_store/DBObject.h142
-rw-r--r--SoftHSMv2/src/lib/object_store/DBToken.cpp874
-rw-r--r--SoftHSMv2/src/lib/object_store/DBToken.h135
-rw-r--r--SoftHSMv2/src/lib/object_store/Directory.cpp278
-rw-r--r--SoftHSMv2/src/lib/object_store/Directory.h89
-rw-r--r--SoftHSMv2/src/lib/object_store/File.cpp765
-rw-r--r--SoftHSMv2/src/lib/object_store/File.h136
-rw-r--r--SoftHSMv2/src/lib/object_store/FindOperation.cpp80
-rw-r--r--SoftHSMv2/src/lib/object_store/FindOperation.h67
-rw-r--r--SoftHSMv2/src/lib/object_store/Generation.cpp261
-rw-r--r--SoftHSMv2/src/lib/object_store/Generation.h92
-rw-r--r--SoftHSMv2/src/lib/object_store/Makefile.am34
-rw-r--r--SoftHSMv2/src/lib/object_store/OSAttribute.cpp187
-rw-r--r--SoftHSMv2/src/lib/object_store/OSAttribute.h103
-rw-r--r--SoftHSMv2/src/lib/object_store/OSAttributes.h50
-rw-r--r--SoftHSMv2/src/lib/object_store/OSObject.h95
-rw-r--r--SoftHSMv2/src/lib/object_store/OSPathSep.h45
-rw-r--r--SoftHSMv2/src/lib/object_store/OSToken.cpp722
-rw-r--r--SoftHSMv2/src/lib/object_store/OSToken.h160
-rw-r--r--SoftHSMv2/src/lib/object_store/ObjectFile.cpp870
-rw-r--r--SoftHSMv2/src/lib/object_store/ObjectFile.h154
-rw-r--r--SoftHSMv2/src/lib/object_store/ObjectStore.cpp187
-rw-r--r--SoftHSMv2/src/lib/object_store/ObjectStore.h88
-rw-r--r--SoftHSMv2/src/lib/object_store/ObjectStoreToken.cpp84
-rw-r--r--SoftHSMv2/src/lib/object_store/ObjectStoreToken.h106
-rw-r--r--SoftHSMv2/src/lib/object_store/SessionObject.cpp334
-rw-r--r--SoftHSMv2/src/lib/object_store/SessionObject.h132
-rw-r--r--SoftHSMv2/src/lib/object_store/SessionObjectStore.cpp212
-rw-r--r--SoftHSMv2/src/lib/object_store/SessionObjectStore.h100
-rw-r--r--SoftHSMv2/src/lib/object_store/UUID.cpp68
-rw-r--r--SoftHSMv2/src/lib/object_store/UUID.h48
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.cpp159
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.h79
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBObjectTests.cpp816
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBObjectTests.h93
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBTests.cpp648
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBTests.h134
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBTokenTests.cpp491
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DBTokenTests.h66
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DirectoryTests.cpp227
-rw-r--r--SoftHSMv2/src/lib/object_store/test/DirectoryTests.h54
-rw-r--r--SoftHSMv2/src/lib/object_store/test/FileTests.cpp340
-rw-r--r--SoftHSMv2/src/lib/object_store/test/FileTests.h63
-rw-r--r--SoftHSMv2/src/lib/object_store/test/Makefile.am39
-rw-r--r--SoftHSMv2/src/lib/object_store/test/OSTokenTests.cpp504
-rw-r--r--SoftHSMv2/src/lib/object_store/test/OSTokenTests.h60
-rw-r--r--SoftHSMv2/src/lib/object_store/test/ObjectFileTests.cpp911
-rw-r--r--SoftHSMv2/src/lib/object_store/test/ObjectFileTests.h72
-rw-r--r--SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.cpp278
-rw-r--r--SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.h58
-rw-r--r--SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.cpp319
-rw-r--r--SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.h56
-rw-r--r--SoftHSMv2/src/lib/object_store/test/SessionObjectTests.cpp436
-rw-r--r--SoftHSMv2/src/lib/object_store/test/SessionObjectTests.h68
-rw-r--r--SoftHSMv2/src/lib/object_store/test/UUIDTests.cpp61
-rw-r--r--SoftHSMv2/src/lib/object_store/test/UUIDTests.h54
-rw-r--r--SoftHSMv2/src/lib/object_store/test/objstoretest.cpp91
-rw-r--r--SoftHSMv2/src/lib/pkcs11/cryptoki.h94
-rw-r--r--SoftHSMv2/src/lib/pkcs11/pkcs11.h265
-rw-r--r--SoftHSMv2/src/lib/pkcs11/pkcs11f.h939
-rw-r--r--SoftHSMv2/src/lib/pkcs11/pkcs11t.h2003
-rw-r--r--SoftHSMv2/src/lib/session_mgr/Makefile.am17
-rw-r--r--SoftHSMv2/src/lib/session_mgr/Session.cpp454
-rw-r--r--SoftHSMv2/src/lib/session_mgr/Session.h175
-rw-r--r--SoftHSMv2/src/lib/session_mgr/SessionManager.cpp246
-rw-r--r--SoftHSMv2/src/lib/session_mgr/SessionManager.h66
-rw-r--r--SoftHSMv2/src/lib/session_mgr/test/Makefile.am26
-rw-r--r--SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp260
-rw-r--r--SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h53
-rw-r--r--SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp111
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Makefile.am18
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Slot.cpp116
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Slot.h81
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/SlotManager.cpp179
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/SlotManager.h71
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Token.cpp573
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/Token.h112
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/test/Makefile.am25
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.cpp485
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.h60
-rw-r--r--SoftHSMv2/src/lib/slot_mgr/test/slotmgrtest.cpp91
-rw-r--r--SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.cpp206
-rw-r--r--SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.h55
-rw-r--r--SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.cpp228
-rw-r--r--SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.h55
-rw-r--r--SoftHSMv2/src/lib/test/DeriveTests.cpp737
-rw-r--r--SoftHSMv2/src/lib/test/DeriveTests.h73
-rw-r--r--SoftHSMv2/src/lib/test/DigestTests.cpp326
-rw-r--r--SoftHSMv2/src/lib/test/DigestTests.h60
-rw-r--r--SoftHSMv2/src/lib/test/InfoTests.cpp320
-rw-r--r--SoftHSMv2/src/lib/test/InfoTests.h65
-rw-r--r--SoftHSMv2/src/lib/test/InitTests.cpp247
-rw-r--r--SoftHSMv2/src/lib/test/InitTests.h65
-rw-r--r--SoftHSMv2/src/lib/test/Makefile.am40
-rw-r--r--SoftHSMv2/src/lib/test/ObjectTests.cpp2393
-rw-r--r--SoftHSMv2/src/lib/test/ObjectTests.h194
-rw-r--r--SoftHSMv2/src/lib/test/README17
-rw-r--r--SoftHSMv2/src/lib/test/RandomTests.cpp94
-rw-r--r--SoftHSMv2/src/lib/test/RandomTests.h51
-rw-r--r--SoftHSMv2/src/lib/test/SessionTests.cpp176
-rw-r--r--SoftHSMv2/src/lib/test/SessionTests.h57
-rw-r--r--SoftHSMv2/src/lib/test/SignVerifyTests.cpp830
-rw-r--r--SoftHSMv2/src/lib/test/SignVerifyTests.h73
-rw-r--r--SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.cpp998
-rw-r--r--SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.h80
-rw-r--r--SoftHSMv2/src/lib/test/TestsBase.cpp49
-rw-r--r--SoftHSMv2/src/lib/test/TestsBase.h44
-rw-r--r--SoftHSMv2/src/lib/test/TestsNoPINInitBase.cpp160
-rw-r--r--SoftHSMv2/src/lib/test/TestsNoPINInitBase.h78
-rw-r--r--SoftHSMv2/src/lib/test/TokenTests.cpp98
-rw-r--r--SoftHSMv2/src/lib/test/TokenTests.h50
-rw-r--r--SoftHSMv2/src/lib/test/UserTests.cpp270
-rw-r--r--SoftHSMv2/src/lib/test/UserTests.h56
-rw-r--r--SoftHSMv2/src/lib/test/p11test.cpp92
-rw-r--r--SoftHSMv2/src/lib/test/softhsm2-alt.conf.in6
-rw-r--r--SoftHSMv2/src/lib/test/softhsm2-alt.conf.win326
-rw-r--r--SoftHSMv2/src/lib/test/softhsm2.conf.in6
-rw-r--r--SoftHSMv2/src/lib/test/softhsm2.conf.win326
-rw-r--r--SoftHSMv2/src/lib/test/tokens/dummy.in0
-rw-r--r--SoftHSMv2/src/lib/win32/dllmain.cc18
-rw-r--r--SoftHSMv2/src/lib/win32/setenv.cpp20
-rw-r--r--SoftHSMv2/src/lib/win32/setenv.h12
-rw-r--r--SoftHSMv2/src/lib/win32/syslog.cpp69
-rw-r--r--SoftHSMv2/src/lib/win32/syslog.h46
-rw-r--r--SoftHSMv2/testing/appveyor/APPVEYOR-NOTES.MD27
-rw-r--r--SoftHSMv2/testing/appveyor/appveyor_build.bat51
-rw-r--r--SoftHSMv2/testing/appveyor/appveyor_download_requirements.ps180
-rw-r--r--SoftHSMv2/testing/build-botan.sh85
-rw-r--r--SoftHSMv2/testing/build-softhsm2.sh110
-rw-r--r--SoftHSMv2/testing/lib.sh2232
-rw-r--r--SoftHSMv2/testing/travis/travis.sh35
-rw-r--r--SoftHSMv2/win32/.gitignore35
-rw-r--r--SoftHSMv2/win32/Configure.py1167
-rw-r--r--SoftHSMv2/win32/config.h.in185
-rw-r--r--SoftHSMv2/win32/convarch/convarch.vcxproj.filters.in928
-rw-r--r--SoftHSMv2/win32/convarch/convarch.vcxproj.in374
-rw-r--r--SoftHSMv2/win32/convarch/convarch.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.filters123
-rw-r--r--SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.in127
-rw-r--r--SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.filters54
-rw-r--r--SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.in104
-rw-r--r--SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/dump/dump.vcxproj.filters33
-rw-r--r--SoftHSMv2/win32/dump/dump.vcxproj.in95
-rw-r--r--SoftHSMv2/win32/dump/dump.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.filters42
-rw-r--r--SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.in100
-rw-r--r--SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/keyconv/keyconv.vcxproj.filters.in88
-rw-r--r--SoftHSMv2/win32/keyconv/keyconv.vcxproj.in116
-rw-r--r--SoftHSMv2/win32/keyconv/keyconv.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.filters84
-rw-r--r--SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.in114
-rw-r--r--SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/p11test/p11test.vcxproj.filters181
-rw-r--r--SoftHSMv2/win32/p11test/p11test.vcxproj.in159
-rw-r--r--SoftHSMv2/win32/p11test/p11test.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.filters42
-rw-r--r--SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.in100
-rw-r--r--SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.filters42
-rw-r--r--SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.in100
-rw-r--r--SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/softhsm2.sln.in117
-rw-r--r--SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.filters63
-rw-r--r--SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.in107
-rw-r--r--SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.user3
-rw-r--r--SoftHSMv2/win32/util/util.vcxproj.filters.in108
-rw-r--r--SoftHSMv2/win32/util/util.vcxproj.in130
-rw-r--r--SoftHSMv2/win32/util/util.vcxproj.user3
-rw-r--r--TPM2-Plugin/README5
559 files changed, 112872 insertions, 0 deletions
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..5b40e19
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,5 @@
+[gerrit]
+host=gerrit.onap.org
+port=29418
+project=aaf/sshsm.git
+
diff --git a/Adapter/README b/Adapter/README
new file mode 100644
index 0000000..0851e1e
--- /dev/null
+++ b/Adapter/README
@@ -0,0 +1,3 @@
+## Introduction
+
+This is an adapatation layer between SoftHSM and TPM2-Plugin.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4f2c0d7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,17 @@
+# SoftHSMv2 + TPM-Plugin
+## Introduction
+
+## Installation
+
+### Configure
+
+### Compile
+
+### Install
+
+
+
+
+## Note
+SoftHSMv2 is cloned from https://github.com/opendnssec/SoftHSMv2.git
+with commit 6eb01f906ea112572b7bd80ca7b43982f1a160d6
diff --git a/SoftHSMv2/.appveyor.yml b/SoftHSMv2/.appveyor.yml
new file mode 100644
index 0000000..121d805
--- /dev/null
+++ b/SoftHSMv2/.appveyor.yml
@@ -0,0 +1,63 @@
+version: 2.2.{build}
+configuration: Release
+platform:
+- x86
+- x64
+init:
+- ps: >-
+ If ($env:Platform -Match "x86") {
+ $env:VCVARS_PLATFORM="x86"
+ $env:MSBUILD_PLATFORM="Win32"
+ $env:ENV_PLATFORM="x86"
+ $env:CONFIGURE_OPTIONS="disable-debug $env:ADDITIONAL_CONFIGURE_OPTIONS"
+ } Else {
+ $env:VCVARS_PLATFORM="amd64"
+ $env:MSBUILD_PLATFORM="x64"
+ $env:ENV_PLATFORM="x64"
+ $env:CONFIGURE_OPTIONS="enable-64bit disable-debug $env:ADDITIONAL_CONFIGURE_OPTIONS"
+ }
+
+
+ $CURRENT_DIR_PATH = (Get-Item -Path ".\" -Verbose).FullName
+
+ $env:BUILD_DIR = Join-Path $CURRENT_DIR_PATH build
+
+ $env:CRYPTO_PACKAGE= "$env:CRYPTO_PACKAGE_NAME-$env:ENV_PLATFORM.zip"
+
+ $env:CRYPTO_PACKAGE_PATH = Join-Path $env:BUILD_DIR "$env:CRYPTO_PACKAGE_NAME-$env:ENV_PLATFORM"
+
+ $env:CPPUNIT_VERSION_NAME = "CppUnit-1.13.2"
+
+ $env:CPPUNIT_PACKAGE_NAME = "cppunit-1.13.2"
+
+ $env:CPPUNIT_PACKAGE = "$env:CPPUNIT_PACKAGE_NAME-$env:ENV_PLATFORM.zip"
+
+ $env:PYTHON_PATH = Join-Path $env:BUILD_DIR python
+
+ $env:CPPUNIT_PATH = Join-Path $env:BUILD_DIR "$env:CPPUNIT_PACKAGE_NAME-$env:ENV_PLATFORM"
+
+ $env:PYTHON_EXE = Join-Path $env:PYTHON_PATH python.exe
+
+ $env:RELEASE_DIR=Join-Path $env:BUILD_DIR "SoftHSMv2-$env:ENV_PLATFORM"
+
+ $env:CONFIGURE_OPTIONS = "$env:CONFIGURE_OPTIONS with-crypto-backend=$env:CRYPTO_BACKEND with-$env:CRYPTO_BACKEND=$env:CRYPTO_PACKAGE_PATH\ with-cppunit=$env:CPPUNIT_PATH\"
+environment:
+ matrix:
+ - CRYPTO_BACKEND: openssl
+ PACKAGE_VERSION_NAME: OpenSSL-1.0.2j
+ CRYPTO_PACKAGE_NAME: openssl-1.0.2j
+ - CRYPTO_BACKEND: botan
+ PACKAGE_VERSION_NAME: Botan-1.10.13
+ CRYPTO_PACKAGE_NAME: botan-1.10.13
+ - CRYPTO_BACKEND: openssl
+ PACKAGE_VERSION_NAME: OpenSSL-1.1.0b
+ CRYPTO_PACKAGE_NAME: openssl-1.1.0b
+ ADDITIONAL_CONFIGURE_OPTIONS: disable-gost
+install:
+- cmd: powershell -File testing/appveyor/appveyor_download_requirements.ps1
+build_script:
+- cmd: testing/appveyor/appveyor_build.bat
+test: off
+artifacts:
+- path: build/SoftHSMv2-$(Platform)
+ name: SoftHSMv2-$(PACKAGE_VERSION_NAME)-$(Platform)
diff --git a/SoftHSMv2/.gitignore b/SoftHSMv2/.gitignore
new file mode 100644
index 0000000..88488d9
--- /dev/null
+++ b/SoftHSMv2/.gitignore
@@ -0,0 +1,80 @@
+# Automake, autoconf, libtool
+Makefile
+Makefile.in
+core
+acinclude.m4
+aclocal.m4
+autom4te.cache
+compile
+py-compile
+confdefs.h
+config.*
+!win32+botan/config.h
+!win32+openssl/config.h
+configure
+conftest
+conftest.c
+depcomp
+install-sh
+libtool
+libtool.m4
+lt*.m4
+ltmain.sh
+missing
+mkinstalldirs
+stamp-h*
+obj
+test-driver
+.deps
+.libs
+
+# Object files
+*.lo
+*.o
+
+# Libraries
+*.lib
+*.la
+*.a
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Test outputs
+*.log
+*.trs
+test-results.xml
+
+# Temporary files
+*~
+
+# Building directories
+build
+Botan-*
+ROOT
+
+# Specifics
+softhsm2.module
+src/bin/common/.dirstamp
+src/bin/dump/softhsm2-dump-db
+src/bin/dump/softhsm2-dump-file
+src/bin/keyconv/softhsm2-keyconv
+src/bin/util/softhsm2-util
+src/lib/common/.dirstamp
+src/lib/common/softhsm2.conf
+src/lib/common/softhsm2.conf.5
+src/lib/crypto/.dirstamp
+src/lib/crypto/test/cryptotest
+src/lib/data_mgr/test/datamgrtest
+src/lib/handle_mgr/test/handlemgrtest
+src/lib/object_store/test/objstoretest
+src/lib/session_mgr/test/sessionmgrtest
+src/lib/slot_mgr/test/slotmgrtest
+src/lib/test/p11test
+src/lib/test/softhsm2-alt.conf
+src/lib/test/softhsm2.conf
+src/lib/test/tokens/64d6c3fe-1575-1736-1d26-5ccb28440ea7/
+src/lib/test/tokens/dummy
diff --git a/SoftHSMv2/.travis.yml b/SoftHSMv2/.travis.yml
new file mode 100644
index 0000000..13f50a5
--- /dev/null
+++ b/SoftHSMv2/.travis.yml
@@ -0,0 +1,13 @@
+language: cpp
+compiler:
+ - gcc
+ - clang
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install build-essential autoconf automake libtool libcppunit-dev libsqlite3-dev sqlite3 libbotan1.10-dev libssl-dev p11-kit
+script: sh testing/travis/travis.sh
+env:
+ - CRYPTO=openssl OBJSTORE=file
+ - CRYPTO=openssl OBJSTORE=sqlite
+ - CRYPTO=botan OBJSTORE=file
+ - CRYPTO=botan OBJSTORE=sqlite
diff --git a/SoftHSMv2/FIPS-NOTES.md b/SoftHSMv2/FIPS-NOTES.md
new file mode 100644
index 0000000..1827a3b
--- /dev/null
+++ b/SoftHSMv2/FIPS-NOTES.md
@@ -0,0 +1,56 @@
+# FIPS 140-2
+
+The OpenSSL crypto backend can be a FIPS 140-2 capable library,
+cf. the OpenSSL FIPS 140 documents SecurityPolicy and UserGuide.
+
+## Introduction
+
+Please read the OpenSSL FIPS 140 documents about to get
+a FIPS Capable OpenSSL library.
+
+## Hard points
+
+Reread the OpenSSL FIPS 140 documents as they are hard to apply.
+
+Note the following is for Unix/Linux.
+
+Now I suppose you have a >= 1.0.1e capable static library (a
+dynamic library is far easier but always possible and often
+dubious from a security point of view... BTW if you have built
+a FIPS Capable OpenSSL library you should not be afraid of
+extra complexity :-).
+
+Do not forget to compile OpenSSL with position indepent code
+(aka PIC) as the libsofthsm.so requires it. The FIPS module
+canister is already compiled this way.
+
+A usual issue is the C++ compiler not compiling .c files as C code.
+A simple test can show this, put in foo.c file this code:
+
+foo() { char *x = "ab"; }
+
+and compile with the C and C++ compilers with all warnings:
+the C++ compiler should raise an extra warning or error about
+the no type for foo() and/or for the char* string constant.
+
+When this raises some errors in the fispld script, you have to
+insert '-x c' and '-x none' before and after each .c file
+in the C++ commands, for instance using this wrapper:
+
+-------------------------------- cut here --------------------------------
+#!/bin/sh
+
+commands="g++"
+
+for elem in $@
+do
+ case $elem in
+ *.c) commands+=" -x c $elem -x none";;
+ *) commands+=" $elem";;
+ esac
+done
+
+exec $commands
+-------------------------------- end --------------------------------
+
+In any cases you have to set CC and CXX to fipsld.
diff --git a/SoftHSMv2/LICENSE b/SoftHSMv2/LICENSE
new file mode 100644
index 0000000..be4c168
--- /dev/null
+++ b/SoftHSMv2/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2010 .SE, The Internet Infrastructure Foundation
+ http://www.iis.se
+
+Copyright (c) 2010 SURFnet bv
+ http://www.surfnet.nl/en
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/SoftHSMv2/Makefile.am b/SoftHSMv2/Makefile.am
new file mode 100644
index 0000000..a6573a3
--- /dev/null
+++ b/SoftHSMv2/Makefile.am
@@ -0,0 +1,65 @@
+ACLOCAL_AMFLAGS = -I m4
+
+MAINTAINERCLEANFILES = \
+ config.log config.status softhsm2.module \
+ $(srcdir)/Makefile.in \
+ $(srcdir)/config.h.in $(srcdir)/config.h.in~ \
+ $(srcdir)/configure \
+ $(srcdir)/install-sh $(srcdir)/ltmain.sh $(srcdir)/missing \
+ $(srcdir)/depcomp $(srcdir)/aclocal.m4 $(srcdir)/compile \
+ $(srcdir)/config.guess $(srcdir)/config.sub
+
+SUBDIRS = src
+
+if WITH_P11KIT
+p11moddir = @P11KIT_PATH@
+p11mod_DATA = softhsm2.module
+endif
+
+EXTRA_DIST = $(srcdir)/aes_wrap_key_with_pad/botan-diff \
+ $(srcdir)/aes_wrap_key_with_pad/README \
+ $(srcdir)/FIPS-NOTES.md \
+ $(srcdir)/LICENSE \
+ $(srcdir)/m4/*.m4 \
+ $(srcdir)/OSX-NOTES.md \
+ $(srcdir)/README.md \
+ $(srcdir)/win32/config.h.in \
+ $(srcdir)/win32/Configure.py \
+ $(srcdir)/win32/convarch/convarch.vcxproj.in \
+ $(srcdir)/win32/convarch/convarch.vcxproj.filters.in \
+ $(srcdir)/win32/convarch/convarch.vcxproj.user \
+ $(srcdir)/win32/cryptotest/cryptotest.vcxproj.in \
+ $(srcdir)/win32/cryptotest/cryptotest.vcxproj.filters \
+ $(srcdir)/win32/cryptotest/cryptotest.vcxproj.user \
+ $(srcdir)/win32/datamgrtest/datamgrtest.vcxproj.in \
+ $(srcdir)/win32/datamgrtest/datamgrtest.vcxproj.filters \
+ $(srcdir)/win32/datamgrtest/datamgrtest.vcxproj.user \
+ $(srcdir)/win32/dump/dump.vcxproj.in \
+ $(srcdir)/win32/dump/dump.vcxproj.filters \
+ $(srcdir)/win32/dump/dump.vcxproj.user \
+ $(srcdir)/win32/handlemgrtest/handlemgrtest.vcxproj.in \
+ $(srcdir)/win32/handlemgrtest/handlemgrtest.vcxproj.filters \
+ $(srcdir)/win32/handlemgrtest/handlemgrtest.vcxproj.user \
+ $(srcdir)/win32/keyconv/keyconv.vcxproj.in \
+ $(srcdir)/win32/keyconv/keyconv.vcxproj.filters.in \
+ $(srcdir)/win32/keyconv/keyconv.vcxproj.user \
+ $(srcdir)/win32/objstoretest/objstoretest.vcxproj.in \
+ $(srcdir)/win32/objstoretest/objstoretest.vcxproj.filters \
+ $(srcdir)/win32/objstoretest/objstoretest.vcxproj.user \
+ $(srcdir)/win32/p11test/p11test.vcxproj.in \
+ $(srcdir)/win32/p11test/p11test.vcxproj.filters \
+ $(srcdir)/win32/p11test/p11test.vcxproj.user \
+ $(srcdir)/win32/sessionmgrtest/sessionmgrtest.vcxproj.in \
+ $(srcdir)/win32/sessionmgrtest/sessionmgrtest.vcxproj.filters \
+ $(srcdir)/win32/sessionmgrtest/sessionmgrtest.vcxproj.user \
+ $(srcdir)/win32/slotmgrtest/slotmgrtest.vcxproj.in \
+ $(srcdir)/win32/slotmgrtest/slotmgrtest.vcxproj.filters \
+ $(srcdir)/win32/slotmgrtest/slotmgrtest.vcxproj.user \
+ $(srcdir)/win32/softhsm2/softhsm2.vcxproj.in \
+ $(srcdir)/win32/softhsm2/softhsm2.vcxproj.filters \
+ $(srcdir)/win32/softhsm2/softhsm2.vcxproj.user \
+ $(srcdir)/win32/softhsm2.sln.in \
+ $(srcdir)/win32/util/util.vcxproj.in \
+ $(srcdir)/win32/util/util.vcxproj.filters.in \
+ $(srcdir)/win32/util/util.vcxproj.user \
+ $(srcdir)/WIN32-NOTES.md
diff --git a/SoftHSMv2/NEWS b/SoftHSMv2/NEWS
new file mode 100644
index 0000000..5d209ec
--- /dev/null
+++ b/SoftHSMv2/NEWS
@@ -0,0 +1,292 @@
+NEWS for SoftHSM -- History of user visible changes
+
+SoftHSM develop
+
+* Issue #140: Support for CKA_ALLOWED_MECHANISMS.
+ (Patch from Brad Hess)
+* Issue #141: Support CKA_ALWAYS_AUTHENTICATE for private key objects.
+* Issue #220: Support for CKM_DES3_CMAC and CKM_AES_CMAC.
+* Issue #226: Configuration option for Windows build to enable build with
+ static CRT (/MT).
+* Issue #325: Support for CKM_AES_GCM.
+* Issue #334: Document that initialized tokens will be reassigned to another
+ slot (based on the token serial number).
+* Issue #335: Support for CKM_RSA_PKCS_PSS.
+ (Patch from Nikos Mavrogiannopoulos)
+* Issue #341: Import AES keys with softhsm2-util.
+ (Patch from Pavel Cherezov)
+* Issue #348: Document that OSX needs pkg-config to detect cppunit.
+* Issue #349: softhsm2-util will check the configuration and report any
+ issues before loading the PKCS#11 library.
+* Issue #351: Upgrade Botan in Jenkins build.
+
+Bugfixes:
+* Issue #345: Private objects are presented to security officer in search
+ results.
+* Issue #358: Race condition when multiple applications are creating and
+ reading object files.
+
+
+SoftHSM 2.3.0 - 2017-07-03
+
+* Issue #130: Upgraded to PKCS#11 v2.40.
+ * Minor changes to some return values.
+ * Added CKA_DESTROYABLE to all objects. Used by C_DestroyObject().
+ * Added CKA_PUBLIC_KEY_INFO to certificates, private, and public key
+ objects. Will be accepted from application, but SoftHSM will
+ currently not calculate it.
+* Issue #142: Support for CKM_AES_CTR.
+* Issue #155: Add unit tests for SessionManager.
+* Issue #189: C_DigestKey returns CKR_KEY_INDIGESTIBLE when key
+ attribute CKA_EXTRACTABLE = false. Whitelist SHA algorithms to allow
+ C_DigestKey in this case.
+* Issue #225: Show slot id after initialization.
+* Issue #247: Run AppVeyor (Windows CI) for each PR and merge.
+* Issue #257: Set CKA_DECRYPT/CKA_ENCRYPT flags on key import to true.
+ (Patch from Martin Domke)
+* Issue #261: Add support for libeaycompat lib for FIPS on Windows.
+ (Patch from Matt Hauck)
+* Issue #262: Support importing ECDSA P-521 in softhsm-util.
+* Issue #276: Support for Botan 2.0.
+* Issue #279: Editorial changes from Mountain Lion to Sierra.
+ (Patch from Mike Neumann)
+* Issue #283: More detailed error messages when initializing SoftHSM.
+* Issue #285: Support for LibreSSL.
+ (Patch from Alon Bar-Lev)
+* Issue #286: Update .gitignore.
+ (Patch from Alon Bar-Lev)
+* Issue #291: Change to enable builds and reports on new Jenkinks
+ environment.
+* Issue #293: Detect cppunit in autoconf.
+ (Patch from Alon Bar-Lev)
+* Issue #309: CKO_CERTIFICATE and CKO_PUBLIC_KEY now defaults to
+ CKA_PRIVATE=false.
+* Issue #314: Update README with information about logging.
+* Issue #330: Adjust log levels for failing to enumerate object store.
+ (Patch from Nikos Mavrogiannopoulos)
+
+Bugfixes:
+* Issue #216: Better handling of CRYPTO_set_locking_callback() for OpenSSL.
+* Issue #265: Fix deriving shared secret with ECC.
+* Issue #280: HMAC with sizes less than L bytes is strongly discouraged.
+ Set a lower bound equal to L bytes in ulMinKeySize and check it when
+ initializing the operation.
+* Issue #281: Fix test of p11 shared library.
+ (Patch from Lars Silvén)
+* Issue #289: Minor fix of 'EVP_CipherFinal_ex'.
+ (Patch from Viktor Tarasov)
+* Issue #297: Fix build with cppunit.
+ (Patch from Ludovic Rousseau)
+* Issue #302: Export PKCS#11 symbols from the library.
+ (Patch from Ludovic Rousseau)
+* Issue #305: Zero pad key to fit the block in CKM_AES_KEY_WRAP.
+* Issue #313: Detecting CppUnit when using Macports.
+ (Patch from mouse07410)
+
+
+SoftHSM 2.2.0 - 2016-12-05
+
+* Issue #143: Delete a token using softhsm2-util.
+* Issue #185: Change access mode bits for /var/lib/softhsm/tokens/
+ to 1777. All users can now create tokens, but only access their own.
+ (Patch from Rick van Rein)
+* Issue #186: Reinitializing a token will now keep the token, but all
+ token objects are deleted, the user PIN is removed and the token
+ label is updated.
+* Issue #190: Support for OpenSSL 1.1.0.
+* Issue #198: Calling C_GetSlotList with NULL_PTR will make sure that
+ there is always a slot with an uninitialized token available.
+* Issue #199: The token serial number will be used when setting the slot
+ number. The serial number is set after the token has been initialized.
+ (Patch from Lars Silvén)
+* Issue #203: Update the command utils to use the token label or serial
+ to find the token and its slot number.
+* Issue #209: Possibility to test other PKCS#11 implementations with the
+ CppUnit test.
+ (Patch from Lars Silvén)
+* Issue #223: Mark public key as non private by default.
+ (Patch from Nikos Mavrogiannopoulos)
+* Issue #230: Install p11-kit module, to disable use --disable-p11-kit.
+ (Patch from David Woodhouse)
+* Issue #237: Add windows continuous integration build.
+ (Patch from Peter Polačko)
+
+Bugfixes:
+* Issue #201: Missing new source file and test configuration in the
+ Windows build project.
+* Issue #205: ECDSA P-521 support for OpenSSL and better test coverage.
+* Issue #207: Fix segmentation faults in loadLibrary function.
+ (Patch from Jaroslav Imrich)
+* Issue #215: Update the Homebrew install notes for OSX.
+* Issue #218: Fix build warnings.
+* Issue #235: Add the libtool install command for OSX.
+ (Patch from Mark Wylde)
+* Issue #236: Use GetEnvironmentVariable instead of getenv on Windows.
+ (Patch from Jaroslav Imrich)
+* Issue #239: Crash on module unload with OpenSSL.
+ (Patch from David Woodhouse)
+* Issue #241: Added EXTRALIBS to Windows utils project.
+ (Patch from Peter Polačko)
+* Issue #250: C++11 not detected.
+* Issue #255: API changes in Botan 1.11.27.
+* Issue #260: Fix include guard to check WITH_FIPS.
+ (Patch from Matt Hauck)
+* Issue #268: p11test fails on 32-bit systems.
+* Issue #270: Build warning about "converting a string constant".
+* Issue #272: Fix C++11 check to look for unique_ptr.
+ (Patch from Matt Hauck)
+
+
+SoftHSM 2.1.0 - 2016-03-14
+
+* Issue #136: Improved guide and build scripts for Windows.
+ (Thanks to Jaroslav Imrich)
+* Issue #144: The password prompt in softhsm2-util can now be
+ interrupted (ctrl-c).
+* Issue #166: Add slots.removable config option.
+ (Patch from Sumit Bose)
+* Issue #180: Windows configure script improvements.
+ (Patch from Arnaud Grandville)
+
+Bugfixes:
+* Issue #128: Prioritize the return values in C_GetAttributeValue.
+ (Patch from Nicholas Wilson)
+* Issue #129: Fix errors reported by Visual Studio 2015.
+ (Patch from Jaroslav Imrich)
+* Issue #132: Handle the CKA_CHECK_VALUE correctly for certificates
+ and symmetric key objects.
+* Issue #154: Fix the Windows build and destruction order of objects.
+ (Patch from Arnaud Grandville)
+* Issue #162: Not possible to create certificate objects containing
+ CKA_CERTIFICATE_CATEGORY, CKA_NAME_HASH_ALGORITHM, or
+ CKA_JAVA_MIDP_SECURITY_DOMAIN.
+* Issue #163: Do not attempt decryption of empty byte strings.
+ (Patch from Michal Kepien)
+* Issue #165: Minor changes after a PVS-Studio code analysis, and
+ C_EncryptUpdate crash if no ciphered data is produced.
+ (Patch from Arnaud Grandville)
+* Issue #169: One-byte buffer overflow in call to EVP_DecryptUpdate.
+* Issue #171: Problem while closing library that is initialized but
+ improperly finalized.
+* Issue #173: Adjust return values for the template parsing.
+* Issue #174: C_DeriveKey() error with leading zero bytes.
+* Issue #177: CKA_NEVER_EXTRACTABLE set to CK_FALSE on objects
+ created with C_CreateObject.
+* Issue #182: Resolve compiler warning.
+ (Patch from Josh Datko)
+* Issue #184: Stop discarding the global OpenSSL libcrypto state.
+ (Patch from Michal Trojnara)
+* SOFTHSM-123: Fix library cleanup on BSD.
+
+
+SoftHSM 2.0.0 - 2015-07-17
+
+* SOFTHSM-121: Test cases for C_DecryptUpdate/C_DecryptFinal.
+* Support C_DecryptUpdate/C_DecryptFinal for symmetric algorithms.
+ (Patch from Thomas Calderon)
+
+Bugfixes:
+* SOFTHSM-120: Segfault after renaming variables.
+
+
+SoftHSM 2.0.0b3 - 2015-04-17
+
+* SOFTHSM-113: Support for Botan 1.11.15
+* SOFTHSM-119: softhsm2-util: Support ECDSA key import
+ (Patch from Magnus Ahltorp)
+* SUPPORT-139: Support deriving generic secrets, DES, DES2, DES3, and AES.
+ Using DH, ECDH or symmetric encryption.
+
+Bugfixes:
+* SOFTHSM-108: A marked as trusted certificate cannot be imported.
+* SOFTHSM-109: Unused parameter and variable warnings.
+* SOFTHSM-110: subdir-objects warnings from autoreconf.
+* SOFTHSM-111: Include FIPS-NOTES.md in dist.
+* SOFTHSM-112: CKM_AES_KEY_WRAP* conflict in pkcs11.h.
+* SOFTHSM-114: Fix memory leak in a test script.
+* SOFTHSM-115: Fix static analysis warnings.
+* SUPPORT-154: A marked as non-modifiable object cannot be generated.
+* SUPPORT-155: auto_ptr is deprecated in C++11, use unique_ptr.
+* SUPPORT-157: Derived secrets were truncated after encryption and
+ could thus not be decrypted.
+* Mutex should call MutexFactory wrapper functions.
+ (Patch from Jerry Lundström)
+* Return detailed error message to loadLibrary().
+ (Patch from Petr Spacek)
+
+
+SoftHSM 2.0.0b2 - 2014-12-28
+
+* SOFTHSM-50: OpenSSL FIPS support.
+* SOFTHSM-64: Updated build script for Windows.
+* SOFTHSM-100: Use --free with softhsm2-util to initialize the first
+ free token.
+* SOFTHSM-103: Allow runtime configuration of log level.
+* SOFTHSM-107: Support for CKM_<symcipher>_CBC_PAD.
+* Add support for CKM_RSA_PKCS_OAEP key un/wrapping.
+ (Patch from Petr Spacek)
+* Use OpenSSL EVP interface for AES key wrapping.
+ (Patch from Petr Spacek)
+* Allow reading configuration file from user's home directory.
+ (Patch from Nikos Mavrogiannopoulos)
+
+Bugfixes:
+* SOFTHSM-102: C_DeriveKey() uses OBJECT_OP_GENERATE.
+* Coverity found a number of issues.
+
+
+SoftHSM 2.0.0b1 - 2014-09-10
+
+* SOFTHSM-84: Check that all mandatory attributes are given during
+ the creation process.
+* SOFTHSM-92: Enable -fvisibility=hidden on per default
+* SUPPORT-137: Implement C_EncryptUpdate and C_EncryptFinal
+ (Patch from Martin Paljak)
+* Add support for CKM_RSA_PKCS key un/wrapping
+ (Patch from Petr Spacek)
+
+Bugfixes:
+* SOFTHSM-66: Attribute handling when using multiple threads
+* SOFTHSM-93: Invalid C++ object recycling.
+* SOFTHSM-95: umask affecting the calling application.
+* SOFTHSM-97: Check if Botan has already been initialized.
+* SOFTHSM-98: Handle mandatory attributes for DSA, DH, and ECDSA
+ correctly.
+* SOFTHSM-99: Binary encoding of GOST values.
+* SUPPORT-136: softhsm2-keyconv creates files with sensitive material
+ in insecure way.
+
+
+SoftHSM 2.0.0a2 - 2014-03-25
+
+* SOFTHSM-68: Display a better configure message when there is a
+ version of Botan with a broken ECC/GOST/OID implementation.
+* SOFTHSM-70: Improved handling of the database backend.
+* SOFTHSM-71: Supporting Botan 1.11.
+* SOFTHSM-76: Do not generate RSA keys smaller than 1024 bit when
+ using the Botan crypto backend.
+* SOFTHSM-83: Support CKA_VALUE_BITS for CKK_DH private key object.
+* SOFTHSM-85: Rename libsofthsm.so to libsofthsm2.so and prefix the
+ command line utilties with softhsm2-.
+* SOFTHSM-89: Use constants and not strings for signaling algorithms.
+* SUPPORT-129: Possible to use an empty template in C_GenerateKey.
+ The class and key type are inherited from the generation mechanism.
+ Some mechanisms do however require a length attribute. [SOFTHSM-88]
+* SUPPORT-131: Support RSA-PSS using SHA1, SHA224, SHA256, SHA384,
+ or SHA512. [SOFTHSM-87]
+
+Bugfixes:
+* SOFTHSM-39: Fix 64 bit build on sparc sun4v.
+* SOFTHSM-69: GOST did not work when you disabled ECC.
+* SOFTHSM-78: Correct the attribute checks for a number of objects.
+* SOFTHSM-80: Prevent segfault in OpenSSL GOST HMAC code.
+* SOFTHSM-91: Fix a warning from static code analysis.
+* Fixed a number of memory leaks.
+
+
+SoftHSM 2.0.0a1 - 2014-02-10
+
+This is the first alpha release of SoftHSMv2. It focuses on a higher
+level of security by encrypting sensitive information and using
+unswappable memory. There is also a more generalized crypto backend,
+where you can use Botan or OpenSSL.
diff --git a/SoftHSMv2/OSX-NOTES.md b/SoftHSMv2/OSX-NOTES.md
new file mode 100644
index 0000000..f1c7ee2
--- /dev/null
+++ b/SoftHSMv2/OSX-NOTES.md
@@ -0,0 +1,182 @@
+# Building SoftHSMv2 on macOS 10.12.3 (Sierra)
+
+This document contains instructions for building SoftHSMv2 from the command
+line on macOS 10.12.3.
+
+This may work for other versions of OS X/macOS, but this has not been verified.
+
+## Command Line Tools
+
+We assume that XCode has been installed. To find out where Xcode keeps the C++
+compiler type the following at the command line:
+
+ $ xcode-select --print-path
+ /Applications/Xcode.app/Contents/Developer
+
+The gcc compiler in this case can be found at
+/Applications/Xcode.app/Contents/Developer/usr/bin/gcc
+
+Alternatively if you don't want to install XCode you could install command line
+tools for macOS that can be downloaded from Apple.
+
+e.g. currently the following package for the Sierra release of macOS is
+available for download.
+
+ Command_Line_Tools_macOS_10.12_for_Xcode_8.2.dmg
+
+This dmg file is ~150MB but it is at least orders of magnitude smaller than
+installing all of XCode.
+
+## Homebrew
+
+The libraries that come as part of macOS are rather old. We need to use more
+recent versions of these libraries to avoid unexpected failures during building
+and running.
+
+There is a community supported command line package manager for installing the
+dependencies we need. It's called homebrew. First we'll need to install it as
+follows:
+
+ $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+
+Now we need to install some dependencies
+
+ $ brew install automake
+ $ brew install pkg-config
+ $ brew install openssl
+ $ brew install sqlite
+ $ brew install cppunit
+ $ brew install libtool
+
+openssl, sqlite, and libtool are pre-installed on the system. The versions downloaded
+by brew are stored in an alternative location under /usr/local
+
+The only brew warning of note is for libtool:
+
+ ==> Caveats
+ In order to prevent conflicts with Apple's own libtool we have prepended a "g"
+ so, you have instead: glibtool and glibtoolize.
+
+Note: gblitoolize seems to be found in the configuration step below just fine. It's unclear
+if glibtool is used since autogen.sh generates its own libtool script that is used by make.
+
+During configure, the paths to the newly installed libraries need to be passed
+in so configure can actually find the libraries. We'll show how to do that
+later.
+
+## Cloning SoftHSMv2
+
+We now need to clone SoftHSMv2 from github.
+
+ $ git clone https://github.com/opendnssec/SoftHSMv2.git
+ $ cd SoftHSMv2
+
+## Configuring the build
+
+Start by installing autoconf in the source directory by executing the
+autogen.sh script.
+
+ $ sh ./autogen.sh
+
+If all went well a configure script should have been generated. To find out the
+options available for building issue the following command:
+
+ $ ./configure --help
+
+In the example below I will enable the optional token object store database
+backend.
+
+ $ ./configure --with-objectstore-backend-db \
+ --with-openssl=/usr/local/opt/openssl \
+ --with-sqlite3=/usr/local/opt/sqlite
+
+Now if for some reason the compilers are not found, do the following at the
+command line.
+
+ $ export CC="xcrun gcc"
+ $ export CPP="xcrun cpp"
+ $ export CXX="xcrun g++"
+ $ ./configure --with-objectstore-backend-db \
+ --with-openssl=/usr/local/opt/openssl \
+ --with-sqlite3=/usr/local/opt/sqlite
+
+By exporting these environment variables we are instructing configure to use
+the compilers stored inside the installed XCode.app.
+
+## Building and Testing SoftHSMv2
+
+Now we can build SoftHSMv2 by just executing make.
+
+ $ make
+
+And we can check that it works by running all tests.
+
+ $ make check
+
+To try a specific test, e.g. to check just the PKCS#11 test cases use the
+following make command:
+
+ $ make -C src/lib/test check
+
+Then change src/lib/test/softhsm2.conf so it contains the following lines.
+
+ # SoftHSM v2 configuration file
+ directories.tokendir = ./tokens
+ objectstore.backend = db
+ log.level = INFO
+ slots.removable = false
+
+Then change src/lib/test/softhsm2-alt.conf so it contains the following lines.
+
+ # SoftHSM v2 configuration file
+ directories.tokendir = ./tokens
+ objectstore.backend = db
+ log.level = INFO
+ slots.removable = true
+
+We are now ready to run the tests again.
+
+ $ make -C src/lib/test check
+
+Because the object store backend was changed from file to db we have used
+sqlite for storing the token objects. Verify this by looking in the sub-folders
+of src/lib/test/tokens There you should find a database file named sqlite3.db
+
+## Performance
+
+The file backend currently exhibits the best performance. It is normally at
+least twice as fast as the database backend.
+
+The idea behind storing token objects in a database is that it has advantages
+when a large number (> 100K) of keys are stored in a token. A database allows
+for selectively querying and loading in only a subset of the keys into memory.
+The file based storage backend reads in the complete contents of the token.
+Also because the database is only a single file, we should not hit any system
+limitations w.r.t. the number of files that can be stored in a file system.
+
+The database backend uses transactions to write changes to the token database.
+For modifiable attributes this will require a round trip to the database every
+time an attribute has been read as another process may have modified the given
+attribute.
+
+The database backend uses approximately 20% less memory because it will only
+load in object attributes on demand. For non-mutable attributes that is not a
+problem because once an object with its attributes is created those attributes
+won't change. On the other hand the mutable attributes of the object are always
+read when the object is accessed, making it slower because this will require a
+roundtrip to the database for every mutable attribute. Note that most
+attributes are non-mutable and especially the key material is non-mutable. So
+once this (encrypted !) material has been read into memory it will remain
+cached (encrypted !).
+
+Currently the query functionality for only retrieving a subset of the objects
+is not yet implemented. Therefore the database solution has no advantages
+w.r.t. the file based solution for large number of files other than the 20%
+less memory usage mentioned before.
+
+For applications that need the highest speed possible and only read/use the
+token, a solution would be to copy the whole of the token database to a
+ramdisk. This should only be used when the application doesn't modify the
+token, because a power-cycle of the host will wipe out the ramdisk.
+
+3-January-2017
diff --git a/SoftHSMv2/README.md b/SoftHSMv2/README.md
new file mode 100644
index 0000000..c8230e8
--- /dev/null
+++ b/SoftHSMv2/README.md
@@ -0,0 +1,149 @@
+# SoftHSM version 2
+
+SoftHSM is part of the OpenDNSSEC project. Read more at www.opendnssec.org.
+
+[![Travis Build Status](https://api.travis-ci.org/opendnssec/SoftHSMv2.png)](https://travis-ci.org/opendnssec/SoftHSMv2)
+[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/opendnssec/SoftHSMv2?svg=true)](https://ci.appveyor.com/project/opendnssec/softhsmv2)
+
+## Introduction
+
+OpenDNSSEC handles and stores its cryptographic keys via the PKCS#11 interface.
+This interface specifies how to communicate with cryptographic devices such as
+HSM:s (Hardware Security Modules) and smart cards. The purpose of these devices
+is, among others, to generate cryptographic keys and sign information without
+revealing private-key material to the outside world. They are often designed to
+perform well on these specific tasks compared to ordinary processes in a normal
+computer.
+
+A potential problem with the use of the PKCS#11 interface is that it might
+limit the wide spread use of OpenDNSSEC, since a potential user might not be
+willing to invest in a new hardware device. To counter this effect, OpenDNSSEC
+is providing a software implementation of a generic cryptographic device with a
+PKCS#11 interface, the SoftHSM. SoftHSM is designed to meet the requirements of
+OpenDNSSEC, but can also work together with other cryptographic products
+because of the PKCS#11 interface.
+
+## Developers
+
+- Rickard Bellgrim (Knowit Secure AB, www.knowitgroup.com)
+- Francis Dupont (ISC, www.isc.org)
+- René Post (XPT Software and Consulting, www.xpt.nl)
+- Roland van Rijswijk (SURFnet bv, www.surfnet.nl)
+
+## Dependencies
+
+SoftHSM depends on a cryptographic library, Botan or OpenSSL.
+Minimum required versions:
+
+- Botan 1.10.0
+- OpenSSL 1.0.0
+
+If you are using Botan, make sure that it has support for GNU MP (--with-gnump).
+This will improve the performance when doing public key operations.
+
+The GNU Autotools are also required for building the software.
+
+There is a migration tool for converting token databases from SoftHSMv1 into
+the new type of tokens. If this tool is built, then SQLite3 is required (>=
+3.4.2).
+
+## Installation
+
+### Configure
+
+Configure the installation/compilation scripts:
+
+ sh ./autogen.sh
+ ./configure
+
+Options:
+
+ --disable-non-paged-memory
+ Disable non-paged memory for secure storage
+ (default enabled)
+ --disable-ecc Disable support for ECC (default enabled)
+ --disable-gost Disable support for GOST (default enabled)
+ --disable-visibility Disable hidden visibilty link mode [enabled]
+ --with-crypto-backend Select crypto backend (openssl|botan)
+ --with-openssl=PATH Specify prefix of path of OpenSSL
+ --with-botan=PATH Specify prefix of path of Botan
+ --with-migrate Build the migration tool. Used when migrating
+ a SoftHSM v1 token database. Requires SQLite3
+ --with-objectstore-backend-db
+ Build with database object store (SQLite3)
+ --with-sqlite3=PATH Specify prefix of path of SQLite3
+ --disable-p11-kit Disable p11-kit integration (default enabled)
+ --with-p11-kit=PATH Specify install path of the p11-kit module, will
+ override path given by pkg-config
+
+For more options:
+
+ ./configure --help
+
+
+### Compile
+
+Compile the source code using the following command:
+
+ make
+
+### Install Library
+
+Install the library using the follow command:
+
+ sudo make install
+
+### Configure
+
+The default location of the config file is /etc/softhsm2.conf. This location
+can be change by setting the environment variable.
+
+ export SOFTHSM2_CONF=/home/user/config.file
+
+Details on the configuration can be found in "man softhsm2.conf".
+
+Create the token directory you defined in your config file:
+
+ mkdir <token_dir>
+
+### Initialize Tokens
+
+Use either softhsm2-util or the PKCS#11 interface. The SO PIN can e.g. be used
+to re-initialize the token and the user PIN is handed out to the application so
+it can interact with the token.
+
+ softhsm2-util --init-token --slot 0 --label "My token 1"
+
+Type in SO PIN and user PIN. Once a token has been initialized, more slots will
+be added automatically with a new uninitialized token.
+
+Initialized tokens will be reassigned to another slot (based on the token
+serial number). It is recommended to find and interact with the token by
+searching for the token label or serial number in the slot list / token info.
+
+### Link
+
+Link to this library and use the PKCS#11 interface.
+
+
+## Backup
+
+All of the tokens and their objects are stored in the location given by
+softhsm2.conf. Backup can thus be done as a regular file copy.
+
+
+## Log information
+
+Log information is sent to syslog or the Windows event log and the log
+level is set in the configuration file. Each log event is prepended with
+the source file name and line number.
+
+
+## Building from the repository
+
+If the code is downloaded directly from the code repository, you have to
+prepare the configuration scripts before continuing with the real README.
+
+1. You need to install automake, autoconf, libtool, etc.
+2. Run the command 'sh autogen.sh'
+3. Continue reading this README.
diff --git a/SoftHSMv2/WIN32-NOTES.md b/SoftHSMv2/WIN32-NOTES.md
new file mode 100644
index 0000000..a3ce7ab
--- /dev/null
+++ b/SoftHSMv2/WIN32-NOTES.md
@@ -0,0 +1,311 @@
+# Building SoftHSM2 for Windows
+
+This document describes process of building both 32-bit and 64-bit versions of SoftHSM2 on 64-bit Windows 8.1 machine.
+Either OpenSSL or Botan can be used as the crypto backend.
+
+## Required software
+
+- [Visual Studio](https://www.visualstudio.com/products/visual-studio-community-vs) (2015 Community)
+- [GNU Privacy Guard for Windows](http://www.gpg4win.org/) (2.2.5)
+- [7-zip](http://www.7-zip.org/) (9.20)
+- [Strawberry Perl](http://strawberryperl.com/) (5.22.0.1)
+- [The Netwide Assembler](http://www.nasm.us/) (2.11.08)
+- [Python](https://www.python.org/downloads/windows/) (3.4.2)
+
+## Prepare working directories
+
+ mkdir C:\build\bin\
+ mkdir C:\build\src\
+
+## Build OpenSSL 1.0.2d static library
+
+Download [OpenSSL 1.0.2d](http://openssl.org/source/openssl-1.0.2d.tar.gz) with [its signature](http://openssl.org/source/openssl-1.0.2d.tar.gz.asc) into `C:\build\src\` directory and verify signature of the downloaded archive:
+
+ cd C:\build\src\
+ gpg --keyserver pgp.mit.edu --recv-keys 0E604491
+ gpg --verify openssl-1.0.2d.tar.gz.asc openssl-1.0.2d.tar.gz
+
+### 32-bit
+
+Extract archive `openssl-1.0.2d.tar.gz` into `C:\build\src\openssl-1.0.2d-x86` directory:
+
+ cd C:\build\src\
+ "C:\Program Files\7-Zip\7z" x openssl-1.0.2d.tar.gz
+ "C:\Program Files\7-Zip\7z" x openssl-1.0.2d.tar
+ rename openssl-1.0.2d openssl-1.0.2d-x86
+ del openssl-1.0.2d.tar*
+
+In a **new command line window** build OpenSSL and install it into `C:\build\bin\openssl-1.0.2d-x86` directory:
+
+ cd C:\build\src\openssl-1.0.2d-x86
+ set PATH=%PATH%;C:\nasm
+ "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
+ perl Configure VC-WIN32 --prefix=C:\build\bin\openssl-1.0.2d-x86 enable-static-engine
+ ms\do_nasm
+ nmake /f ms\nt.mak
+ nmake /f ms\nt.mak test
+ nmake /f ms\nt.mak install
+
+## 64-bit
+
+Extract archive `openssl-1.0.2d.tar.gz` into `C:\build\src\openssl-1.0.2d-x64` directory:
+
+ cd C:\build\src\
+ "C:\Program Files\7-Zip\7z" x openssl-1.0.2d.tar.gz
+ "C:\Program Files\7-Zip\7z" x openssl-1.0.2d.tar
+ rename openssl-1.0.2d openssl-1.0.2d-x64
+ del openssl-1.0.2d.tar*
+
+In a **new command line window** build OpenSSL and install it into `C:\build\bin\openssl-1.0.2d-x64` directory:
+
+ cd C:\build\src\openssl-1.0.2d-x64
+ set PATH=%PATH%;C:\nasm
+ "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
+ perl Configure VC-WIN64A --prefix=C:\build\bin\openssl-1.0.2d-x64 enable-static-engine
+ ms\do_win64a
+ nmake /f ms\nt.mak
+ nmake /f ms\nt.mak test
+ nmake /f ms\nt.mak install
+
+## Build OpenSSL 1.1.0a static library
+
+Download [OpenSSL 1.1.0a](https://www.openssl.org/source/openssl-1.1.0a.tar.gz) with [its signature](https://www.openssl.org/source/openssl-1.1.0a.tar.gz.asc) into `C:\build\src\` directory and verify signature of the downloaded archive:
+
+ cd C:\build\src\
+ gpg --keyserver pgp.mit.edu --recv-keys 0E604491
+ gpg --verify openssl-1.1.0a.tar.gz.asc openssl-1.1.0a.tar.gz
+
+### 32-bit
+
+Extract archive `openssl-1.1.0a.tar.gz` into `C:\build\src\openssl-1.1.0a-x86` directory:
+
+ cd C:\build\src\
+ "C:\Program Files\7-Zip\7z" x openssl-1.1.0a.tar.gz
+ "C:\Program Files\7-Zip\7z" x openssl-1.1.0a.tar
+ rename openssl-1.1.0a openssl-1.1.0a-x86
+ del openssl-1.1.0a.tar*
+
+In a **new command line window** build OpenSSL and install it into `C:\build\bin\openssl-1.1.0a-x86` directory:
+
+ cd C:\build\src\openssl-1.1.0a-x86
+ set PATH=%PATH%;C:\nasm
+ "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
+ perl Configure VC-WIN32 --prefix=C:\build\bin\openssl-1.1.0a-x86 --openssldir=C:\build\bin\openssl-1.1.0a-x86\ssl no-shared
+ nmake
+ nmake test
+ nmake install
+
+## 64-bit
+
+Extract archive `openssl-1.1.0a.tar.gz` into `C:\build\src\openssl-1.1.0a-x64` directory:
+
+ cd C:\build\src\
+ "C:\Program Files\7-Zip\7z" x openssl-1.1.0a.tar.gz
+ "C:\Program Files\7-Zip\7z" x openssl-1.1.0a.tar
+ rename openssl-1.1.0a openssl-1.1.0a-x64
+ del openssl-1.1.0a.tar*
+
+In a **new command line window** build OpenSSL and install it into `C:\build\bin\openssl-1.1.0a-x64` directory:
+
+ cd C:\build\src\openssl-1.1.0a-x64
+ set PATH=%PATH%;C:\nasm
+ "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
+ perl Configure VC-WIN64A --prefix=C:\build\bin\openssl-1.1.0a-x64 --openssldir=C:\build\bin\openssl-1.1.0a-x64\ssl no-shared
+ nmake
+ nmake test
+ nmake install
+
+## Build Botan 1.10.10
+
+Download [Botan 1.10.10](http://botan.randombit.net/releases/Botan-1.10.10.tgz) with [its signature](http://botan.randombit.net/releases/Botan-1.10.10.tgz.asc) into `C:\build\src\` directory and verify signature of the downloaded archive:
+
+ cd C:\build\src\
+ gpg --keyserver pgp.mit.edu --recv-keys EFBADFBC
+ gpg --verify Botan-1.10.10.tgz.asc Botan-1.10.10.tgz
+
+### 32-bit
+
+Extract archive `Botan-1.10.10.tgz` into `C:\build\src\botan-1.10.10-x86` directory:
+
+ cd C:\build\src\
+ rename Botan-1.10.10.tgz Botan-1.10.10.tar.gz
+ "C:\Program Files\7-Zip\7z" x Botan-1.10.10.tar.gz
+ "C:\Program Files\7-Zip\7z" x Botan-1.10.10.tgz
+ rename Botan-1.10.10 botan-1.10.10-x86
+ del Botan-1.10.10.t*
+
+In a **new command line window as admin** build Botan and install it into `C:\build\bin\botan-1.10.10-x86` directory. Need to run the configure script as admin so it can link objects:
+
+ cd C:\build\src\botan-1.10.10-x86
+ "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
+ python configure.py --cc=msvc --cpu=x86 --prefix=C:\build\bin\botan-1.10.10-x86
+ nmake
+ nmake check
+ check.exe --validate
+ nmake install
+
+## 64-bit
+
+Extract archive `Botan-1.10.10.tgz` into `C:\build\src\botan-1.10.10-x64` directory:
+
+ cd C:\build\src\
+ rename Botan-1.10.10.tgz Botan-1.10.10.tar.gz
+ "C:\Program Files\7-Zip\7z" x Botan-1.10.10.tar.gz
+ "C:\Program Files\7-Zip\7z" x Botan-1.10.10.tgz
+ rename Botan-1.10.10 botan-1.10.10-x64
+ del Botan-1.10.10.t*
+
+In a **new command line window as admin** build Botan and install it into `C:\build\bin\botan-1.10.10-x64` directory. Need to run the configure script as admin so it can link objects:
+
+ cd C:\build\src\botan-1.10.10-x64
+ "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
+ python configure.py --cc=msvc --cpu=x64 --prefix=C:\build\bin\botan-1.10.10-x64
+ nmake
+ nmake check
+ check.exe --validate
+ nmake install
+
+## Build CppUnit 1.13.2 unicode library
+
+Download [CppUnit 1.13.2](http://dev-www.libreoffice.org/src/cppunit-1.13.2.tar.gz) into `C:\build\src\` directory.
+
+### 32-bit
+
+Extract archive `cppunit-1.13.2.tar.gz` into `C:\build\src\cppunit-1.13.2-x86` directory:
+
+ cd C:\build\src\
+ "C:\Program Files\7-Zip\7z" x cppunit-1.13.2.tar.gz
+ "C:\Program Files\7-Zip\7z" x cppunit-1.13.2.tar
+ rename cppunit-1.13.2 cppunit-1.13.2-x86
+ del cppunit-1.13.2.tar*
+
+Open solution `C:\build\src\cppunit-1.13.2-x86\src\CppUnitLibraries2010.sln` in Visual Studio and rebuild the source with `Release Unicode\Win32` solution configuration.
+
+(If you want to compile SoftHSM with static CRT, then you must also compile CppUnit with static CRT. Change "Runtime Library" to "Multi-threaded (/MT)" in the project "cppunit". This will create some build errors for project "TestRunner", but that can be ignored since it is not used by SoftHSM.)
+
+Copy the results into `C:\build\bin\cppunit-1.13.2-x86` directory:
+
+ mkdir C:\build\bin\cppunit-1.13.2-x86\lib
+ xcopy C:\build\src\cppunit-1.13.2-x86\lib C:\build\bin\cppunit-1.13.2-x86\lib /E
+ mkdir C:\build\bin\cppunit-1.13.2-x86\include
+ xcopy C:\build\src\cppunit-1.13.2-x86\include C:\build\bin\cppunit-1.13.2-x86\include /E
+
+### 64-bit
+
+Extract archive `cppunit-1.13.2.tar.gz` into `C:\build\src\cppunit-1.13.2-x64` directory:
+
+ cd C:\build\src\
+ "C:\Program Files\7-Zip\7z" x cppunit-1.13.2.tar.gz
+ "C:\Program Files\7-Zip\7z" x cppunit-1.13.2.tar
+ rename cppunit-1.13.2 cppunit-1.13.2-x64
+ del cppunit-1.13.2.tar*
+
+Open solution `C:\build\src\cppunit-1.13.2-x64\src\CppUnitLibraries2010.sln` in Visual Studio and rebuild the source with `Release Unicode\x64` solution configuration.
+
+(If you want to compile SoftHSM with static CRT, then you must also compile CppUnit with static CRT. Change "Runtime Library" to "Multi-threaded (/MT)" in the project "cppunit". This will create some build errors for project "TestRunner", but that can be ignored since it is not used by SoftHSM.)
+
+Copy the results into `C:\build\bin\cppunit-1.13.2-x64` directory:
+
+ mkdir C:\build\bin\cppunit-1.13.2-x64\lib
+ xcopy C:\build\src\cppunit-1.13.2-x64\lib C:\build\bin\cppunit-1.13.2-x64\lib /E
+ mkdir C:\build\bin\cppunit-1.13.2-x64\include
+ xcopy C:\build\src\cppunit-1.13.2-x64\include C:\build\bin\cppunit-1.13.2-x64\include /E
+
+## Build SoftHSM
+
+Download the latest version of [SoftHSMv2](https://dist.opendnssec.org/source/) with its signature into `C:\build\src\` directory and verify signature of the downloaded archive:
+
+ cd C:\build\src\
+ gpg --keyserver pgp.mit.edu --recv-keys 4EE17CD2
+ gpg --verify softhsm-2.x.y.tar.gz.sig softhsm-2.x.y.tar.gz
+ "C:\Program Files\7-Zip\7z" x softhsm-2.x.y.tar.gz
+ "C:\Program Files\7-Zip\7z" x softhsm-2.x.y.tar
+ rename softhsm-2.x.y SoftHSMv2
+ del softhsm-2.x.y.tar*
+
+Or clone the source code from GitHub:
+
+ cd C:\build\src\
+ git clone https://github.com/opendnssec/SoftHSMv2.git
+
+### 32-bit
+
+Configure build process in a **new command line window**:
+
+ cd C:\build\src\SoftHSMv2\win32\
+ "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
+
+OpenSSL (OpenSSL GOST engine does not support OpenSSL 1.1.0) or Botan crypto backend:
+
+ python Configure.py disable-debug disable-gost with-crypto-backend=openssl with-openssl=C:\build\bin\openssl-1.1.0a-x86\ with-cppunit=C:\build\bin\cppunit-1.13.2-x86\
+ python Configure.py disable-debug with-crypto-backend=botan with-botan=C:\build\bin\botan-1.10.10-x86\ with-cppunit=C:\build\bin\cppunit-1.13.2-x86\
+
+(Add option enable-static-runtime if you want to compile with static CRT (/MT))
+
+Open solution `C:\build\src\SoftHSMv2\win32\softhsm2.sln` in Visual Studio and rebuild the source with `Release\Win32` solution configuration.
+
+Verify the build by running the test programs:
+
+ C:\build\src\SoftHSMv2\win32\Release\cryptotest.exe
+ C:\build\src\SoftHSMv2\win32\Release\datamgrtest.exe
+ C:\build\src\SoftHSMv2\win32\Release\handlemgrtest.exe
+ C:\build\src\SoftHSMv2\win32\Release\objstoretest.exe
+ C:\build\src\SoftHSMv2\win32\Release\p11test.exe
+ C:\build\src\SoftHSMv2\win32\Release\sessionmgrtest.exe
+ C:\build\src\SoftHSMv2\win32\Release\slotmgrtest.exe
+
+Copy the results into `C:\build\bin\SoftHSMv2-x86` directory:
+
+ mkdir C:\build\bin\SoftHSMv2-x86
+ mkdir C:\build\bin\SoftHSMv2-x86\tokens
+ copy C:\build\src\SoftHSMv2\win32\Release\softhsm2.dll C:\build\bin\SoftHSMv2-x86\
+ copy C:\build\src\SoftHSMv2\win32\Release\softhsm2-dump-file.exe C:\build\bin\SoftHSMv2-x86\
+ copy C:\build\src\SoftHSMv2\win32\Release\softhsm2-keyconv.exe C:\build\bin\SoftHSMv2-x86\
+ copy C:\build\src\SoftHSMv2\win32\Release\softhsm2-util.exe C:\build\bin\SoftHSMv2-x86\
+ copy C:\build\src\SoftHSMv2\src\lib\common\softhsm2.conf.in C:\build\bin\SoftHSMv2-x86\softhsm2.conf
+
+Replace `@softhsmtokendir@` with `C:\build\bin\SoftHSMv2-x86\tokens` in the file `C:\build\bin\SoftHSMv2-x86\softhsm2.conf`
+
+Set the environment variable SOFTHSM2_CONF to `C:\build\bin\SoftHSMv2-x86\softhsm2.conf`
+
+### 64-bit
+
+Configure build process in a **new command line window**:
+
+ cd C:\build\src\SoftHSMv2\win32\
+ "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
+
+OpenSSL (OpenSSL GOST engine does not support OpenSSL 1.1.0) or Botan crypto backend:
+
+ python Configure.py enable-64bit disable-debug disable-gost with-crypto-backend=openssl with-openssl=C:\build\bin\openssl-1.1.0a-x64\ with-cppunit=C:\build\bin\cppunit-1.13.2-x64\
+ python Configure.py enable-64bit disable-debug with-crypto-backend=botan with-botan=C:\build\bin\botan-1.10.10-x64\ with-cppunit=C:\build\bin\cppunit-1.13.2-x64\
+
+(Add option enable-static-runtime if you want to compile with static CRT (/MT))
+
+Open solution `C:\build\src\SoftHSMv2\win32\softhsm2.sln` in Visual Studio and rebuild the source with `Release\x64` solution configuration.
+
+Verify the build by running the test programs:
+
+ C:\build\src\SoftHSMv2\win32\x64\Release\cryptotest.exe
+ C:\build\src\SoftHSMv2\win32\x64\Release\datamgrtest.exe
+ C:\build\src\SoftHSMv2\win32\x64\Release\handlemgrtest.exe
+ C:\build\src\SoftHSMv2\win32\x64\Release\objstoretest.exe
+ C:\build\src\SoftHSMv2\win32\x64\Release\p11test.exe
+ C:\build\src\SoftHSMv2\win32\x64\Release\sessionmgrtest.exe
+ C:\build\src\SoftHSMv2\win32\x64\Release\slotmgrtest.exe
+
+Copy the results into `C:\build\bin\SoftHSMv2-x64` directory:
+
+ mkdir C:\build\bin\SoftHSMv2-x64
+ mkdir C:\build\bin\SoftHSMv2-x64\tokens
+ copy C:\build\src\SoftHSMv2\win32\x64\Release\softhsm2.dll C:\build\bin\SoftHSMv2-x64\
+ copy C:\build\src\SoftHSMv2\win32\x64\Release\softhsm2-dump-file.exe C:\build\bin\SoftHSMv2-x64\
+ copy C:\build\src\SoftHSMv2\win32\x64\Release\softhsm2-keyconv.exe C:\build\bin\SoftHSMv2-x64\
+ copy C:\build\src\SoftHSMv2\win32\x64\Release\softhsm2-util.exe C:\build\bin\SoftHSMv2-x64\
+ copy C:\build\src\SoftHSMv2\src\lib\common\softhsm2.conf.in C:\build\bin\SoftHSMv2-x64\softhsm2.conf
+
+Replace `@softhsmtokendir@` with `C:\build\bin\SoftHSMv2-x64\tokens` in the file `C:\build\bin\SoftHSMv2-x64\softhsm2.conf`
+
+Set the environment variable SOFTHSM2_CONF to `C:\build\bin\SoftHSMv2-x64\softhsm2.conf`
+
+## Continue reading in the README
diff --git a/SoftHSMv2/aes_wrap_key_with_pad/README b/SoftHSMv2/aes_wrap_key_with_pad/README
new file mode 100644
index 0000000..883cbf4
--- /dev/null
+++ b/SoftHSMv2/aes_wrap_key_with_pad/README
@@ -0,0 +1,7 @@
+Here are the patches to add advanced AES key wrap *with pad*, aka RFC 5649,
+to Botan (1.10, not 1.11 even it should be easy).
+PS: standardized (and approved) under the KWP name in NIST SP 800-38F.
+
+OpenSSL added support for RFC 5649 in commit
+d31fed73e25391cd71a0de488d88724db78f6f8a and it is waiting for nearest release.
+Some distributions backported the interface, e.g. Fedora and RHEL.
diff --git a/SoftHSMv2/aes_wrap_key_with_pad/botan-diff b/SoftHSMv2/aes_wrap_key_with_pad/botan-diff
new file mode 100644
index 0000000..bf03118
--- /dev/null
+++ b/SoftHSMv2/aes_wrap_key_with_pad/botan-diff
@@ -0,0 +1,340 @@
+--- src/constructs/rfc3394/rfc3394.h-dist 2013-11-10 17:06:11.000000000 +0100
++++ src/constructs/rfc3394/rfc3394.h 2013-12-22 02:14:50.000000000 +0100
+@@ -27,6 +27,13 @@
+ const SymmetricKey& kek,
+ Algorithm_Factory& af);
+
++/* overload with an extra initial value */
++
++SecureVector<byte> BOTAN_DLL rfc3394_keywrap(const MemoryRegion<byte>& key,
++ const byte iv[8],
++ const SymmetricKey& kek,
++ Algorithm_Factory& af);
++
+ /**
+ * Decrypt a key under a key encryption key using the algorithm
+ * described in RFC 3394
+@@ -40,6 +47,47 @@
+ const SymmetricKey& kek,
+ Algorithm_Factory& af);
+
++/* overload with an extra initial value */
++
++SecureVector<byte> BOTAN_DLL rfc3394_keyunwrap(const MemoryRegion<byte>& key,
++ const byte iv[8],
++ const SymmetricKey& kek,
++ Algorithm_Factory& af);
++
++/* overload with an extra initial value and integrity check value */
++
++SecureVector<byte> BOTAN_DLL rfc3394_keyunwrap(const MemoryRegion<byte>& key,
++ const byte iv[8],
++ byte icv[8],
++ const SymmetricKey& kek,
++ Algorithm_Factory& af);
++
++/**
++* Pad and encrypt a key under a key encryption key using the algorithm
++* described in RFC 5649
++*
++* @param key the plaintext key to encrypt
++* @param kek the key encryption key
++* @param af an algorithm factory
++* @return key encrypted under kek
++*/
++SecureVector<byte> BOTAN_DLL rfc5649_keywrap(const MemoryRegion<byte>& key,
++ const SymmetricKey& kek,
++ Algorithm_Factory& af);
++
++/**
++* Decrypt and unpad a key under a key encryption key using the algorithm
++* described in RFC 5649
++*
++* @param key the encrypted key to decrypt
++* @param kek the key encryption key
++* @param af an algorithm factory
++* @return key decrypted under kek
++*/
++SecureVector<byte> BOTAN_DLL rfc5649_keyunwrap(const MemoryRegion<byte>& key,
++ const SymmetricKey& kek,
++ Algorithm_Factory& af);
++
+ }
+
+ #endif
+--- src/constructs/rfc3394/rfc3394.cpp-dist 2013-11-10 17:06:11.000000000 +0100
++++ src/constructs/rfc3394/rfc3394.cpp 2013-12-22 03:46:13.000000000 +0100
+@@ -30,12 +30,35 @@
+ throw std::invalid_argument("Bad KEK length for NIST keywrap");
+ }
+
++BlockCipher* make_aesp(size_t keylength,
++ Algorithm_Factory& af)
++ {
++ if(keylength == 16)
++ return af.make_block_cipher("AES-128");
++ else if(keylength == 24)
++ return af.make_block_cipher("AES-192");
++ else if(keylength == 32)
++ return af.make_block_cipher("AES-256");
++ else
++ throw std::invalid_argument("Bad KEK length for NIST keywrap with pad");
++ }
+ }
+
+ SecureVector<byte> rfc3394_keywrap(const MemoryRegion<byte>& key,
+ const SymmetricKey& kek,
+ Algorithm_Factory& af)
+ {
++ byte iv[8];
++ for(size_t i = 0; i != 8; ++i)
++ iv[i] = 0xA6;
++ return rfc3394_keywrap(key, iv, kek, af);
++ }
++
++SecureVector<byte> rfc3394_keywrap(const MemoryRegion<byte>& key,
++ const byte iv[8],
++ const SymmetricKey& kek,
++ Algorithm_Factory& af)
++ {
+ if(key.size() % 8 != 0)
+ throw std::invalid_argument("Bad input key size for NIST key wrap");
+
+@@ -48,7 +71,7 @@
+ SecureVector<byte> A(16);
+
+ for(size_t i = 0; i != 8; ++i)
+- A[i] = 0xA6;
++ A[i] = iv[i];
+
+ copy_mem(&R[8], key.begin(), key.size());
+
+@@ -78,6 +101,29 @@
+ const SymmetricKey& kek,
+ Algorithm_Factory& af)
+ {
++ byte iv[8];
++ for(size_t i = 0; i != 8; ++i)
++ iv[i] = 0xA6;
++ return rfc3394_keyunwrap(key, iv, kek, af);
++ }
++
++SecureVector<byte> rfc3394_keyunwrap(const MemoryRegion<byte>& key,
++ const byte iv[8],
++ const SymmetricKey& kek,
++ Algorithm_Factory& af)
++ {
++ byte icv[8];
++ for(size_t i = 0; i != 8; ++i)
++ icv[i] = iv[i];
++ return rfc3394_keyunwrap(key, iv, icv, kek, af);
++ }
++
++SecureVector<byte> rfc3394_keyunwrap(const MemoryRegion<byte>& key,
++ const byte iv[8],
++ byte icv[8],
++ const SymmetricKey& kek,
++ Algorithm_Factory& af)
++ {
+ if(key.size() < 16 || key.size() % 8 != 0)
+ throw std::invalid_argument("Bad input key size for NIST key unwrap");
+
+@@ -113,10 +159,107 @@
+ }
+ }
+
+- if(load_be<u64bit>(&A[0], 0) != 0xA6A6A6A6A6A6A6A6)
+- throw Integrity_Failure("NIST key unwrap failed");
++ if(load_be<u64bit>(iv, 0) == load_be<u64bit>(icv, 0))
++ {
++ if(load_be<u64bit>(&A[0], 0) != load_be<u64bit>(iv, 0))
++ throw Integrity_Failure("NIST key unwrap failed");
++ }
++ else
++ store_be(load_be<u64bit>(&A[0], 0), icv);
+
+ return R;
+ }
+
++SecureVector<byte> rfc5649_keywrap(const MemoryRegion<byte>& key,
++ const SymmetricKey& kek,
++ Algorithm_Factory& af)
++ {
++ const size_t len = key.size() +
++ (key.size() % 8 == 0 ? 0 : (8 - key.size() % 8));
++
++ u32bit aivh = 0xA65959A6;
++ byte ivh[4] = { 0 };
++ store_be(aivh, ivh);
++ u32bit mli = key.size();
++ byte ivl[4] = { 0 };
++ store_be(mli, ivl);
++
++ if(len == 8)
++ {
++ std::auto_ptr<BlockCipher> aes(make_aesp(kek.length(), af));
++ aes->set_key(kek);
++
++ SecureVector<byte> buf(16);
++ copy_mem(&buf[0], ivh, 4);
++ copy_mem(&buf[4], ivl, 4);
++ copy_mem(&buf[8], key.begin(), key.size());
++
++ aes->encrypt(&buf[0]);
++
++ return buf;
++ }
++ else
++ {
++ MemoryVector<byte> buf(len);
++ copy_mem(&buf[0], key.begin(), key.size());
++ byte iv[8] = { 0 };
++ copy_mem(iv, ivh, 4);
++ copy_mem(&iv[4], ivl, 4);
++ return rfc3394_keywrap(buf, iv, kek, af);
++ }
++ }
++
++SecureVector<byte> rfc5649_keyunwrap(const MemoryRegion<byte>& key,
++ const SymmetricKey& kek,
++ Algorithm_Factory& af)
++ {
++ if(key.size() < 16 || key.size() % 8 != 0)
++ throw std::invalid_argument("Bad input key size for NIST key unwrap with pad");
++
++ byte iv[8] = { 0 };
++ SecureVector<byte> out;
++
++ if(key.size() == 16)
++ {
++ std::auto_ptr<BlockCipher> aes(make_aesp(kek.length(), af));
++ aes->set_key(kek);
++
++ SecureVector<byte> buf(key);
++
++ aes->decrypt(&buf[0]);
++
++ copy_mem(iv, buf.begin(), 8);
++ out.resize(8);
++ copy_mem(&out[0], &buf[8], 8);
++ }
++ else
++ {
++ byte dummy[8] = { 1 };
++ try
++ {
++ out = rfc3394_keyunwrap(key, dummy, iv, kek, af);
++ }
++ catch(...)
++ {
++ throw Integrity_Failure("NIST key unwrap with pad failed");
++ }
++ }
++
++ if(load_be<u32bit>(&iv[0], 0) != 0xA65959A6)
++ throw Integrity_Failure("NIST key unwrap with pad failed");
++
++ u32bit mli = load_be<u32bit>(iv, 1);
++ if(mli > out.size() || mli <= out.size() - 8)
++ throw Integrity_Failure("NIST key unwrap with pad failed");
++
++ size_t padlen = out.size() - mli;
++ byte zero[8] = { 0 };
++ clear_mem(zero, 8);
++ if(padlen && !same_mem(zero, &out[mli], padlen))
++ throw Integrity_Failure("NIST key unwrap with pad failed");
++
++ out.resize(mli);
++ return out;
++ }
++
+ }
+--- src/constructs/rfc3394/info.txt-dist 2013-11-10 17:06:11.000000000 +0100
++++ src/constructs/rfc3394/info.txt 2013-12-22 00:42:08.000000000 +0100
+@@ -1 +1,2 @@
+ define RFC3394_KEYWRAP
++define RFC5649_KEYWRAP
+--- checks/validate.cpp-dist 2013-11-10 17:06:11.000000000 +0100
++++ checks/validate.cpp 2013-12-22 02:15:12.000000000 +0100
+@@ -180,6 +180,68 @@
+ return ok;
+ }
+
++bool keywrap_withpad_test(const char* key_str,
++ const char* expected_str,
++ const char* kek_str)
++ {
++ std::cout << '.' << std::flush;
++
++ bool ok = true;
++
++#if defined(BOTAN_HAS_RFC5649_KEYWRAP)
++ try
++ {
++ SymmetricKey key(key_str);
++ SymmetricKey expected(expected_str);
++ SymmetricKey kek(kek_str);
++
++ Algorithm_Factory& af = global_state().algorithm_factory();
++
++ SecureVector<byte> enc = rfc5649_keywrap(key.bits_of(), kek, af);
++
++ if(enc != expected.bits_of())
++ {
++ std::cout << "NIST key wrap encryption failure: "
++ << hex_encode(enc) << " != " << hex_encode(expected.bits_of()) << "\n";
++ ok = false;
++ }
++
++ SecureVector<byte> dec = rfc5649_keyunwrap(expected.bits_of(), kek, af);
++
++ if(dec != key.bits_of())
++ {
++ std::cout << "NIST key wrap decryption failure: "
++ << hex_encode(dec) << " != " << hex_encode(key.bits_of()) << "\n";
++ ok = false;
++ }
++ }
++ catch(std::exception& e)
++ {
++ std::cout << e.what() << "\n";
++ }
++#endif
++
++ return ok;
++ }
++
++bool test_keywrap_withpad()
++ {
++ std::cout << "Testing NIST keywrap with pad: " << std::flush;
++
++ bool ok = true;
++
++ ok &= keywrap_withpad_test("C37B7E6492584340BED12207808941155068F738",
++ "138BDEAA9B8FA7FC61F97742E72248EE5AE6AE5360D1AE6A5F54F373FA543B6A",
++ "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8");
++
++ ok &= keywrap_withpad_test("466f7250617369",
++ "AFBEB0F07DFBF5419200F2CCB50BB24F",
++ "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8");
++
++ std::cout << "\n";
++ return ok;
++ }
++
+ bool test_bcrypt(RandomNumberGenerator& rng)
+ {
+ #if defined(BOTAN_HAS_BCRYPT)
+@@ -410,6 +472,12 @@
+ errors++;
+ }
+
++ if(should_pass && !test_keywrap_withpad())
++ {
++ std::cout << "NIST keywrap with pad tests failed" << std::endl;
++ errors++;
++ }
++
+ if(should_pass && !test_cryptobox(rng))
+ {
+ std::cout << "Cryptobox tests failed" << std::endl;
diff --git a/SoftHSMv2/autogen.sh b/SoftHSMv2/autogen.sh
new file mode 100644
index 0000000..01db361
--- /dev/null
+++ b/SoftHSMv2/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+autoreconf --install --force
diff --git a/SoftHSMv2/configure.ac b/SoftHSMv2/configure.ac
new file mode 100644
index 0000000..7a9e665
--- /dev/null
+++ b/SoftHSMv2/configure.ac
@@ -0,0 +1,226 @@
+##################
+# #
+# Version #
+# #
+################
+
+# Program version
+
+define([SOFTHSM_VERSION_MAJOR], [2])
+define([SOFTHSM_VERSION_MINOR], [3])
+define([SOFTHSM_VERSION_FIX], [0])
+define([PACKAGE_SUFFIX], [])
+
+# Library version
+
+# Code changed: SOFTHSM_VERSION_REVISION++
+# Interface added/removed/changed: SOFTHSM_VERSION_CURRENT++, SOFTHSM_VERSION_REVISION=0
+# Interface added: SOFTHSM_VERSION_AGE++
+# Interface removed: SOFTHSM_VERSION_AGE=0
+
+define([SOFTHSM_VERSION_CURRENT], [2])
+define([SOFTHSM_VERSION_AGE], [1])
+define([SOFTHSM_VERSION_REVISION], [3])
+
+##################
+# #
+# Configure code #
+# #
+##################
+
+# Init
+AC_PREREQ(2.61)
+AC_INIT([SoftHSM],[SOFTHSM_VERSION_MAJOR.SOFTHSM_VERSION_MINOR.SOFTHSM_VERSION_FIX[]PACKAGE_SUFFIX])
+AC_CONFIG_HEADER([config.h])
+AC_CONFIG_SRCDIR([src/Makefile.am])
+AC_CONFIG_MACRO_DIR([m4])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+ACX_PREFIXHACK
+
+# Version info for the library
+VERSION_INFO="SOFTHSM_VERSION_CURRENT:SOFTHSM_VERSION_REVISION:SOFTHSM_VERSION_AGE"
+AC_SUBST(VERSION_INFO)
+
+# Checks for compilers
+AC_PROG_CC
+AC_PROG_CXX
+
+# Compiler flags
+ACX_PEDANTIC
+ACX_STRICT
+ACX_64BIT
+AX_CXX_COMPILE_STDCXX_11([noext],[optional])
+
+# Check for libraries (-ldl can be required by OpenSSL too)
+ACX_DLOPEN
+
+# Check for headers
+AC_CHECK_HEADERS([pthread.h])
+
+# What crypto backend to use and if we want to have support GOST
+ACX_CRYPTO_BACKEND
+
+# Non-paged memory for secure storage
+ACX_NON_PAGED_MEMORY
+
+# If the user want to have the migration tool
+# Requires SQLite3
+AC_ARG_WITH(migrate,
+ AC_HELP_STRING([--with-migrate],
+ [Build the migration tool. Requires SQLite3.]
+ ),
+ [build_migrate="${withval}"],
+ [build_migrate="no"]
+)
+AC_MSG_CHECKING(if building with softhsm2-migrate)
+if test "x${build_migrate}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ ACX_YIELD
+else
+ AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL([BUILD_MIGRATE], [test "x${build_migrate}" = "xyes"])
+
+# If the user wants to have the database storage backend
+AC_ARG_WITH([objectstore-backend-db],
+ AC_HELP_STRING([--with-objectstore-backend-db],
+ [Build with object store backend database (SQLite3).]
+ ),
+ [build_objectstore_backend_db="${withval}"],
+ [build_objectstore_backend_db="no"]
+)
+AC_MSG_CHECKING(if building database object store backend)
+if test "x${build_objectstore_backend_db}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED(
+ [HAVE_OBJECTSTORE_BACKEND_DB],
+ [1],
+ [Build with object store database backend.]
+ )
+else
+ AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL([BUILD_OBJECTSTORE_BACKEND_DB], [test "x${build_objectstore_backend_db}" = "xyes"])
+
+# Require SQLite3 if either building --with-migrate or --with-objectstore-backend-db
+AC_MSG_CHECKING(if SQLite3 required)
+if test "x${build_migrate}" = "xyes" -o "x${build_objectstore_backend_db}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ ACX_SQLITE3
+else
+ AC_MSG_RESULT(no)
+fi
+
+# Set visibility flags so only PKCS#11 entry points are exported
+ACX_VISIBILITY
+
+# If we should install the p11-kit module
+ACX_P11KIT
+
+# cppunit settings
+ACX_CPPUNIT
+
+# Set full directory paths
+full_sysconfdir=`eval eval eval eval eval echo "${sysconfdir}" | sed "s#NONE#${prefix}#" | sed "s#NONE#${ac_default_prefix}#"`
+full_localstatedir=`eval eval eval eval eval echo "${localstatedir}" | sed "s#NONE#${prefix}#" | sed "s#NONE#${ac_default_prefix}#"`
+full_libdir=`eval eval eval eval eval echo "${libdir}" | sed "s#NONE#${prefix}#" | sed "s#NONE#${ac_default_prefix}#"`
+default_softhsm2_conf="`eval echo ${full_sysconfdir} | sed s,NONE,$ac_default_prefix,g`/softhsm2.conf"
+softhsmtokendir=${full_localstatedir}/lib/softhsm/tokens/
+
+# Install the library in a sub-directory
+full_libdir="$full_libdir/softhsm"
+libdir=$full_libdir
+default_softhsm2_lib="$full_libdir/libsofthsm2.so"
+
+# For getConfigPath()
+AC_CHECK_FUNCS([getpwuid_r])
+
+# Define some variables for the code
+AC_DEFINE_UNQUOTED(
+ [VERSION_MAJOR],
+ [SOFTHSM_VERSION_MAJOR],
+ [SoftHSM major version number via PKCS#11]
+)
+AC_DEFINE_UNQUOTED(
+ [VERSION_MINOR],
+ [SOFTHSM_VERSION_MINOR],
+ [SoftHSM minor version number via PKCS#11]
+)
+AC_DEFINE_UNQUOTED(
+ [MAX_PIN_LEN],
+ [255],
+ [Maximum PIN length]
+)
+AC_DEFINE_UNQUOTED(
+ [MIN_PIN_LEN],
+ [4],
+ [Minimum PIN length]
+)
+AC_DEFINE_UNQUOTED(
+ [DEFAULT_SOFTHSM2_CONF],
+ ["$default_softhsm2_conf"],
+ [The default location of softhsm2.conf]
+)
+AC_DEFINE_UNQUOTED(
+ [DEFAULT_TOKENDIR],
+ ["$softhsmtokendir"],
+ [The default location of the token directory]
+)
+AC_DEFINE_UNQUOTED(
+ [DEFAULT_OBJECTSTORE_BACKEND],
+ ["file"],
+ [Default storage backend for token objects]
+)
+AC_DEFINE_UNQUOTED(
+ [DEFAULT_LOG_LEVEL],
+ ["INFO"],
+ [The default log level]
+)
+AC_DEFINE_UNQUOTED(
+ [DEFAULT_PKCS11_LIB],
+ ["$default_softhsm2_lib"],
+ [The default PKCS#11 library]
+)
+
+AC_SUBST([softhsmtokendir])
+AC_SUBST([default_softhsm2_conf])
+AC_SUBST([default_softhsm2_lib])
+
+# Generate the libtool script and install script
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+
+# Generate the makefiles
+AC_CONFIG_FILES([
+ Makefile
+ softhsm2.module
+ src/Makefile
+ src/lib/Makefile
+ src/lib/common/Makefile
+ src/lib/common/softhsm2.conf
+ src/lib/common/softhsm2.conf.5
+ src/lib/crypto/Makefile
+ src/lib/crypto/test/Makefile
+ src/lib/data_mgr/Makefile
+ src/lib/data_mgr/test/Makefile
+ src/lib/object_store/Makefile
+ src/lib/object_store/test/Makefile
+ src/lib/session_mgr/Makefile
+ src/lib/session_mgr/test/Makefile
+ src/lib/slot_mgr/Makefile
+ src/lib/slot_mgr/test/Makefile
+ src/lib/handle_mgr/Makefile
+ src/lib/handle_mgr/test/Makefile
+ src/lib/test/Makefile
+ src/lib/test/softhsm2.conf
+ src/lib/test/softhsm2-alt.conf
+ src/lib/test/tokens/dummy
+ src/bin/Makefile
+ src/bin/common/Makefile
+ src/bin/dump/Makefile
+ src/bin/keyconv/Makefile
+ src/bin/migrate/Makefile
+ src/bin/util/Makefile
+])
+
+AC_OUTPUT
diff --git a/SoftHSMv2/m4/acx_64bit.m4 b/SoftHSMv2/m4/acx_64bit.m4
new file mode 100644
index 0000000..f610b21
--- /dev/null
+++ b/SoftHSMv2/m4/acx_64bit.m4
@@ -0,0 +1,29 @@
+AC_DEFUN([ACX_64BIT],[
+ AC_ARG_ENABLE(
+ [64bit],
+ [AS_HELP_STRING([--enable-64bit],[enable 64-bit compiling @<:@disabled@:>@])],
+ [enable_64bit="${enableval}"],
+ [enable_64bit="no"])
+
+ if test "x$enable_64bit" = "xyes"
+ then
+ AC_MSG_CHECKING(if we can compile in 64-bit mode)
+ tmp_CFLAGS=$CFLAGS
+ CFLAGS="-m64"
+ AC_RUN_IFELSE(
+ [
+ AC_LANG_PROGRAM([],[return sizeof(void*) == 8 ? 0 : 1;])
+ ], [
+ AC_MSG_RESULT(yes)
+ CXXFLAGS="-m64 $CXXFLAGS"
+ LDFLAGS="-m64 $LDFLAGS"
+ CFLAGS="-m64 $tmp_CFLAGS"
+ ],[
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR([Don't know how to compile in 64-bit mode.])
+ CFLAGS=$tmp_CFLAGS
+ ]
+ )
+ fi
+
+])
diff --git a/SoftHSMv2/m4/acx_botan.m4 b/SoftHSMv2/m4/acx_botan.m4
new file mode 100644
index 0000000..ed93786
--- /dev/null
+++ b/SoftHSMv2/m4/acx_botan.m4
@@ -0,0 +1,72 @@
+AC_DEFUN([ACX_BOTAN],[
+ AC_ARG_WITH(botan,
+ AC_HELP_STRING([--with-botan=PATH],[Specify prefix of path of Botan]),
+ [
+ BOTAN_PATH="$withval"
+ ],
+ [
+ BOTAN_PATH="/usr/local"
+ ])
+
+ BOTAN_VERSION_MAJOR=2
+ BOTAN_VERSION_MINOR=0
+ AC_CHECK_FILE($BOTAN_PATH/include/botan-2/botan/version.h,
+ BOTAN_VERSION_MAJOR=2
+ BOTAN_VERSION_MINOR=0,
+ AC_CHECK_FILE($BOTAN_PATH/include/botan-1.11/botan/version.h,
+ BOTAN_VERSION_MAJOR=1
+ BOTAN_VERSION_MINOR=11,
+ AC_CHECK_FILE($BOTAN_PATH/include/botan-1.10/botan/version.h,
+ BOTAN_VERSION_MAJOR=1
+ BOTAN_VERSION_MINOR=10,
+ AC_MSG_ERROR([Cannot find Botan includes]))))
+ AC_MSG_CHECKING(what are the Botan includes)
+ if test "x${BOTAN_VERSION_MAJOR}" = "x2"; then
+ BOTAN_INCLUDES="-I$BOTAN_PATH/include/botan-2"
+ else
+ BOTAN_INCLUDES="-I$BOTAN_PATH/include/botan-1.$BOTAN_VERSION_MINOR"
+ fi
+ AC_MSG_RESULT($BOTAN_INCLUDES)
+
+ AC_MSG_CHECKING(what are the Botan libs)
+ if test "x${BOTAN_VERSION_MAJOR}" = "x2"; then
+ BOTAN_LIBS="-L$BOTAN_PATH/lib -lbotan-2"
+ else
+ BOTAN_LIBS="-L$BOTAN_PATH/lib -lbotan-1.$BOTAN_VERSION_MINOR"
+ fi
+ AC_MSG_RESULT($BOTAN_LIBS)
+
+ if test "x${BOTAN_VERSION_MAJOR}" != "x1" -o "x${BOTAN_VERSION_MINOR}" != "x10"; then
+ AX_CXX_COMPILE_STDCXX_11([noext],[mandatory])
+ fi
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $BOTAN_INCLUDES"
+ LIBS="$LIBS $BOTAN_LIBS"
+
+ AC_LANG_PUSH([C++])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <botan/init.h>
+ #include <botan/version.h>],
+ [using namespace Botan;
+ LibraryInitializer::initialize();
+ #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR($1,$2,$3)
+ #error "Botan version too old";
+ #endif])],
+ [AC_MSG_RESULT([checking for Botan >= v$1.$2.$3 ... yes])],
+ [AC_MSG_RESULT([checking for Botan >= v$1.$2.$3 ... no])
+ AC_MSG_ERROR([Missing the correct version of the Botan library])]
+ )
+ AC_LANG_POP([C++])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+
+ AC_SUBST(BOTAN_INCLUDES)
+ AC_SUBST(BOTAN_LIBS)
+ AC_SUBST(BOTAN_VERSION_MAJOR)
+ AC_SUBST(BOTAN_VERSION_MINOR)
+])
diff --git a/SoftHSMv2/m4/acx_botan_aes_gcm.m4 b/SoftHSMv2/m4/acx_botan_aes_gcm.m4
new file mode 100644
index 0000000..d52c9cb
--- /dev/null
+++ b/SoftHSMv2/m4/acx_botan_aes_gcm.m4
@@ -0,0 +1,37 @@
+AC_DEFUN([ACX_BOTAN_AES_GCM],[
+ AC_MSG_CHECKING(for Botan AES GCM support)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <botan/botan.h>
+ #include <botan/version.h>
+ int main()
+ {
+ using namespace Botan;
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+ return 0;
+#endif
+ return 1;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([Found AES GCM])
+ AC_DEFINE([WITH_AES_GCM], [1],
+ [Compile with AES GCM])
+ ],[
+ AC_MSG_RESULT([Cannot find AES GCM support, upgrade to Botan >= v2.0.0])
+
+ ])
+ AC_LANG_POP([C++])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_botan_ecc.m4 b/SoftHSMv2/m4/acx_botan_ecc.m4
new file mode 100644
index 0000000..9bce21d
--- /dev/null
+++ b/SoftHSMv2/m4/acx_botan_ecc.m4
@@ -0,0 +1,51 @@
+AC_DEFUN([ACX_BOTAN_ECC],[
+ AC_MSG_CHECKING(for Botan ECC support)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <botan/init.h>
+ #include <botan/ec_group.h>
+ #include <botan/oids.h>
+ #include <botan/version.h>
+ int main()
+ {
+ Botan::LibraryInitializer::initialize();
+ const std::string name("secp256r1");
+ const Botan::OID oid(Botan::OIDS::lookup(name));
+ const Botan::EC_Group ecg(oid);
+ try {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ const std::vector<Botan::byte> der =
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);
+#else
+ const Botan::SecureVector<Botan::byte> der =
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);
+#endif
+ } catch(...) {
+ return 1;
+ }
+ return 0;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([Found P256])
+ ],[
+ AC_MSG_RESULT([Cannot find P256])
+ AC_MSG_ERROR([
+Botan library has no valid ECC support. Please upgrade to a later version
+of Botan, above or including version 1.10.6 or 1.11.5.
+Alternatively disable ECC support in SoftHSM with --disable-ecc
+])
+ ],[])
+ AC_LANG_POP([C++])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_botan_gnump.m4 b/SoftHSMv2/m4/acx_botan_gnump.m4
new file mode 100644
index 0000000..d15859a
--- /dev/null
+++ b/SoftHSMv2/m4/acx_botan_gnump.m4
@@ -0,0 +1,27 @@
+AC_DEFUN([ACX_BOTAN_GNUMP],[
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $BOTAN_INCLUDES"
+ LIBS="$LIBS $BOTAN_LIBS"
+
+ AC_LANG_PUSH([C++])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <botan/build.h>],
+ [#ifndef BOTAN_HAS_ENGINE_GNU_MP
+ #error "No GNU MP support";
+ #endif])],
+ [AC_MSG_RESULT([checking for Botan GNU MP support... yes])],
+ [AC_MSG_RESULT([checking for Botan GNU MP support... no])
+ AC_MSG_WARN([
+====================================================
+Botan has not been built with GNU MP (--with-gnump).
+This will give negative impact on the performance.
+====================================================])]
+ )
+ AC_LANG_POP([C++])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_botan_gost.m4 b/SoftHSMv2/m4/acx_botan_gost.m4
new file mode 100644
index 0000000..3720f4a
--- /dev/null
+++ b/SoftHSMv2/m4/acx_botan_gost.m4
@@ -0,0 +1,52 @@
+AC_DEFUN([ACX_BOTAN_GOST],[
+ AC_MSG_CHECKING(for Botan GOST support)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <botan/init.h>
+ #include <botan/gost_3410.h>
+ #include <botan/oids.h>
+ #include <botan/version.h>
+ int main()
+ {
+ Botan::LibraryInitializer::initialize();
+ const std::string name("gost_256A");
+ const Botan::OID oid(Botan::OIDS::lookup(name));
+ const Botan::EC_Group ecg(oid);
+ try {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ const std::vector<Botan::byte> der =
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);
+#else
+ const Botan::SecureVector<Botan::byte> der =
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);
+#endif
+ } catch(...) {
+ return 1;
+ }
+
+ return 0;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([Found GOST])
+ ],[
+ AC_MSG_RESULT([Cannot find GOST])
+ AC_MSG_ERROR([
+Botan library has no valid GOST support. Please upgrade to a later version
+of Botan, above or including version 1.10.6 or 1.11.5.
+Alternatively disable GOST support in SoftHSM with --disable-gost
+])
+ ],[])
+ AC_LANG_POP([C++])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_botan_rawpss.m4 b/SoftHSMv2/m4/acx_botan_rawpss.m4
new file mode 100644
index 0000000..018e324
--- /dev/null
+++ b/SoftHSMv2/m4/acx_botan_rawpss.m4
@@ -0,0 +1,37 @@
+AC_DEFUN([ACX_BOTAN_RAWPSS],[
+ AC_MSG_CHECKING(for Botan raw PSS support)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ AC_LANG_PUSH([C++])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <botan/botan.h>
+ #include <botan/version.h>
+ int main()
+ {
+ using namespace Botan;
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,3,0)
+ return 0;
+#endif
+ return 1;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([Found raw PSS])
+ AC_DEFINE([WITH_RAW_PSS], [1],
+ [Compile with raw RSA PKCS PSS])
+ ],[
+ AC_MSG_RESULT([Cannot find raw PSS support, upgrade to Botan >= v2.3.0])
+
+ ])
+ AC_LANG_POP([C++])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_botan_rfc5649.m4 b/SoftHSMv2/m4/acx_botan_rfc5649.m4
new file mode 100644
index 0000000..25a3d26
--- /dev/null
+++ b/SoftHSMv2/m4/acx_botan_rfc5649.m4
@@ -0,0 +1,47 @@
+AC_DEFUN([ACX_BOTAN_RFC5649],[
+ AC_MSG_CHECKING(for Botan RFC5649 support)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ AC_DEFINE([HAVE_AES_KEY_WRAP], [1],
+ [Define if advanced AES key wrap without pad is supported])
+ AC_LANG_PUSH([C++])
+ AC_LINK_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <botan/botan.h>
+ #include <botan/rfc3394.h>
+ #include <botan/version.h>
+ int main()
+ {
+ using namespace Botan;
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ secure_vector<byte> key(10);
+ SymmetricKey kek("AABB");
+ secure_vector<byte> x = rfc5649_keywrap(key, kek);
+#else
+ SecureVector<byte> key(10);
+ SymmetricKey kek("AABB");
+ Algorithm_Factory& af = global_state().algorithm_factory();
+ SecureVector<byte> x = rfc5649_keywrap(key, kek, af);
+#endif
+ return 1;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([Found AES key wrap with pad])
+ AC_DEFINE([HAVE_AES_KEY_WRAP_PAD], [1],
+ [Define if advanced AES key wrap with pad is supported])
+ ],[
+ AC_MSG_RESULT([Cannot find AES key wrap with pad])
+
+ ])
+ AC_LANG_POP([C++])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_cppunit.m4 b/SoftHSMv2/m4/acx_cppunit.m4
new file mode 100644
index 0000000..2720d81
--- /dev/null
+++ b/SoftHSMv2/m4/acx_cppunit.m4
@@ -0,0 +1,21 @@
+AC_DEFUN([ACX_CPPUNIT],[
+ AC_PATH_PROG([CPPUNIT_CONFIG], [cppunit-config])
+ AC_PATH_PROG([PKG_CONFIG], [pkg-config])
+ if test -n "${CPPUNIT_CONFIG}"; then
+ AC_MSG_CHECKING([cppunit cflags])
+ CPPUNIT_CFLAGS=`${CPPUNIT_CONFIG} --cflags`
+ AC_MSG_RESULT([${CPPUNIT_CFLAGS}])
+ AC_MSG_CHECKING([cppunit libs])
+ CPPUNIT_LIBS=`${CPPUNIT_CONFIG} --libs`
+ AC_MSG_RESULT([${CPPUNIT_LIBS}])
+ elif test -n "${PKG_CONFIG}"; then
+ AC_MSG_CHECKING([cppunit cflags])
+ CPPUNIT_CFLAGS=`${PKG_CONFIG} cppunit --cflags`
+ AC_MSG_RESULT([${CPPUNIT_CFLAGS}])
+ AC_MSG_CHECKING([cppunit libs])
+ CPPUNIT_LIBS=`${PKG_CONFIG} cppunit --libs`
+ AC_MSG_RESULT([${CPPUNIT_LIBS}])
+ fi
+ AC_SUBST([CPPUNIT_CFLAGS])
+ AC_SUBST([CPPUNIT_LIBS])
+])
diff --git a/SoftHSMv2/m4/acx_crypto_backend.m4 b/SoftHSMv2/m4/acx_crypto_backend.m4
new file mode 100644
index 0000000..c860c89
--- /dev/null
+++ b/SoftHSMv2/m4/acx_crypto_backend.m4
@@ -0,0 +1,168 @@
+AC_DEFUN([ACX_CRYPTO_BACKEND],[
+
+ # First check if we want to support ECC and GOST
+
+ AC_ARG_ENABLE(ecc,
+ AC_HELP_STRING([--enable-ecc],
+ [Enable support for ECC (default enabled)]
+ ),
+ [enable_ecc="${enableval}"],
+ [enable_ecc="yes"]
+ )
+ AC_MSG_CHECKING(for ECC support)
+ if test "x${enable_ecc}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED(
+ [WITH_ECC],
+ [],
+ [Compile with ECC support]
+ )
+ else
+ AC_MSG_RESULT(no)
+ fi
+ AM_CONDITIONAL([WITH_ECC], [test "x${enable_ecc}" = "xyes"])
+
+ AC_ARG_ENABLE(gost,
+ AC_HELP_STRING([--enable-gost],
+ [Enable support for GOST (default enabled)]
+ ),
+ [enable_gost="${enableval}"],
+ [enable_gost="yes"]
+ )
+ AC_MSG_CHECKING(for GOST support)
+ if test "x${enable_gost}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED(
+ [WITH_GOST],
+ [],
+ [Compile with GOST support]
+ )
+ else
+ AC_MSG_RESULT(no)
+ fi
+ AM_CONDITIONAL([WITH_GOST], [test "x${enable_gost}" = "xyes"])
+
+ # Second check for the FIPS 140-2 mode
+
+ AC_ARG_ENABLE(fips,
+ AC_HELP_STRING([--enable-fips],
+ [Enable support for FIPS 140-2 mode (default disabled)]
+ ),
+ [enable_fips="${enableval}"],
+ [enable_fips="no"]
+ )
+ AC_MSG_CHECKING(for FIPS 140-2 mode)
+ if test "x${enable_fips}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED(
+ [WITH_FIPS],
+ [],
+ [Compile with FIPS 140-2 mode]
+ )
+ else
+ AC_MSG_RESULT(no)
+ fi
+ AM_CONDITIONAL([WITH_GOST], [test "x${enable_fips}" = "xyes"])
+
+ # Then check what crypto library we want to use
+
+ AC_ARG_WITH(crypto-backend,
+ AC_HELP_STRING([--with-crypto-backend],
+ [Select crypto backend (openssl|botan)]
+ ),
+ [crypto_backend="${withval}"],
+ [crypto_backend="openssl"]
+ )
+
+ AC_MSG_CHECKING(for crypto backend)
+
+ if test "x${crypto_backend}" = "xopenssl"; then
+ AC_MSG_RESULT(OpenSSL)
+
+ if test "x${enable_fips}" = "xyes"; then
+ ACX_OPENSSL(1,0,1)
+ else
+ ACX_OPENSSL(1,0,0)
+ fi
+
+ CRYPTO_INCLUDES=$OPENSSL_INCLUDES
+ CRYPTO_LIBS=$OPENSSL_LIBS
+
+ if test "x${enable_ecc}" = "xyes"; then
+ ACX_OPENSSL_ECC
+ fi
+
+ if test "x${enable_gost}" = "xyes"; then
+ if test "x${enable_fips}" = "xyes"; then
+ AC_MSG_ERROR([GOST is not FIPS approved])
+ fi
+ ACX_OPENSSL_GOST
+ fi
+
+ if test "x${enable_fips}" = "xyes"; then
+ ACX_OPENSSL_FIPS
+ else
+ ACX_OPENSSL_EVPAESWRAP
+ fi
+
+ AC_DEFINE_UNQUOTED(
+ [WITH_RAW_PSS],
+ [1],
+ [Compile with raw RSA PKCS PSS]
+ )
+ AC_DEFINE_UNQUOTED(
+ [WITH_AES_GCM],
+ [1],
+ [Compile with AES_GCM]
+ )
+ AC_DEFINE_UNQUOTED(
+ [WITH_OPENSSL],
+ [],
+ [Compile with OpenSSL support]
+ )
+
+ elif test "x${crypto_backend}" = "xbotan"; then
+ AC_MSG_RESULT(Botan)
+
+ ACX_BOTAN(1,10,0)
+
+ CRYPTO_INCLUDES=$BOTAN_INCLUDES
+ CRYPTO_LIBS=$BOTAN_LIBS
+
+ if test "x${enable_ecc}" = "xyes"; then
+ ACX_BOTAN_ECC
+ fi
+
+ if test "x${enable_fips}" = "xyes"; then
+ AC_MSG_ERROR([Botan does not support FIPS 140-2 mode])
+ fi
+
+ if test "x${enable_gost}" = "xyes"; then
+ ACX_BOTAN_GOST
+ fi
+
+ if test "x${BOTAN_VERSION_MAJOR}" = "x1" -a "x${BOTAN_VERSION_MINOR}" = "x10"; then
+ ACX_BOTAN_GNUMP
+ fi
+
+ ACX_BOTAN_RFC5649
+ ACX_BOTAN_RAWPSS
+ ACX_BOTAN_AES_GCM
+
+ AC_DEFINE_UNQUOTED(
+ [WITH_BOTAN],
+ [],
+ [Compile with Botan support]
+ )
+
+ else
+ AC_MSG_RESULT(Unknown)
+ AC_MSG_ERROR([Crypto backend ${crypto_backend} not supported. Use openssl or botan.])
+ fi
+
+ AC_SUBST(CRYPTO_INCLUDES)
+ AC_SUBST(CRYPTO_LIBS)
+ AM_CONDITIONAL([WITH_OPENSSL], [test "x${crypto_backend}" = "xopenssl"])
+ AM_CONDITIONAL([WITH_BOTAN], [test "x${crypto_backend}" = "xbotan"])
+
+])
diff --git a/SoftHSMv2/m4/acx_dlopen.m4 b/SoftHSMv2/m4/acx_dlopen.m4
new file mode 100644
index 0000000..2d67614
--- /dev/null
+++ b/SoftHSMv2/m4/acx_dlopen.m4
@@ -0,0 +1,15 @@
+AC_DEFUN([ACX_DLOPEN],[
+ AC_CHECK_FUNC(dlopen, [AC_DEFINE(HAVE_DLOPEN,1,[Define if you have dlopen])],
+ [
+ AC_CHECK_LIB([dl],[dlopen],
+ [AC_DEFINE(HAVE_DLOPEN,1,[Define if you have dlopen])
+ LIBS="$LIBS -ldl"],
+ [AC_CHECK_FUNC(LoadLibrary,
+ [if test $ac_cv_func_LoadLibrary = yes; then
+ AC_DEFINE(HAVE_LOADLIBRARY, 1, [Whether LoadLibrary is available])
+ fi
+ ], [AC_MSG_ERROR(No dynamic library loading support)]
+ )]
+ )
+ ])
+])
diff --git a/SoftHSMv2/m4/acx_non_paged_memory.m4 b/SoftHSMv2/m4/acx_non_paged_memory.m4
new file mode 100644
index 0000000..0253e98
--- /dev/null
+++ b/SoftHSMv2/m4/acx_non_paged_memory.m4
@@ -0,0 +1,57 @@
+AC_DEFUN([ACX_NON_PAGED_MEMORY],[
+
+ AC_ARG_ENABLE(non-paged-memory,
+ AC_HELP_STRING([--disable-non-paged-memory],
+ [Disable non-paged memory for secure storage (default enabled)]
+ ),
+ [enable_non_paged_memory="${enableval}"],
+ [enable_non_paged_memory="yes"]
+ )
+
+ AC_MSG_CHECKING(for non-paged memory for secure storage)
+
+ if test "x${enable_non_paged_memory}" = "xyes"; then
+ AC_MSG_RESULT(enabled)
+ AC_DEFINE_UNQUOTED(
+ [SENSITIVE_NON_PAGE],
+ [],
+ [Non-paged memory for secure storage]
+ )
+ AC_CHECK_HEADERS([sys/mman.h])
+
+ AC_MSG_CHECKING(the maximum size that may be locked into memory)
+ MLOCK_SIZE="`ulimit -l`"
+ AC_MSG_RESULT($MLOCK_SIZE)
+
+ if test "x${MLOCK_SIZE}" != "xunlimited"; then
+ AC_MSG_WARN([
+======================================================================
+SoftHSM has been configured to store sensitive data in non-page RAM
+(i.e. memory that is not swapped out to disk). This is the default and
+most secure configuration. Your system, however, is not configured to
+support this model in non-privileged accounts (i.e. user accounts).
+
+You can check the setting on your system by running the following
+command in a shell:
+
+ ulimit -l
+
+If this does not return "unlimited" and you plan to run SoftHSM from
+non-privileged accounts then you should edit the configuration file
+/etc/security/limits.conf (on most systems).
+
+You will need to add the following lines to this file:
+
+#<domain> <type> <item> <value>
+* - memlock unlimited
+
+Alternatively, you can elect to disable this feature of SoftHSM by
+re-running configure with the option "--disable-non-paged-memory".
+Please be advised that this may seriously degrade the security of
+SoftHSM.
+======================================================================])
+ fi
+ else
+ AC_MSG_RESULT(disabled)
+ fi
+])
diff --git a/SoftHSMv2/m4/acx_openssl.m4 b/SoftHSMv2/m4/acx_openssl.m4
new file mode 100644
index 0000000..e90c78f
--- /dev/null
+++ b/SoftHSMv2/m4/acx_openssl.m4
@@ -0,0 +1,60 @@
+AC_DEFUN([ACX_OPENSSL],[
+ AC_ARG_WITH(openssl,
+ AC_HELP_STRING([--with-openssl=PATH],[Specify prefix of path of OpenSSL]),
+ [
+ OPENSSL_PATH="$withval"
+ ],
+ [
+ OPENSSL_PATH="/usr/local"
+ ])
+
+ AC_MSG_CHECKING(what are the OpenSSL includes)
+ OPENSSL_INCLUDES="-I$OPENSSL_PATH/include"
+ AC_MSG_RESULT($OPENSSL_INCLUDES)
+
+ AC_MSG_CHECKING(what are the OpenSSL libs)
+ OPENSSL_LIBS="-L$OPENSSL_PATH/lib -lcrypto"
+ AC_MSG_RESULT($OPENSSL_LIBS)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $OPENSSL_INCLUDES"
+ LIBS="$OPENSSL_LIBS $LIBS"
+
+ AC_CHECK_HEADERS([openssl/ssl.h],,[AC_MSG_ERROR([Can't find OpenSSL headers])])
+ AC_CHECK_LIB(crypto, BN_new,,[AC_MSG_ERROR([Can't find OpenSSL library])])
+
+ AC_MSG_CHECKING([for OpenSSL version])
+ CHECK_OPENSSL_VERSION=m4_format(0x%02x%02x%02x000L, $1, $2, $3)
+ AC_LANG_PUSH([C])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <openssl/ssl.h>
+ #include <openssl/opensslv.h>
+ int main()
+ {
+ #ifndef OPENSSL_VERSION_NUMBER
+ return -1;
+ #endif
+ #if OPENSSL_VERSION_NUMBER >= $CHECK_OPENSSL_VERSION
+ return 0;
+ #else
+ return 1;
+ #endif
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([>= $1.$2.$3])
+ ],[
+ AC_MSG_RESULT([< $1.$2.$3])
+ AC_MSG_ERROR([OpenSSL library too old ($1.$2.$3 or later required)])
+ ],[])
+ AC_LANG_POP([C])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+
+ AC_SUBST(OPENSSL_INCLUDES)
+ AC_SUBST(OPENSSL_LIBS)
+])
diff --git a/SoftHSMv2/m4/acx_openssl_ecc.m4 b/SoftHSMv2/m4/acx_openssl_ecc.m4
new file mode 100644
index 0000000..612c505
--- /dev/null
+++ b/SoftHSMv2/m4/acx_openssl_ecc.m4
@@ -0,0 +1,37 @@
+AC_DEFUN([ACX_OPENSSL_ECC],[
+ AC_MSG_CHECKING(for OpenSSL ECC support)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ AC_LANG_PUSH([C])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <openssl/ecdsa.h>
+ #include <openssl/objects.h>
+ int main()
+ {
+ EC_KEY *ec256, *ec384, *ec521;
+
+ ec256 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ ec384 = EC_KEY_new_by_curve_name(NID_secp384r1);
+ ec521 = EC_KEY_new_by_curve_name(NID_secp521r1);
+ if (ec256 == NULL || ec384 == NULL || ec521 == NULL)
+ return 1;
+ return 0;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([Found P256, P384, and P521])
+ ],[
+ AC_MSG_RESULT([Cannot find P256, P384, or P521])
+ AC_MSG_ERROR([OpenSSL library has no ECC support])
+ ],[])
+ AC_LANG_POP([C])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_openssl_fips.m4 b/SoftHSMv2/m4/acx_openssl_fips.m4
new file mode 100644
index 0000000..0491397
--- /dev/null
+++ b/SoftHSMv2/m4/acx_openssl_fips.m4
@@ -0,0 +1,50 @@
+AC_DEFUN([ACX_OPENSSL_FIPS],[
+ AC_MSG_CHECKING(for OpenSSL FIPS capable library)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ # check whether we can build an application which can
+ # "reference the OpenSSL FIPS object module"
+
+ AC_LANG_PUSH([C])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <openssl/crypto.h>
+ int main()
+ {
+ return !FIPS_mode_set(1);
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([Found working FIPS_mode_set()])
+ ],[
+ AC_MSG_RESULT([FIPS_mode_set(1) failed])
+ AC_MSG_ERROR([OpenSSL library is not FIPS capable])
+ ],[])
+ AC_LANG_POP([C])
+
+ # build missing fips_premain_dso tool
+
+ if test "x${FIPSLD_CC}" != "x"; then
+ THERE="`echo $CC | sed -e 's|[[^/]]*$||'`"..
+ if test "x${FIPSLIBDIR}" != "x"; then
+ PREMAIN_C="${FIPSLIBDIR}/fips_premain.c"
+ elif test -f "${THERE}/fips/fips_premain.c"; then
+ PREMAIN_C="${THERE}/fips/fips_premain.c"
+ elif test -f "${THERE}/lib/fips_premain.c"; then
+ PREMAIN_C="${THERE}/lib/fips_premain.c"
+ else
+ AC_MSG_WARN([can't find fips_premain.c])
+ fi
+
+ $FIPSLD_CC $CPPFLAGS -DFINGERPRINT_PREMAIN_DSO_LOAD \
+ -o src/lib/fips_premain_dso $PREMAIN_C $LIBS
+ fi
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_openssl_gost.m4 b/SoftHSMv2/m4/acx_openssl_gost.m4
new file mode 100644
index 0000000..dca489b
--- /dev/null
+++ b/SoftHSMv2/m4/acx_openssl_gost.m4
@@ -0,0 +1,65 @@
+AC_DEFUN([ACX_OPENSSL_GOST],[
+ AC_MSG_CHECKING(for OpenSSL GOST support)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ AC_LANG_PUSH([C])
+ AC_RUN_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <openssl/engine.h>
+ #include <openssl/crypto.h>
+ #include <openssl/opensslv.h>
+ int main()
+ {
+ ENGINE* eg;
+ const EVP_MD* EVP_GOST_34_11;
+
+ /* Initialise OpenSSL */
+ OpenSSL_add_all_algorithms();
+
+ /* Load engines */
+ #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ ENGINE_load_builtin_engines();
+ #else
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN | OPENSSL_INIT_LOAD_CONFIG, NULL);
+ #endif
+
+ /* Initialise the GOST engine */
+ eg = ENGINE_by_id("gost");
+ if (eg == NULL)
+ return 1;
+ if (ENGINE_init(eg) <= 0)
+ return 1;
+
+ /* better than digest_gost */
+ EVP_GOST_34_11 = ENGINE_get_digest(eg, NID_id_GostR3411_94);
+ if (EVP_GOST_34_11 == NULL)
+ return 1;
+
+ /* from the openssl.cnf */
+ if (ENGINE_register_pkey_asn1_meths(eg) <= 0)
+ return 1;
+ if (ENGINE_ctrl_cmd_string(eg,
+ "CRYPT_PARAMS",
+ "id-Gost28147-89-CryptoPro-A-ParamSet",
+ 0) <= 0)
+ return 1;
+
+ return 0;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([Found GOST engine])
+ ],[
+ AC_MSG_RESULT([Cannot find GOST engine])
+ AC_MSG_ERROR([OpenSSL library has no GOST support])
+ ],[])
+ AC_LANG_POP([C])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_openssl_rfc5649.m4 b/SoftHSMv2/m4/acx_openssl_rfc5649.m4
new file mode 100644
index 0000000..c68a336
--- /dev/null
+++ b/SoftHSMv2/m4/acx_openssl_rfc5649.m4
@@ -0,0 +1,51 @@
+AC_DEFUN([ACX_OPENSSL_EVPAESWRAP],[
+ AC_MSG_CHECKING(OpenSSL EVP interface for AES key wrapping)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $CRYPTO_INCLUDES"
+ LIBS="$CRYPTO_LIBS $LIBS"
+
+ AC_LANG_PUSH([C])
+
+ AC_LINK_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <openssl/evp.h>
+ int main()
+ {
+ EVP_aes_128_wrap();
+ return 1;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([RFC 3394 is supported])
+ AC_DEFINE([HAVE_AES_KEY_WRAP], [1],
+ [Define if advanced AES key wrap without pad is supported in EVP interface])
+ ],[
+ AC_MSG_RESULT([RFC 3394 is not supported])
+ ])
+
+ AC_MSG_CHECKING(OpenSSL EVP interface for AES key wrapping with pad)
+ AC_LINK_IFELSE([
+ AC_LANG_SOURCE([[
+ #include <openssl/evp.h>
+ int main()
+ {
+ EVP_aes_128_wrap_pad();
+ return 1;
+ }
+ ]])
+ ],[
+ AC_MSG_RESULT([RFC 5649 is supported])
+ AC_DEFINE([HAVE_AES_KEY_WRAP_PAD], [1],
+ [Define if advanced AES key wrap with pad is supported in EVP interface])
+ ],[
+ AC_MSG_RESULT([RFC 5649 is not supported])
+ ])
+
+ AC_LANG_POP([C])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+])
diff --git a/SoftHSMv2/m4/acx_p11kit.m4 b/SoftHSMv2/m4/acx_p11kit.m4
new file mode 100644
index 0000000..20c7b7e
--- /dev/null
+++ b/SoftHSMv2/m4/acx_p11kit.m4
@@ -0,0 +1,36 @@
+AC_DEFUN([ACX_P11KIT],[
+ AC_ARG_ENABLE([p11-kit],
+ AC_HELP_STRING([--enable-p11-kit],
+ [Enable p11-kit integration (default enabled)]
+ ),
+ [enable_p11kit="${enableval}"],
+ [enable_p11kit="yes"]
+ )
+
+ AC_ARG_WITH(p11-kit,
+ AC_HELP_STRING([--with-p11-kit=PATH],[Specify install path of the p11-kit module, will override path given by pkg-config]),
+ [P11KIT_PATH="$withval"],
+ [P11KIT_PATH=""]
+ )
+
+ AC_MSG_CHECKING(for p11-kit integration)
+ if test "x${enable_p11kit}" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ if test "x${P11KIT_PATH}" = "x"; then
+ AC_PATH_PROG(PKGCONFIG, [pkg-config])
+ if test "x${PKGCONFIG}" != "x" && ${PKGCONFIG} --exists p11-kit-1; then
+ P11KIT_PATH=`${PKGCONFIG} --variable=p11_module_configs p11-kit-1`
+ fi
+ fi
+ AC_MSG_CHECKING(where to install the p11-kit module)
+ AC_MSG_RESULT($P11KIT_PATH)
+ if test "x${P11KIT_PATH}" = "x"; then
+ AC_MSG_WARN([Missing install path for the p11-kit module, skipping module])
+ fi
+ else
+ AC_MSG_RESULT(no)
+ fi
+
+ AC_SUBST(P11KIT_PATH)
+ AM_CONDITIONAL([WITH_P11KIT], [test "x${enable_p11kit}" = "xyes" -a "x${P11KIT_PATH}" != "x"])
+])
diff --git a/SoftHSMv2/m4/acx_pedantic.m4 b/SoftHSMv2/m4/acx_pedantic.m4
new file mode 100644
index 0000000..11808ee
--- /dev/null
+++ b/SoftHSMv2/m4/acx_pedantic.m4
@@ -0,0 +1,12 @@
+AC_DEFUN([ACX_PEDANTIC],[
+ AC_ARG_ENABLE(
+ [pedantic],
+ [AS_HELP_STRING([--enable-pedantic],[enable pedantic compile mode @<:@enabled@:>@])],
+ ,
+ [enable_pedantic="yes"]
+ )
+ if test "${enable_pedantic}" = "yes"; then
+ enable_strict="yes";
+ CFLAGS="${CFLAGS} -pedantic"
+ fi
+])
diff --git a/SoftHSMv2/m4/acx_prefixhack.m4 b/SoftHSMv2/m4/acx_prefixhack.m4
new file mode 100644
index 0000000..16a50a2
--- /dev/null
+++ b/SoftHSMv2/m4/acx_prefixhack.m4
@@ -0,0 +1,23 @@
+# Special processing of paths depending on whether --prefix,
+# --sysconfdir or --localstatedir arguments were given.
+
+AC_DEFUN([ACX_PREFIXHACK],[
+ case "$prefix" in
+ NONE)
+ case "$sysconfdir" in
+ '${prefix}/etc')
+ sysconfdir=/etc
+ ac_configure_args="$ac_configure_args --sysconfdir=$sysconfdir"
+ AC_MSG_NOTICE([sysconfdir set to $sysconfdir])
+ ;;
+ esac
+ case "$localstatedir" in
+ '${prefix}/var')
+ localstatedir=/var
+ ac_configure_args="$ac_configure_args --localstatedir=$localstatedir"
+ AC_MSG_NOTICE([localstate set to $localstatedir])
+ ;;
+ esac
+ ;;
+ esac
+])
diff --git a/SoftHSMv2/m4/acx_sqlite3.m4 b/SoftHSMv2/m4/acx_sqlite3.m4
new file mode 100644
index 0000000..cf829b7
--- /dev/null
+++ b/SoftHSMv2/m4/acx_sqlite3.m4
@@ -0,0 +1,40 @@
+AC_DEFUN([ACX_SQLITE3],[
+ AC_ARG_WITH(sqlite3,
+ AC_HELP_STRING([--with-sqlite3=PATH],[Specify prefix of path of SQLite3]),
+ [
+ SQLITE3_PATH="$withval"
+ AC_PATH_PROGS(SQLITE3, sqlite3, sqlite3, $withval/bin)
+
+ ],[
+ SQLITE3_PATH="/usr/local"
+ AC_PATH_PROGS(SQLITE3, sqlite3, sqlite3, $PATH)
+ ])
+
+
+ if ! test -x "$SQLITE3"; then
+ AC_MSG_ERROR([sqlite3 command not found])
+ fi
+
+ AC_MSG_CHECKING(what are the SQLite3 includes)
+ SQLITE3_INCLUDES="-I$SQLITE3_PATH/include"
+ AC_MSG_RESULT($SQLITE3_INCLUDES)
+
+ AC_MSG_CHECKING(what are the SQLite3 libs)
+ SQLITE3_LIBS="-L$SQLITE3_PATH/lib -lsqlite3"
+ AC_MSG_RESULT($SQLITE3_LIBS)
+
+ tmp_CPPFLAGS=$CPPFLAGS
+ tmp_LIBS=$LIBS
+
+ CPPFLAGS="$CPPFLAGS $SQLITE3_INCLUDES"
+ LIBS="$LIBS $SQLITE3_LIBS"
+
+ AC_CHECK_HEADERS(sqlite3.h,,[AC_MSG_ERROR([Can't find SQLite3 headers])])
+ AC_CHECK_LIB(sqlite3, sqlite3_prepare_v2, [], [AC_MSG_ERROR([Missing SQLite3 library v3.4.2 or greater])])
+
+ CPPFLAGS=$tmp_CPPFLAGS
+ LIBS=$tmp_LIBS
+
+ AC_SUBST(SQLITE3_INCLUDES)
+ AC_SUBST(SQLITE3_LIBS)
+])
diff --git a/SoftHSMv2/m4/acx_strict.m4 b/SoftHSMv2/m4/acx_strict.m4
new file mode 100644
index 0000000..0bb8089
--- /dev/null
+++ b/SoftHSMv2/m4/acx_strict.m4
@@ -0,0 +1,12 @@
+AC_DEFUN([ACX_STRICT],[
+ AC_ARG_ENABLE(
+ [strict],
+ [AS_HELP_STRING([--enable-strict],[enable strict compile mode @<:@enabled@:>@])],
+ ,
+ [enable_strict="yes"]
+ )
+ if test "${enable_strict}" = "yes"; then
+ CFLAGS="${CFLAGS} -Wall -Wextra"
+ CXXFLAGS="${CXXFLAGS} -Wall -Wextra"
+ fi
+])
diff --git a/SoftHSMv2/m4/acx_visibility.m4 b/SoftHSMv2/m4/acx_visibility.m4
new file mode 100644
index 0000000..589a72e
--- /dev/null
+++ b/SoftHSMv2/m4/acx_visibility.m4
@@ -0,0 +1,14 @@
+AC_DEFUN([ACX_VISIBILITY],[
+ AC_ARG_ENABLE(
+ [visibility],
+ [AS_HELP_STRING([--disable-visibility],[disable hidden visibilty link mode @<:@enabled@:>@])],
+ [enable_visibility="${enableval}"],
+ [enable_visibility="yes"]
+ )
+ if test "${enable_visibility}" = "yes"; then
+ CFLAGS="${CFLAGS} -fvisibility=hidden"
+ CXXFLAGS="${CXXFLAGS} -fvisibility=hidden"
+ AC_DEFINE(CRYPTOKI_VISIBILITY, 1,
+ [Define to default visibility of PKCS@%:@11 entry points])
+ fi
+])
diff --git a/SoftHSMv2/m4/acx_yield.m4 b/SoftHSMv2/m4/acx_yield.m4
new file mode 100644
index 0000000..335c190
--- /dev/null
+++ b/SoftHSMv2/m4/acx_yield.m4
@@ -0,0 +1,10 @@
+AC_DEFUN([ACX_YIELD],[
+ YIELD_LIB=
+ # Solaris has sched_yield in librt, not in libpthread or libc.
+ # Solaris 2.5.1, 2.6 has sched_yield in libposix4, not librt.
+ AC_CHECK_LIB(rt, sched_yield, [YIELD_LIB=-lrt],
+ [AC_CHECK_LIB(posix4, sched_yield, [YIELD_LIB=-lposix4])])
+ AC_SUBST([YIELD_LIB])
+
+ AC_CHECK_HEADER([sched.h])
+])
diff --git a/SoftHSMv2/m4/ax_cxx_compile_stdcxx_11.m4 b/SoftHSMv2/m4/ax_cxx_compile_stdcxx_11.m4
new file mode 100644
index 0000000..28ab4eb
--- /dev/null
+++ b/SoftHSMv2/m4/ax_cxx_compile_stdcxx_11.m4
@@ -0,0 +1,146 @@
+# ============================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
+#
+# DESCRIPTION
+#
+# Check for baseline language coverage in the compiler for the C++11
+# standard; if necessary, add switches to CXXFLAGS to enable support.
+#
+# The first argument, if specified, indicates whether you insist on an
+# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+# -std=c++11). If neither is specified, you get whatever works, with
+# preference for an extended mode.
+#
+# The second argument, if specified 'mandatory' or if left unspecified,
+# indicates that baseline C++11 support is required and that the macro
+# should error out if no mode with that support is found. If specified
+# 'optional', then configuration proceeds regardless, after defining
+# HAVE_CXX11 if and only if a supporting mode is found.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+# Copyright (c) 2014 Alexey Sokolov <sokolov@google.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 4
+
+m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[
+ #include <memory>
+
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ struct Base {
+ virtual void f() {}
+ };
+ struct Child : public Base {
+ virtual void f() override {}
+ };
+
+ std::unique_ptr<Base> ptr_to_base;
+
+ typedef check<check<bool>> right_angle_brackets;
+
+ int a;
+ decltype(a) b;
+
+ typedef check<int> check_type;
+ check_type c;
+ check_type&& cr = static_cast<check_type&&>(c);
+
+ auto d = a;
+ auto l = [](){};
+]])
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
+ m4_if([$1], [], [],
+ [$1], [ext], [],
+ [$1], [noext], [],
+ [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
+ m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
+ [$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
+ [$2], [optional], [ax_cxx_compile_cxx11_required=false],
+ [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])
+ AC_LANG_PUSH([C++])dnl
+ ac_success=no
+ AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
+ ax_cv_cxx_compile_cxx11,
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [ax_cv_cxx_compile_cxx11=yes],
+ [ax_cv_cxx_compile_cxx11=no])])
+ if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+ ac_success=yes
+ fi
+
+ m4_if([$1], [noext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=gnu++11 -std=gnu++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+ $cachevar,
+ [ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"])
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+
+ m4_if([$1], [ext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=c++11 -std=c++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+ $cachevar,
+ [ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"])
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+ AC_LANG_POP([C++])
+ if test x$ax_cxx_compile_cxx11_required = xtrue; then
+ if test x$ac_success = xno; then
+ AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
+ fi
+ else
+ if test x$ac_success = xno; then
+ HAVE_CXX11=0
+ AC_MSG_NOTICE([No compiler with C++11 support was found])
+ else
+ HAVE_CXX11=1
+ AC_DEFINE(HAVE_CXX11,1,
+ [define if the compiler supports basic C++11 syntax])
+ fi
+
+ AC_SUBST(HAVE_CXX11)
+ fi
+])
diff --git a/SoftHSMv2/prepdist.sh b/SoftHSMv2/prepdist.sh
new file mode 100644
index 0000000..93e5cb2
--- /dev/null
+++ b/SoftHSMv2/prepdist.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+PREFIX=/tmp/softhsm2-release
+export LD_LIBRARY_PATH=/usr/local/lib
+
+if [ ! -f autogen.sh -a ! -f configure ]; then
+ echo "Unable to continue, no autogen.sh or configure"
+ exit 1
+fi
+
+if [ -f autogen.sh ]; then
+ sh autogen.sh
+fi &&
+mkdir -p build &&
+cd build &&
+../configure --prefix=${PREFIX} \
+ --with-crypto-backend=botan \
+ --with-botan=/usr/local \
+ $@
diff --git a/SoftHSMv2/softhsm2.module.in b/SoftHSMv2/softhsm2.module.in
new file mode 100644
index 0000000..fe88908
--- /dev/null
+++ b/SoftHSMv2/softhsm2.module.in
@@ -0,0 +1,4 @@
+# This file describes how to load the pk11 module
+# See: http://p11-glue.freedesktop.org/doc/p11-kit/config.html
+
+module: @default_softhsm2_lib@
diff --git a/SoftHSMv2/src/Makefile.am b/SoftHSMv2/src/Makefile.am
new file mode 100644
index 0000000..7f51142
--- /dev/null
+++ b/SoftHSMv2/src/Makefile.am
@@ -0,0 +1,3 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+SUBDIRS = lib bin
diff --git a/SoftHSMv2/src/bin/Makefile.am b/SoftHSMv2/src/bin/Makefile.am
new file mode 100644
index 0000000..354c272
--- /dev/null
+++ b/SoftHSMv2/src/bin/Makefile.am
@@ -0,0 +1,10 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+SUBDIRS = common keyconv util dump
+
+if BUILD_MIGRATE
+SUBDIRS += migrate
+endif
+
+EXTRA_DIST = $(srcdir)/win32/*.cpp \
+ $(srcdir)/win32/*.h
diff --git a/SoftHSMv2/src/bin/common/Makefile.am b/SoftHSMv2/src/bin/common/Makefile.am
new file mode 100644
index 0000000..e3a2b24
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/Makefile.am
@@ -0,0 +1,3 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/bin/common/findslot.cpp b/SoftHSMv2/src/bin/common/findslot.cpp
new file mode 100644
index 0000000..5936db7
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/findslot.cpp
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2016 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ findslot.cpp
+
+ Helper function to find the slot
+ *****************************************************************************/
+
+#include <config.h>
+#include "findslot.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern CK_FUNCTION_LIST_PTR p11;
+
+// Find the slot/token
+int findSlot(char* slot, char* serial, char* token, bool freeToken, CK_SLOT_ID& slotID)
+{
+ if (slot != NULL)
+ {
+ int slotNumber = atoi(slot);
+ if (slotNumber < 0)
+ {
+ fprintf(stderr, "ERROR: The slot number is negative.\n");
+ return 1;
+ }
+
+ slotID = slotNumber;
+ return 0;
+ }
+
+ if (serial == NULL && token == NULL && freeToken == false)
+ {
+ fprintf(stderr, "ERROR: A slot/token must be supplied. "
+ "Use --slot <number>, --serial <serial>, "
+ "--token <label>, or --free\n");
+ return 1;
+ }
+
+ // Load the variables
+ CK_UTF8CHAR paddedSerial[16];
+ CK_UTF8CHAR paddedToken[32];
+ if (serial != NULL)
+ {
+ size_t inSize = strlen(serial);
+ size_t outSize = sizeof(paddedSerial);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --serial is too long.\n");
+ return 1;
+ }
+ memset(paddedSerial, ' ', outSize);
+ memcpy(paddedSerial, serial, inSize);
+ }
+ if (token != NULL)
+ {
+ size_t inSize = strlen(token);
+ size_t outSize = sizeof(paddedToken);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --token is too long.\n");
+ return 1;
+ }
+ memset(paddedToken, ' ', outSize);
+ memcpy(paddedToken, token, inSize);
+ }
+
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (pSlotList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ size_t counter = 0;
+ for (CK_ULONG i = 0; i < ulSlotCount; i++)
+ {
+ CK_TOKEN_INFO tokenInfo;
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ free(pSlotList);
+ return 1;
+ }
+
+ if (freeToken)
+ {
+ if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0)
+ {
+ printf("Slot %lu has a free/uninitialized token.\n", pSlotList[i]);
+ slotID = pSlotList[i];
+ free(pSlotList);
+ return 0;
+ }
+ }
+ else
+ {
+ if (serial != NULL && token == NULL &&
+ memcmp(tokenInfo.serialNumber, paddedSerial, sizeof(paddedSerial)) == 0)
+ {
+ printf("Found slot %lu with matching serial.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ if (serial == NULL && token != NULL &&
+ memcmp(tokenInfo.label, paddedToken, sizeof(paddedToken)) == 0)
+ {
+ printf("Found slot %lu with matching token label.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ if (serial != NULL && token != NULL &&
+ memcmp(tokenInfo.serialNumber, paddedSerial, sizeof(paddedSerial)) == 0 &&
+ memcmp(tokenInfo.label, paddedToken, sizeof(paddedToken)) == 0)
+ {
+ printf("Found slot %lu with matching serial and token label.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ }
+ }
+
+ free(pSlotList);
+
+ if (counter == 1) return 0;
+ if (counter > 1)
+ {
+ fprintf(stderr, "ERROR: Found multiple matching slots/tokens.\n");
+ return 1;
+ }
+
+ fprintf(stderr, "ERROR: Could not find a slot/token using --serial, --token, or --free.\n");
+ return 1;
+}
+
+// Find the slot/token
+int findSlot(char* slot, char* serial, char* token, CK_SLOT_ID& slotID)
+{
+ if (slot != NULL)
+ {
+ int slotNumber = atoi(slot);
+ if (slotNumber < 0)
+ {
+ fprintf(stderr, "ERROR: The slot number is negative.\n");
+ return 1;
+ }
+
+ slotID = slotNumber;
+ return 0;
+ }
+
+ if (serial == NULL && token == NULL)
+ {
+ fprintf(stderr, "ERROR: A slot/token must be supplied. "
+ "Use --slot <number>, --serial <serial>, "
+ "or --token <label>\n");
+ return 1;
+ }
+
+ // Load the variables
+ CK_UTF8CHAR paddedSerial[16];
+ CK_UTF8CHAR paddedToken[32];
+ if (serial != NULL)
+ {
+ size_t inSize = strlen(serial);
+ size_t outSize = sizeof(paddedSerial);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --serial is too long.\n");
+ return 1;
+ }
+ memset(paddedSerial, ' ', outSize);
+ memcpy(paddedSerial, serial, inSize);
+ }
+ if (token != NULL)
+ {
+ size_t inSize = strlen(token);
+ size_t outSize = sizeof(paddedToken);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --token is too long.\n");
+ return 1;
+ }
+ memset(paddedToken, ' ', outSize);
+ memcpy(paddedToken, token, inSize);
+ }
+
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (pSlotList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ size_t counter = 0;
+ for (CK_ULONG i = 0; i < ulSlotCount; i++)
+ {
+ CK_TOKEN_INFO tokenInfo;
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ free(pSlotList);
+ return 1;
+ }
+
+ if (serial != NULL && token == NULL &&
+ memcmp(tokenInfo.serialNumber, paddedSerial, sizeof(paddedSerial)) == 0)
+ {
+ printf("Found slot %lu with matching serial.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ if (serial == NULL && token != NULL &&
+ memcmp(tokenInfo.label, paddedToken, sizeof(paddedToken)) == 0)
+ {
+ printf("Found slot %lu with matching token label.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ if (serial != NULL && token != NULL &&
+ memcmp(tokenInfo.serialNumber, paddedSerial, sizeof(paddedSerial)) == 0 &&
+ memcmp(tokenInfo.label, paddedToken, sizeof(paddedToken)) == 0)
+ {
+ printf("Found slot %lu with matching serial and token label.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ }
+
+ free(pSlotList);
+
+ if (counter == 1) return 0;
+ if (counter > 1)
+ {
+ fprintf(stderr, "ERROR: Found multiple matching slots/tokens.\n");
+ return 1;
+ }
+
+ fprintf(stderr, "ERROR: Could not find a slot/token using --serial, or --token\n");
+ return 1;
+}
+
+// Find the slot/token
+int findSlot(CK_TOKEN_INFO tokenInfo, CK_SLOT_ID& slotID)
+{
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (pSlotList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ size_t counter = 0;
+ for (CK_ULONG i = 0; i < ulSlotCount; i++)
+ {
+ CK_TOKEN_INFO currentTokenInfo;
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &currentTokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ free(pSlotList);
+ return 1;
+ }
+
+ if (memcmp(currentTokenInfo.serialNumber, tokenInfo.serialNumber, sizeof(tokenInfo.serialNumber)) == 0 &&
+ memcmp(currentTokenInfo.label, tokenInfo.label, sizeof(tokenInfo.label)) == 0)
+ {
+ slotID = pSlotList[i];
+ counter++;
+ }
+ }
+
+ free(pSlotList);
+
+ if (counter == 1) return 0;
+ if (counter > 1)
+ {
+ fprintf(stderr, "ERROR: Found multiple matching slots/tokens.\n");
+ return 1;
+ }
+
+ fprintf(stderr, "ERROR: Could not find a slot/token using --serial, or --token\n");
+ return 1;
+}
diff --git a/SoftHSMv2/src/bin/common/findslot.h b/SoftHSMv2/src/bin/common/findslot.h
new file mode 100644
index 0000000..f8a7ba6
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/findslot.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ findslot.h
+
+ Helper function to find the slot number
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_FINDSLOT_H
+#define _SOFTHSM_V2_BIN_FINDSLOT_H
+
+#include "cryptoki.h"
+
+int findSlot(char* slot, char* serial, char* token, bool freeToken, CK_SLOT_ID& slotID);
+int findSlot(char* slot, char* serial, char* token, CK_SLOT_ID& slotID);
+int findSlot(CK_TOKEN_INFO tokenInfo, CK_SLOT_ID& slotID);
+
+#endif // !_SOFTHSM_V2_BIN_FINDSLOT_H
diff --git a/SoftHSMv2/src/bin/common/getpw.cpp b/SoftHSMv2/src/bin/common/getpw.cpp
new file mode 100644
index 0000000..938abd5
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/getpw.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ getpw.cpp
+
+ Helper function to get a password from the user
+ *****************************************************************************/
+
+#include <config.h>
+#include "getpw.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <termios.h>
+#include <signal.h>
+#endif
+
+#ifndef _WIN32
+// Remember the signal number
+static volatile sig_atomic_t signo;
+
+void sighandler(int s)
+{
+ signo = s;
+}
+#endif
+
+int getpin(const char* prompt, char* buffer, size_t size)
+{
+ if (prompt == NULL || buffer == NULL || size < 1)
+ return -1;
+
+ printf("%s", prompt);
+
+#ifdef _WIN32
+ HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD mode;
+
+ // Save current console mode
+ if (!GetConsoleMode(hstdin, &mode))
+ return -1;
+
+ // Update the console mode
+ if (hstdin == INVALID_HANDLE_VALUE || !(SetConsoleMode(hstdin, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT)))
+ return -1;
+#else
+ struct termios new_attr, old_attr;
+
+ // Get current terminal attributes
+ if (tcgetattr(STDIN_FILENO, &old_attr) < 0)
+ return -1;
+
+ // Save the mode flags
+ new_attr = old_attr;
+
+ // Update the mode flags
+ new_attr.c_lflag &= ~ICANON;
+ new_attr.c_lflag &= ~ECHO;
+
+ // Handle the SIGINT signal
+ signo = 0;
+ struct sigaction osa, sa;
+ sigaction(SIGINT, NULL, &osa);
+ if (osa.sa_handler != SIG_IGN)
+ {
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = sighandler;
+ sigaction(SIGINT, &sa, &osa);
+ }
+
+ // Set the new terminal attributes
+ if (tcsetattr(STDIN_FILENO, 0, &new_attr) < 0)
+ return -1;
+#endif
+
+ size_t nread = 0;
+ int ch = 0;
+ while ((ch = getchar()) != '\n' && ch != EOF)
+ {
+ // Check buffer size
+ if ((nread+2) > size)
+ continue;
+
+ putchar('*');
+ buffer[nread] = ch;
+ nread++;
+ }
+
+ putchar('\n');
+ buffer[nread] = '\0';
+
+#ifdef _WIN32
+ // Restore the console mode
+ if (!SetConsoleMode(hstdin, mode))
+ return -1;
+#else
+ // Restore terminal
+ if (tcsetattr(STDIN_FILENO, 0, &old_attr) < 0)
+ return -1;
+
+ // Restore the signal
+ sigaction(SIGINT, &osa, NULL);
+ if (signo)
+ raise(signo);
+#endif
+
+ return nread;
+}
+
+// Get a password from the user
+int getPW(char* pin, char* newPIN, CK_ULONG userType)
+{
+ char password1[MAX_PIN_LEN+1];
+ char password2[MAX_PIN_LEN+1];
+ size_t size = MAX_PIN_LEN+1;
+ int length = 0;
+
+ // Check if the user has provided a password
+ if (pin)
+ {
+ length = strlen(pin);
+ // Save the PIN if it has the correct length
+ if (length >= MIN_PIN_LEN && length <= MAX_PIN_LEN)
+ memcpy(password1, pin, length+1);
+ }
+
+ while (length < MIN_PIN_LEN || length > MAX_PIN_LEN)
+ {
+ if (userType == CKU_SO)
+ {
+ printf("=== SO PIN (%i-%i characters) ===\n",
+ MIN_PIN_LEN, MAX_PIN_LEN);
+ length = getpin("Please enter SO PIN: ",
+ password1, size);
+ }
+ else
+ {
+ printf("=== User PIN (%i-%i characters) ===\n",
+ MIN_PIN_LEN, MAX_PIN_LEN);
+ length = getpin("Please enter user PIN: ",
+ password1, size);
+ }
+
+ if (length < 0)
+ return 1;
+ if (length < MIN_PIN_LEN || length > MAX_PIN_LEN)
+ {
+ fprintf(stderr, "ERROR: The length of the PIN is out of range.\n");
+ length = 0;
+ continue;
+ }
+
+ if (userType == CKU_SO)
+ {
+ length = getpin("Please reenter SO PIN: ",
+ password2, size);
+ }
+ else
+ {
+ length = getpin("Please reenter user PIN: ",
+ password2, size);
+ }
+
+ if (length < 0)
+ return 1;
+ if (strcmp(password1, password2))
+ {
+ fprintf(stderr, "ERROR: The entered PINs are not equal.\n");
+ length = 0;
+ continue;
+ }
+ }
+
+ memcpy(newPIN, password1, length+1);
+ return 0;
+}
diff --git a/SoftHSMv2/src/bin/common/getpw.h b/SoftHSMv2/src/bin/common/getpw.h
new file mode 100644
index 0000000..1ca15a5
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/getpw.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ getpw.h
+
+ Helper function to get a password from the user
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_GETPW_H
+#define _SOFTHSM_V2_BIN_GETPW_H
+
+#include "cryptoki.h"
+
+int getPW(char* pin, char* newPIN, CK_ULONG userType);
+
+#endif // !_SOFTHSM_V2_BIN_GETPW_H
diff --git a/SoftHSMv2/src/bin/common/library.cpp b/SoftHSMv2/src/bin/common/library.cpp
new file mode 100644
index 0000000..af0dd93
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/library.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ library.cpp
+
+ Support function for handling PKCS#11 libraries
+ *****************************************************************************/
+
+#include <config.h>
+#include "library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_DLOPEN)
+#include <dlfcn.h>
+#endif
+
+// Load the PKCS#11 library
+CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle,
+ char **pErrMsg)
+{
+ CK_C_GetFunctionList pGetFunctionList = NULL;
+
+#if defined(HAVE_LOADLIBRARY)
+ HINSTANCE hDLL = NULL;
+ DWORD dw = NULL;
+ static char errMsg[100];
+
+ // Load PKCS #11 library
+ if (module)
+ {
+ hDLL = LoadLibraryA(module);
+ }
+ else
+ {
+ hDLL = LoadLibraryA(DEFAULT_PKCS11_LIB);
+ }
+
+ if (hDLL == NULL)
+ {
+ // Failed to load the PKCS #11 library
+ dw = GetLastError();
+ snprintf((char*)errMsg, sizeof(errMsg), "LoadLibraryA failed: 0x%08X", dw);
+ *pErrMsg = errMsg;
+ return NULL;
+ }
+ else
+ {
+ *pErrMsg = NULL;
+ }
+
+ // Retrieve the entry point for C_GetFunctionList
+ pGetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hDLL, "C_GetFunctionList");
+ if (pGetFunctionList == NULL)
+ {
+ dw = GetLastError();
+ snprintf((char*)errMsg, sizeof(errMsg), "getProcAddress failed: 0x%08X", dw);
+ *pErrMsg = errMsg;
+ FreeLibrary(hDLL);
+ return NULL;
+ }
+
+ // Store the handle so we can FreeLibrary it later
+ *moduleHandle = hDLL;
+
+#elif defined(HAVE_DLOPEN)
+ void* pDynLib = NULL;
+
+ // Load PKCS #11 library
+ if (module)
+ {
+ pDynLib = dlopen(module, RTLD_NOW | RTLD_LOCAL);
+ }
+ else
+ {
+ pDynLib = dlopen(DEFAULT_PKCS11_LIB, RTLD_NOW | RTLD_LOCAL);
+ }
+
+ *pErrMsg = dlerror();
+ if (pDynLib == NULL || *pErrMsg != NULL)
+ {
+ if (pDynLib != NULL) dlclose(pDynLib);
+
+ // Failed to load the PKCS #11 library
+ return NULL;
+ }
+
+ // Retrieve the entry point for C_GetFunctionList
+ pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
+
+ // Store the handle so we can dlclose it later
+ *pErrMsg = dlerror();
+ if (*pErrMsg != NULL)
+ {
+ dlclose(pDynLib);
+
+ // An error occured during dlsym()
+ return NULL;
+ }
+
+ *moduleHandle = pDynLib;
+#else
+ fprintf(stderr, "ERROR: Not compiled with library support.\n");
+
+ return NULL;
+#endif
+
+ return pGetFunctionList;
+}
+
+void unloadLibrary(void* moduleHandle)
+{
+ if (moduleHandle)
+ {
+#if defined(HAVE_LOADLIBRARY)
+ FreeLibrary((HMODULE) moduleHandle);
+#elif defined(HAVE_DLOPEN)
+ dlclose(moduleHandle);
+#endif
+ }
+}
diff --git a/SoftHSMv2/src/bin/common/library.h b/SoftHSMv2/src/bin/common/library.h
new file mode 100644
index 0000000..6c6b3e4
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/library.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ library.h
+
+ Support function for handling PKCS#11 libraries
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_LIBRARY_H
+#define _SOFTHSM_V2_BIN_LIBRARY_H
+
+#include "cryptoki.h"
+
+CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle,
+ char **pErrMsg);
+void unloadLibrary(void* moduleHandle);
+
+#endif // !_SOFTHSM_V2_BIN_LIBRARY_H
diff --git a/SoftHSMv2/src/bin/dump/Makefile.am b/SoftHSMv2/src/bin/dump/Makefile.am
new file mode 100644
index 0000000..c70d6f6
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/Makefile.am
@@ -0,0 +1,24 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib \
+ -I$(srcdir)/../../lib/object_store \
+ -I$(srcdir)/../../lib/pkcs11 \
+ @SQLITE3_INCLUDES@
+
+dist_man_MANS = softhsm2-dump-file.1
+
+bin_PROGRAMS = softhsm2-dump-file
+
+if BUILD_OBJECTSTORE_BACKEND_DB
+dist_man_MANS += softhsm2-dump-db.1
+bin_PROGRAMS += softhsm2-dump-db
+endif
+
+softhsm2_dump_file_SOURCES = softhsm2-dump-file.cpp
+
+softhsm2_dump_db_SOURCES = softhsm2-dump-db.cpp
+
+softhsm2_dump_db_LDADD = @SQLITE3_LIBS@ @YIELD_LIB@
+
+EXTRA_DIST = $(srcdir)/*.h \
+ softhsm2-dump-db.1
diff --git a/SoftHSMv2/src/bin/dump/common.h b/SoftHSMv2/src/bin/dump/common.h
new file mode 100644
index 0000000..d38b924
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/common.h
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2013 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ common.h
+
+ Common definitions for SoftHSMv2 dump.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_COMMON_H
+#define _SOFTHSM_V2_COMMON_H
+
+#include <config.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <map>
+#include <set>
+#include <string>
+#include <stdexcept>
+#include <vector>
+#include "tables.h"
+
+// Table of attribute types
+std::map<unsigned long, std::string> CKA_table;
+
+// Dump an attribute type
+void dumpCKA(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKA_table.empty())
+ {
+ fill_CKA_table(CKA_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKA_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKA_VENDOR_DEFINED)
+ {
+ cka &= ~CKA_VENDOR_DEFINED;
+ printf("CKA_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of mechanism types
+std::map<unsigned long, std::string> CKM_table;
+
+// Dump a mechanism type
+void dumpCKM(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKM_table.empty())
+ {
+ fill_CKM_table(CKM_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKM_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKM_VENDOR_DEFINED)
+ {
+ cka &= ~CKM_VENDOR_DEFINED;
+ printf("CKM_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of object classes
+std::map<unsigned long, std::string> CKO_table;
+
+// Dump a object class
+void dumpCKO(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKO_table.empty())
+ {
+ fill_CKO_table(CKO_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKO_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKO_VENDOR_DEFINED)
+ {
+ cka &= ~CKO_VENDOR_DEFINED;
+ printf("CKO_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of hw feature types
+std::map<unsigned long, std::string> CKH_table;
+
+// Dump a hw feature type
+void dumpCKH(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKH_table.empty())
+ {
+ fill_CKH_table(CKH_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKH_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKH_VENDOR_DEFINED)
+ {
+ cka &= ~CKH_VENDOR_DEFINED;
+ printf("CKH_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of key types
+std::map<unsigned long, std::string> CKK_table;
+
+// Dump a key type
+void dumpCKK(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKK_table.empty())
+ {
+ fill_CKK_table(CKK_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKK_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKK_VENDOR_DEFINED)
+ {
+ cka &= ~CKK_VENDOR_DEFINED;
+ printf("CKK_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of certificate types
+std::map<unsigned long, std::string> CKC_table;
+
+// Dump a certificate type
+void dumpCKC(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKC_table.empty())
+ {
+ fill_CKC_table(CKC_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKC_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKC_VENDOR_DEFINED)
+ {
+ cka &= ~CKC_VENDOR_DEFINED;
+ printf("CKC_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Dump a PKCS#11 integer type
+void dumpCKx(uint64_t cka, uint64_t value, int size)
+{
+ if ((uint32_t)value == (uint32_t)~0)
+ {
+ printf("CK_UNAVAILABLE_INFORMATION");
+ return;
+ }
+
+ switch ((unsigned long) cka)
+ {
+ case CKA_CLASS:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow object class");
+ break;
+ }
+ dumpCKO((unsigned long) value, size);
+ break;
+ case CKA_CERTIFICATE_TYPE:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow certificate type");
+ break;
+ }
+ dumpCKC((unsigned long) value, size);
+ break;
+ case CKA_KEY_TYPE:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow key type");
+ break;
+ }
+ dumpCKK((unsigned long) value, size);
+ break;
+ case CKA_KEY_GEN_MECHANISM:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow mechanism type");
+ break;
+ }
+ dumpCKM((unsigned long) value, size);
+ break;
+ case CKA_HW_FEATURE_TYPE:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow hw feature type");
+ break;
+ }
+ dumpCKH((unsigned long) value, size);
+ break;
+ default:
+ printf("CK_ULONG %lu(0x%lx)",
+ (unsigned long) value,
+ (unsigned long) value);
+ break;
+ }
+}
+
+// Dump a boolean (in fact unsigned 8 bit long) value, true is 0xff
+void dumpBool(uint8_t value, bool inArray = false)
+{
+ printf("%02hhx %s", value, inArray ? " " : "");
+ switch (value)
+ {
+ case 0:
+ printf("FALSE");
+ break;
+ case 0xff:
+ printf("TRUE");
+ break;
+ default:
+ printf("(invalid) TRUE");
+ break;
+ }
+}
+
+// Dump a boolean (in fact unsigned 8 bit long) value, true is 1
+void dumpBool1(uint8_t value, bool inArray = false)
+{
+ printf("%02hhx %s", value, inArray ? " " : "");
+ switch (value)
+ {
+ case 0:
+ printf("FALSE");
+ break;
+ case 1:
+ printf("TRUE");
+ break;
+ default:
+ printf("(invalid) TRUE");
+ break;
+ }
+}
+
+// Dump an unsigned 64 bit long value
+void dumpULong(uint64_t value, bool inArray = false)
+{
+ for (int i = 56; i >= 0; i -= 8)
+ {
+ uint8_t v;
+ v = (value >> i) & 0xff;
+ printf("%02hhx ", v);
+ }
+ if (inArray)
+ {
+ printf(" ");
+ }
+}
+
+// Dump an unsigned 32 bit long value
+void dumpU32(uint32_t value, bool inArray = false)
+{
+ for (int i = 24; i >= 0; i -= 8)
+ {
+ uint8_t v;
+ v = (value >> i) & 0xff;
+ printf("%02hhx ", v);
+ }
+ printf(" ");
+ if (inArray)
+ {
+ printf(" ");
+ }
+}
+
+// Dump a byte string (aka uint8_t vector) value
+void dumpBytes(const std::vector<uint8_t>& value, bool inArray = false)
+{
+ size_t len = value.size();
+ size_t i = 0;
+ while (i + 8 <= len)
+ {
+ for (size_t j = 0; j < 8; j++)
+ {
+ printf("%02hhx ", value[i + j]);
+ }
+ if (inArray)
+ {
+ printf(" ");
+ }
+ printf("<");
+ for (size_t j = 0; j < 8; j++)
+ {
+ uint8_t c = value[i + j];
+ if (isgraph((int) c) == 0)
+ {
+ printf(".");
+ }
+ else
+ {
+ printf("%c", (int) c);
+ }
+ }
+ printf(">\n");
+ i += 8;
+ }
+ len -= i;
+ if (len == 0)
+ {
+ return;
+ }
+
+ for (size_t j = 0; j < len; j++)
+ {
+ printf("%02hhx ", value[i + j]);
+ }
+ for (size_t j = len; j < 8; j++)
+ {
+ printf(" ");
+ }
+ if (inArray)
+ {
+ printf(" ");
+ }
+ printf("<");
+ for (size_t j = 0; j < len; j++)
+ {
+ uint8_t c = value[i + j];
+ if (isgraph((int) c) == 0)
+ {
+ printf(".");
+ }
+ else
+ {
+ printf("%c", (int) c);
+ }
+ }
+ for (size_t j =len; j < 8; j++)
+ {
+ printf(" ");
+ }
+ printf(">\n");
+}
+
+// Attribute (in an array) template
+template<typename T, typename K, typename I>
+class AttributeTK
+{
+public:
+ T type;
+ K kind;
+
+ uint8_t boolValue;
+ I ulongValue;
+ std::vector<uint8_t> bytestrValue;
+ std::set<I> mechSetValue;
+
+ // Dump an array (in fact an Attribute vector) value
+ void dumpType() const;
+ void dumpKind() const;
+ void dumpBoolValue() const;
+ void dumpULongValue(I value) const;
+ bool isBoolean() const;
+ bool isInteger() const;
+ bool isBinary() const;
+ bool isMechSet() const;
+ void dump() const {
+ dumpType();
+ if ((sizeof(type) > 4) &&
+ ((uint64_t)((uint32_t)type) != type))
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 47);
+ printf("\n");
+ }
+
+ dumpKind();
+ if (isBoolean())
+ {
+ printf("boolean attribute\n");
+ dumpBoolValue();
+ printf("\n");
+ }
+ else if (isInteger())
+ {
+ printf("unsigned long attribute\n");
+ dumpULongValue(ulongValue);
+ dumpCKx(type, ulongValue, 47);
+ printf("\n");
+ }
+ else if (isBinary())
+ {
+ printf("byte string attribute\n");
+ I size = bytestrValue.size();
+ dumpULongValue(size);
+ printf("(length %lu)\n", (unsigned long) size);
+ dumpBytes(bytestrValue, true);
+ }
+ else if (isMechSet())
+ {
+ printf("mechanism set attribute\n");
+ I size = mechSetValue.size();
+ dumpULongValue(size);
+ printf("(length %lu)\n", (unsigned long) size);
+ for (typename std::set<I>::const_iterator i = mechSetValue.begin(); i != mechSetValue.end(); ++i)
+ {
+ dumpULongValue(*i);
+ dumpCKM(*i, 47);
+ printf("\n");
+ }
+ }
+ else
+ {
+ printf("unknown attribute format\n");
+ }
+ }
+};
+
+#endif // !_SOFTHSM_V2_COMMON_H
diff --git a/SoftHSMv2/src/bin/dump/softhsm2-dump-db.1 b/SoftHSMv2/src/bin/dump/softhsm2-dump-db.1
new file mode 100644
index 0000000..00f455b
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/softhsm2-dump-db.1
@@ -0,0 +1,18 @@
+.TH SOFTHSM2-DUMP-DB 1 "20 March 2014" "SoftHSM"
+.SH NAME
+softhsm2-dump-db \- SoftHSM database dump
+.SH SYNOPSIS
+.PP
+.B softhsm2-dump-db
+.I path
+.SH DESCRIPTION
+.B softhsm2-dump
+is a tool that can dump SoftHSM v2 database for debugging purposes.
+.LP
+.SH OPTIONS
+.TP
+.B \fIpath\fR
+The SoftHSM v2 database file that is going to be dumped.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
diff --git a/SoftHSMv2/src/bin/dump/softhsm2-dump-db.cpp b/SoftHSMv2/src/bin/dump/softhsm2-dump-db.cpp
new file mode 100644
index 0000000..f55a9db
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/softhsm2-dump-db.cpp
@@ -0,0 +1,968 @@
+/*
+ * Copyright (c) 2013 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-dump-db.cpp
+
+ This program can be used for dumping SoftHSM v2 database.
+ *****************************************************************************/
+
+#include <config.h>
+
+#include <sched.h>
+#include <sqlite3.h>
+#include <string.h>
+
+#include "common.h"
+
+// Attribute types in database arrays
+enum AttributeKind
+{
+ akUnknown,
+ akBoolean,
+ akInteger,
+ akBinary,
+ akArray
+};
+
+// Attribute specialization
+typedef AttributeTK<CK_ATTRIBUTE_TYPE, AttributeKind, unsigned long> Attribute;
+
+template<>
+bool Attribute::isBoolean() const
+{
+ return kind == akBoolean;
+}
+
+template<>
+bool Attribute::isInteger() const
+{
+ return kind == akInteger;
+}
+
+template<>
+bool Attribute::isBinary() const
+{
+ return kind == akBinary;
+}
+
+template<>
+bool Attribute::isMechSet() const
+{
+ // Mechanism sets are stored as binary in the database
+ return false;
+}
+
+template<>
+void Attribute::dumpType() const
+{
+ if (sizeof(type) == 4)
+ {
+ dumpU32((uint32_t)type, true);
+ }
+ else
+ {
+ dumpULong(type, true);
+ }
+}
+
+template<>
+void Attribute::dumpKind() const
+{
+ dumpU32((uint32_t) kind, true);
+}
+
+template<>
+void Attribute::dumpBoolValue() const
+{
+ dumpBool1(boolValue, true);
+}
+
+template<>
+void Attribute::dumpULongValue(unsigned long value) const
+{
+ if (sizeof(unsigned long) == 4)
+ {
+ dumpU32(value, true);
+ }
+ else
+ {
+ dumpULong(value, true);
+ }
+}
+
+// dumpArray specialization
+typedef std::vector<Attribute> va_type;
+
+void dumpArray(const va_type& value)
+{
+ for (va_type::const_iterator attr = value.begin(); attr != value.end(); ++attr)
+ attr->dump();
+}
+
+// Get a boolean (in fact unsigned 8 bit long) value
+bool getBool(sqlite3* db, long long oid, long long id, uint64_t& type, uint8_t& value)
+{
+ int rv;
+ sqlite3_stmt* sql = NULL;
+ std::string command = "select type,value from attribute_boolean where object_id=? and id=?;";
+
+ value = 0;
+
+ rv = sqlite3_prepare_v2(db, command.c_str(), -1, &sql, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr,
+ "can't find boolean attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ rv = sqlite3_bind_int64(sql, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ sqlite3_bind_int64(sql, 2, id);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the attribute id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ while ((rv = sqlite3_step(sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr,
+ "can't read boolean attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ type = sqlite3_column_int64(sql, 0);
+ value = sqlite3_column_int(sql, 1);
+ sqlite3_finalize(sql);
+
+ return true;
+}
+
+// Get an unsigned 64 bit long value
+bool getULong(sqlite3* db, long long oid, long long id, uint64_t& type, uint64_t& value)
+{
+ int rv;
+ sqlite3_stmt* sql = NULL;
+ std::string command = "select type,value from attribute_integer where object_id=? and id=?;";
+
+ value = 0ULL;
+
+ rv = sqlite3_prepare_v2(db, command.c_str(), -1, &sql, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr,
+ "can't find integer attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ rv = sqlite3_bind_int64(sql, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ sqlite3_bind_int64(sql, 2, id);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the attribute id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ while ((rv = sqlite3_step(sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr,
+ "can't read integer attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ type = sqlite3_column_int64(sql, 0);
+ value = sqlite3_column_int64(sql, 1);
+ sqlite3_finalize(sql);
+
+ return true;
+}
+
+// Get a byte string (aka uint8_t vector) value
+bool getBytes(sqlite3* db, long long oid, long long id, uint64_t& type, std::vector<uint8_t>& value)
+{
+ int rv;
+ sqlite3_stmt* sql = NULL;
+ std::string command = "select type,value from attribute_binary where object_id=? and id=?;";
+ size_t len;
+ const uint8_t* val;
+
+ value.clear();
+
+ rv = sqlite3_prepare_v2(db, command.c_str(), -1, &sql, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr,
+ "can't find binary attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ rv = sqlite3_bind_int64(sql, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ sqlite3_bind_int64(sql, 2, id);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the attribute id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ while ((rv = sqlite3_step(sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr,
+ "can't read binary attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ type = sqlite3_column_int64(sql, 0);
+ len = sqlite3_column_bytes(sql, 1);
+ val = (const uint8_t*) sqlite3_column_blob(sql, 1);
+ for (size_t i = 0; i < len; ++i)
+ {
+ value.push_back(val[i]);
+ }
+ sqlite3_finalize(sql);
+
+ return true;
+}
+
+// Get an array (aka Attribute vector) value
+bool getArray(sqlite3* db, long long oid, long long id, uint64_t& type, std::vector<Attribute>& value)
+{
+ int rv;
+ sqlite3_stmt* sql = NULL;
+ std::string command = "select type,value from attribute_array where object_id=? and id=?;";
+ size_t len;
+ const uint8_t* val;
+
+ value.clear();
+
+ rv = sqlite3_prepare_v2(db, command.c_str(), -1, &sql, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr,
+ "can't find array attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ rv = sqlite3_bind_int64(sql, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ sqlite3_bind_int64(sql, 2, id);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the attribute id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ while ((rv = sqlite3_step(sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr,
+ "can't read array attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ type = sqlite3_column_int64(sql, 0);
+ len = sqlite3_column_bytes(sql, 1);
+ val = (const uint8_t*) sqlite3_column_blob(sql, 1);
+
+// CK_ATTRIBUTE_TYPE type, AttributeKind kind
+// bool -> int, integer -> unsigned long, binary -> unsigned long + vector
+
+ for (size_t pos = 0; pos < len; )
+ {
+ // finished?
+ if (pos == len) break;
+
+ Attribute attr;
+
+ if (pos + sizeof(attr.type) > len)
+ {
+ fprintf(stderr, "overflow array item type\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&attr.type, val + pos, sizeof(attr.type));
+ pos += sizeof(attr.type);
+
+ if (pos + sizeof(attr.kind) > len)
+ {
+ fprintf(stderr, "overflow array item kind\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&attr.kind, val + pos, sizeof(attr.kind));
+ pos += sizeof(attr.kind);
+
+ if (attr.kind == akBoolean)
+ {
+ if (pos + sizeof(attr.boolValue) > len)
+ {
+ fprintf(stderr, "overflow array boolean item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&attr.boolValue, val + pos, sizeof(attr.boolValue));
+ pos += sizeof(attr.boolValue);
+ }
+ else if (attr.kind == akInteger)
+ {
+ if (pos + sizeof(attr.ulongValue) > len)
+ {
+ fprintf(stderr, "overflow array integer item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&attr.ulongValue, val + pos, sizeof(attr.ulongValue));
+ pos += sizeof(attr.ulongValue);
+ }
+ else if (attr.kind == akBinary)
+ {
+ unsigned long size;
+ if (pos + sizeof(size) > len)
+ {
+ fprintf(stderr, "overflow array binary item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&size, val + pos, sizeof(size));
+ pos += sizeof(size);
+
+ if (pos + size > len)
+ {
+ fprintf(stderr, "overflow array binary item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ attr.bytestrValue.resize(size);
+ for (unsigned long i = 0; i < size; ++i)
+ {
+ attr.bytestrValue[i] = val[pos + i];
+ }
+ pos += size;
+ }
+ else
+ {
+ fprintf(stderr, "unknown array item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+
+ value.push_back(attr);
+ }
+ sqlite3_finalize(sql);
+
+ return true;
+}
+
+// Dump boolean attributes of an object
+void dump_booleans(sqlite3* db, long long oid)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from attribute_boolean where object_id=?;";
+ std::string commandid = "select id from attribute_boolean where object_id=?;";
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlcnt, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ if (count == 0)
+ return;
+
+ printf("%lu boolean attributes for object %lld\n", count, oid);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlid, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long id = sqlite3_column_int64(sqlid, 0);
+
+ uint64_t type;
+ uint8_t value;
+ if (!getBool(db, oid, id, type, value))
+ {
+ return;
+ }
+ dumpULong(type);
+ if ((uint64_t)((uint32_t)type) != type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 48);
+ printf("\n");
+ }
+
+ dumpBool1(value);
+ printf("\n");
+ }
+}
+
+// Dump integer attributes of an object
+void dump_integers(sqlite3* db, long long oid)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from attribute_integer where object_id=?;";
+ std::string commandid = "select id from attribute_integer where object_id=?;";
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlcnt, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ if (count == 0)
+ return;
+
+ printf("%lu integer attributes for object %lld\n", count, oid);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlid, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long id = sqlite3_column_int64(sqlid, 0);
+
+ uint64_t type;
+ uint64_t value;
+ if (!getULong(db, oid, id, type, value))
+ {
+ return;
+ }
+ dumpULong(type);
+ if ((uint64_t)((uint32_t)type) != type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 48);
+ printf("\n");
+ }
+ dumpULong(value);
+ dumpCKx(type, value, 48);
+ printf("\n");
+ }
+}
+
+// Dump binary attributes of an object
+void dump_binaries(sqlite3* db, long long oid)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from attribute_binary where object_id=?;";
+ std::string commandid = "select id from attribute_binary where object_id=?;";
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlcnt, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ if (count == 0)
+ return;
+
+ printf("%lu binary attributes for object %lld\n", count, oid);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlid, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long id = sqlite3_column_int64(sqlid, 0);
+
+ uint64_t type;
+ std::vector<uint8_t> value;
+ if (!getBytes(db, oid, id, type, value))
+ {
+ return;
+ }
+ dumpULong(type);
+ if ((uint64_t)((uint32_t)type) != type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 48);
+ printf("\n");
+ }
+ dumpULong((uint64_t) value.size());
+ printf("(length %lu)\n", (unsigned long) value.size());
+ dumpBytes(value);
+ }
+}
+
+// Dump array attributes of an object
+void dump_arrays(sqlite3* db, long long oid)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from attribute_array where object_id=?;";
+ std::string commandid = "select id from attribute_array where object_id=?;";
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlcnt, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ if (count == 0)
+ return;
+
+ printf("%lu array attributes for object %lld\n", count, oid);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlid, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long id = sqlite3_column_int64(sqlid, 0);
+
+ uint64_t type;
+ std::vector<Attribute> value;
+ if (!getArray(db, oid, id, type, value))
+ {
+ return;
+ }
+ dumpULong(type);
+ if ((uint64_t)((uint32_t)type) != type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 48);
+ printf("\n");
+ }
+ dumpULong((uint64_t) value.size());
+ printf("(length %lu)\n", (unsigned long) value.size());
+ dumpArray(value);
+ }
+}
+
+// Dump an object
+void dump_object(sqlite3* db, long long oid)
+{
+ printf("dump object id=%lld\n", oid);
+ dump_booleans(db, oid);
+ dump_integers(db, oid);
+ dump_binaries(db, oid);
+ dump_arrays(db, oid);
+}
+
+// Core function
+void dump(sqlite3* db)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from object;";
+ std::string commandid = "select id from object;";
+
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ printf("%lu objects\n", count);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long oid = sqlite3_column_int64(sqlid, 0);
+ dump_object(db, oid);
+ }
+}
+
+// Display the usage
+void usage()
+{
+ printf("SoftHSM dump tool. From SoftHSM v2 database.\n");
+ printf("Usage: softhsm2-dump-db path\n");
+}
+
+// Check the existence of a table
+void check_table_exist(sqlite3* db, std::string name)
+{
+ int rv;
+ std::string command = "select count(id) from " + name + ";";
+
+ rv = sqlite3_exec(db, command.c_str(), NULL, NULL, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't find '%s' table\n", name.c_str());
+ sqlite3_close(db);
+ exit(0);
+ }
+}
+
+// The main function
+int main(int argc, char* argv[])
+{
+ int rv;
+ sqlite3* db = NULL;
+
+ if (argc != 2)
+ {
+ usage();
+ exit(0);
+ }
+
+ rv = sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READONLY, NULL);
+ if (rv != SQLITE_OK)
+ {
+ if (db == NULL)
+ {
+ fprintf(stderr,
+ "can't open database file %s\n",
+ argv[1]);
+ }
+ else
+ {
+ fprintf(stderr,
+ "can't open database file %s: %d(%s)\n",
+ argv[1],
+ rv,
+ sqlite3_errmsg(db));
+ }
+ sqlite3_close(db);
+ exit(0);
+ }
+
+ // No user version to check
+
+ check_table_exist(db, "object");
+ check_table_exist(db, "attribute_boolean");
+ check_table_exist(db, "attribute_integer");
+ check_table_exist(db, "attribute_binary");
+ check_table_exist(db, "attribute_array");
+
+ printf("Dump of object file \"%s\"\n", argv[1]);
+ dump(db);
+ sqlite3_close(db);
+ exit(1);
+}
diff --git a/SoftHSMv2/src/bin/dump/softhsm2-dump-file.1 b/SoftHSMv2/src/bin/dump/softhsm2-dump-file.1
new file mode 100644
index 0000000..5167f70
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/softhsm2-dump-file.1
@@ -0,0 +1,18 @@
+.TH SOFTHSM2-DUMP-FILE 1 "20 March 2014" "SoftHSM"
+.SH NAME
+softhsm2-dump-file \- SoftHSM object file dump
+.SH SYNOPSIS
+.PP
+.B softhsm2-dump-file
+.I path
+.SH DESCRIPTION
+.B softhsm2-dump-file
+is a tool that can dump SoftHSM v2 object file for debugging purposes.
+.LP
+.SH OPTIONS
+.TP
+.B \fIpath\fR
+The SoftHSM v2 object file that is going to be dumped.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
diff --git a/SoftHSMv2/src/bin/dump/softhsm2-dump-file.cpp b/SoftHSMv2/src/bin/dump/softhsm2-dump-file.cpp
new file mode 100644
index 0000000..994f67e
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/softhsm2-dump-file.cpp
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 2013 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-dump-file.cpp
+
+ This program can be used for dumping SoftHSM v2 object files.
+ *****************************************************************************/
+
+#include <config.h>
+
+#include "common.h"
+
+// Attribute types on disk
+#define BOOLEAN_ATTR 0x1
+#define ULONG_ATTR 0x2
+#define BYTES_ATTR 0x3
+#define ATTRMAP_ATTR 0x4
+#define MECHSET_ATTR 0x5
+
+// Maximum byte string length (1Gib)
+#define MAX_BYTES 0x3fffffff
+
+typedef AttributeTK<uint64_t, uint64_t, uint64_t> Attribute;
+
+// Attribute specialization
+template<>
+bool Attribute::isBoolean() const
+{
+ return kind == BOOLEAN_ATTR;
+}
+
+template<>
+bool Attribute::isInteger() const
+{
+ return kind == ULONG_ATTR;
+}
+
+template<>
+bool Attribute::isBinary() const
+{
+ return kind == BYTES_ATTR;
+}
+
+template<>
+bool Attribute::isMechSet() const
+{
+ return kind == MECHSET_ATTR;
+}
+
+template<>
+void Attribute::dumpType() const
+{
+ dumpULong(type, true);
+}
+
+template<>
+void Attribute::dumpKind() const
+{
+ dumpULong(kind, true);
+}
+
+template<>
+void Attribute::dumpBoolValue() const
+{
+ dumpBool(boolValue, true);
+}
+
+template<>
+void Attribute::dumpULongValue(uint64_t value) const
+{
+ dumpULong(value, true);
+}
+
+// dumpMap specialization
+typedef std::vector<Attribute> va_type;
+
+void dumpMap(const va_type& value)
+{
+ for (va_type::const_iterator attr = value.begin(); attr != value.end(); ++attr)
+ attr->dump();
+}
+
+// Read a boolean (in fact unsigned 8 bit long) value
+bool readBool(FILE* stream, uint8_t& value)
+{
+ value = 0;
+ fpos_t pos;
+ if (fgetpos(stream, &pos) != 0)
+ {
+ return false;
+ }
+ uint8_t v;
+ if (fread(&v, 1, 1, stream) != 1)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ value = v;
+ return true;
+}
+
+// Read an unsigned 64 bit long value
+bool readULong(FILE* stream, uint64_t& value)
+{
+ value = 0;
+ fpos_t pos;
+ if (fgetpos(stream, &pos) != 0)
+ {
+ return false;
+ }
+ uint8_t v[8];
+ if (fread(v, 1, 8, stream) != 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ for (size_t i = 0; i < 8; i++)
+ {
+ value <<= 8;
+ value += v[i];
+ }
+ return true;
+}
+
+// Read a byte string (aka uint8_t vector) value
+bool readBytes(FILE* stream, std::vector<uint8_t>& value)
+{
+ size_t len = value.size();
+ fpos_t pos;
+ if (fgetpos(stream, &pos) != 0)
+ {
+ return false;
+ }
+ if (fread(&value[0], 1, len, stream) != len)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ return true;
+}
+
+// Read a map (aka Attribute vector) value
+bool readMap(FILE* stream, uint64_t len, std::vector<Attribute>& value)
+{
+ fpos_t pos;
+ if (fgetpos(stream, &pos) != 0)
+ {
+ return false;
+ }
+ while (len != 0)
+ {
+ Attribute attr;
+
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, attr.type))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, attr.kind))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+
+ if (attr.kind == BOOLEAN_ATTR)
+ {
+ if (len < 1)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 1;
+ if (!readBool(stream, attr.boolValue))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ }
+ else if (attr.kind == ULONG_ATTR)
+ {
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, attr.ulongValue))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+ }
+ else if (attr.kind == BYTES_ATTR)
+ {
+ uint64_t size;
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, size))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+
+ if (len < size)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ attr.bytestrValue.resize((size_t)size);
+ if (!readBytes(stream, attr.bytestrValue))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= size;
+ }
+ else if (attr.kind == MECHSET_ATTR)
+ {
+ uint64_t size;
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, size))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+
+ if (len < size * 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+
+ for (unsigned long i = 0; i < size; i++)
+ {
+ uint64_t mech;
+ if (!readULong(stream, mech))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ attr.mechSetValue.insert(mech);
+ }
+ len -= size * 8;
+ }
+ else
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+
+ value.push_back(attr);
+ }
+
+ return true;
+}
+
+// Error case
+void corrupt(FILE* stream)
+{
+ uint8_t v;
+ for (size_t i = 0; i < 8; i++)
+ {
+ if (fread(&v, 1, 1, stream) != 1)
+ {
+ if (ferror(stream))
+ {
+ printf("get an error...\n");
+ }
+ return;
+ }
+ if (i != 0)
+ {
+ printf(" ");
+ }
+ printf("%02hhx", v);
+ }
+ if (fread(&v, 1, 1, stream) != 1)
+ {
+ if (ferror(stream))
+ {
+ printf("\nget an error...\n");
+ }
+ return;
+ }
+ printf("...\n");
+}
+
+// Core function
+void dump(FILE* stream)
+{
+ uint64_t gen;
+ if (!readULong(stream, gen))
+ {
+ if (feof(stream))
+ {
+ printf("empty file\n");
+ }
+ else
+ {
+ corrupt(stream);
+ }
+ return;
+ }
+ dumpULong(gen);
+ printf("generation %lu\n", (unsigned long) gen);
+
+ while (!feof(stream))
+ {
+ uint64_t p11type;
+ if (!readULong(stream, p11type))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(p11type);
+ if ((uint64_t)((uint32_t)p11type) != p11type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) p11type, 48);
+ printf("\n");
+ }
+
+ uint64_t disktype;
+ if (!readULong(stream, disktype))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(disktype);
+ switch (disktype)
+ {
+ case BOOLEAN_ATTR:
+ printf("boolean attribute\n");
+ break;
+ case ULONG_ATTR:
+ printf("unsigned long attribute\n");
+ break;
+ case BYTES_ATTR:
+ printf("byte string attribute\n");
+ break;
+ case ATTRMAP_ATTR:
+ printf("attribute map attribute\n");
+ break;
+ case MECHSET_ATTR:
+ printf("mechanism set attribute\n");
+ break;
+ default:
+ printf("unknown attribute format\n");
+ break;
+ }
+
+ if (disktype == BOOLEAN_ATTR)
+ {
+ uint8_t value;
+ if (!readBool(stream, value))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpBool(value);
+ printf("\n");
+ }
+ else if (disktype == ULONG_ATTR)
+ {
+ uint64_t value;
+ if (!readULong(stream, value))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(value);
+ dumpCKx(p11type, value, 48);
+ printf("\n");
+ }
+ else if (disktype == BYTES_ATTR)
+ {
+ uint64_t len;
+ if (!readULong(stream, len))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(len);
+ if (len > MAX_BYTES)
+ {
+ printf("overflow length...\n");
+ return;
+ }
+ printf("(length %lu)\n", (unsigned long) len);
+
+ std::vector<uint8_t> value((size_t) len);
+ if (!readBytes(stream, value))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpBytes(value);
+ }
+ else if (disktype == ATTRMAP_ATTR)
+ {
+ uint64_t len;
+ if (!readULong(stream, len))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(len);
+ if (len > MAX_BYTES)
+ {
+ printf("overflow length...\n");
+ return;
+ }
+ printf("(length %lu)\n", (unsigned long) len);
+
+ std::vector<Attribute> value;
+ if (!readMap(stream, len, value))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpMap(value);
+ }
+ else if (disktype == MECHSET_ATTR)
+ {
+ uint64_t len;
+ if (!readULong(stream, len))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(len);
+ if (len > MAX_BYTES)
+ {
+ printf("overflow length...\n");
+ return;
+ }
+ printf("(length %lu)\n", (unsigned long) len);
+
+ for (unsigned long i = 0; i < len; i++)
+ {
+ uint64_t mech;
+ if (!readULong(stream, mech))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(mech);
+ dumpCKM(mech, 48);
+ printf("\n");
+ }
+ }
+ else
+ {
+ corrupt(stream);
+ return;
+ }
+ }
+}
+
+// Display the usage
+void usage()
+{
+ printf("SoftHSM dump tool. From SoftHSM v2 object file.\n");
+ printf("Usage: softhsm2-dump-file path\n");
+}
+
+// The main function
+int main(int argc, char* argv[])
+{
+ FILE* stream;
+
+ if (argc != 2)
+ {
+ usage();
+ exit(0);
+ }
+
+ stream = fopen(argv[1], "r");
+ if (stream == NULL)
+ {
+ fprintf(stderr, "can't open object file %s\n", argv[1]);
+ exit(0);
+ }
+
+ printf("Dump of object file \"%s\"\n", argv[1]);
+ dump(stream);
+ exit(1);
+}
diff --git a/SoftHSMv2/src/bin/dump/tables.h b/SoftHSMv2/src/bin/dump/tables.h
new file mode 100644
index 0000000..76d64fb
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/tables.h
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 2013 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ tables.h
+
+ Tables from PKCS#11 specs.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TABLES_H
+#define _SOFTHSM_V2_TABLES_H
+
+#include "OSAttributes.h"
+
+// Attribute types
+void fill_CKA_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKA_CLASS] = "CKA_CLASS";
+ t[CKA_TOKEN] = "CKA_TOKEN";
+ t[CKA_PRIVATE] = "CKA_PRIVATE";
+ t[CKA_LABEL] = "CKA_LABEL";
+ t[CKA_APPLICATION] = "CKA_APPLICATION";
+ t[CKA_VALUE] = "CKA_VALUE";
+ t[CKA_OBJECT_ID] = "CKA_OBJECT_ID";
+ t[CKA_CERTIFICATE_TYPE] = "CKA_CERTIFICATE_TYPE";
+ t[CKA_ISSUER] = "CKA_ISSUER";
+ t[CKA_SERIAL_NUMBER] = "CKA_SERIAL_NUMBER";
+ t[CKA_AC_ISSUER] = "CKA_AC_ISSUER";
+ t[CKA_OWNER] = "CKA_OWNER";
+ t[CKA_ATTR_TYPES] = "CKA_ATTR_TYPES";
+ t[CKA_TRUSTED] = "CKA_TRUSTED";
+ t[CKA_CERTIFICATE_CATEGORY] = "CKA_CERTIFICATE_CATEGORY";
+ t[CKA_JAVA_MIDP_SECURITY_DOMAIN] = "CKA_JAVA_MIDP_SECURITY_DOMAIN";
+ t[CKA_URL] = "CKA_URL";
+ t[CKA_HASH_OF_SUBJECT_PUBLIC_KEY] = "CKA_HASH_OF_SUBJECT_PUBLIC_KEY";
+ t[CKA_HASH_OF_ISSUER_PUBLIC_KEY] = "CKA_HASH_OF_ISSUER_PUBLIC_KEY";
+ t[CKA_NAME_HASH_ALGORITHM] = "CKA_NAME_HASH_ALGORITHM";
+ t[CKA_CHECK_VALUE] = "CKA_CHECK_VALUE";
+ t[CKA_KEY_TYPE] = "CKA_KEY_TYPE";
+ t[CKA_SUBJECT] = "CKA_SUBJECT";
+ t[CKA_ID] = "CKA_ID";
+ t[CKA_SENSITIVE] = "CKA_SENSITIVE";
+ t[CKA_ENCRYPT] = "CKA_ENCRYPT";
+ t[CKA_DECRYPT] = "CKA_DECRYPT";
+ t[CKA_WRAP] = "CKA_WRAP";
+ t[CKA_UNWRAP] = "CKA_UNWRAP";
+ t[CKA_SIGN] = "CKA_SIGN";
+ t[CKA_SIGN_RECOVER] = "CKA_SIGN_RECOVER";
+ t[CKA_VERIFY] = "CKA_VERIFY";
+ t[CKA_VERIFY_RECOVER] = "CKA_VERIFY_RECOVER";
+ t[CKA_DERIVE] = "CKA_DERIVE";
+ t[CKA_START_DATE] = "CKA_START_DATE";
+ t[CKA_END_DATE] = "CKA_END_DATE";
+ t[CKA_MODULUS] = "CKA_MODULUS";
+ t[CKA_MODULUS_BITS] = "CKA_MODULUS_BITS";
+ t[CKA_PUBLIC_EXPONENT] = "CKA_PUBLIC_EXPONENT";
+ t[CKA_PRIVATE_EXPONENT] = "CKA_PRIVATE_EXPONENT";
+ t[CKA_PRIME_1] = "CKA_PRIME_1";
+ t[CKA_PRIME_2] = "CKA_PRIME_2";
+ t[CKA_EXPONENT_1] = "CKA_EXPONENT_1";
+ t[CKA_EXPONENT_2] = "CKA_EXPONENT_2";
+ t[CKA_COEFFICIENT] = "CKA_COEFFICIENT";
+ t[CKA_PUBLIC_KEY_INFO] = "CKA_PUBLIC_KEY_INFO";
+ t[CKA_PRIME] = "CKA_PRIME";
+ t[CKA_SUBPRIME] = "CKA_SUBPRIME";
+ t[CKA_BASE] = "CKA_BASE";
+ t[CKA_PRIME_BITS] = "CKA_PRIME_BITS";
+ t[CKA_SUBPRIME_BITS] = "CKA_SUBPRIME_BITS";
+ t[CKA_VALUE_BITS] = "CKA_VALUE_BITS";
+ t[CKA_VALUE_LEN] = "CKA_VALUE_LEN";
+ t[CKA_EXTRACTABLE] = "CKA_EXTRACTABLE";
+ t[CKA_LOCAL] = "CKA_LOCAL";
+ t[CKA_NEVER_EXTRACTABLE] = "CKA_NEVER_EXTRACTABLE";
+ t[CKA_ALWAYS_SENSITIVE] = "CKA_ALWAYS_SENSITIVE";
+ t[CKA_KEY_GEN_MECHANISM] = "CKA_KEY_GEN_MECHANISM";
+ t[CKA_MODIFIABLE] = "CKA_MODIFIABLE";
+ t[CKA_COPYABLE] = "CKA_COPYABLE";
+ t[CKA_DESTROYABLE] = "CKA_DESTROYABLE";
+ t[CKA_EC_PARAMS] = "CKA_EC_PARAMS";
+ t[CKA_EC_POINT] = "CKA_EC_POINT";
+ t[CKA_SECONDARY_AUTH] = "CKA_SECONDARY_AUTH";
+ t[CKA_AUTH_PIN_FLAGS] = "CKA_AUTH_PIN_FLAGS";
+ t[CKA_ALWAYS_AUTHENTICATE] = "CKA_ALWAYS_AUTHENTICATE";
+ t[CKA_WRAP_WITH_TRUSTED] = "CKA_WRAP_WITH_TRUSTED";
+ t[CKA_WRAP_TEMPLATE] = "CKA_WRAP_TEMPLATE";
+ t[CKA_UNWRAP_TEMPLATE] = "CKA_UNWRAP_TEMPLATE";
+ t[CKA_DERIVE_TEMPLATE] = "CKA_DERIVE_TEMPLATE";
+ t[CKA_OTP_FORMAT] = "CKA_OTP_FORMAT";
+ t[CKA_OTP_LENGTH] = "CKA_OTP_LENGTH";
+ t[CKA_OTP_TIME_INTERVAL] = "CKA_OTP_TIME_INTERVAL";
+ t[CKA_OTP_USER_FRIENDLY_MODE] = "CKA_OTP_USER_FRIENDLY_MODE";
+ t[CKA_OTP_CHALLENGE_REQUIREMENT] = "CKA_OTP_CHALLENGE_REQUIREMENT";
+ t[CKA_OTP_TIME_REQUIREMENT] = "CKA_OTP_TIME_REQUIREMENT";
+ t[CKA_OTP_COUNTER_REQUIREMENT] = "CKA_OTP_COUNTER_REQUIREMENT";
+ t[CKA_OTP_PIN_REQUIREMENT] = "CKA_OTP_PIN_REQUIREMENT";
+ t[CKA_OTP_COUNTER] = "CKA_OTP_COUNTER";
+ t[CKA_OTP_TIME] = "CKA_OTP_TIME";
+ t[CKA_OTP_USER_IDENTIFIER] = "CKA_OTP_USER_IDENTIFIER";
+ t[CKA_OTP_SERVICE_IDENTIFIER] = "CKA_OTP_SERVICE_IDENTIFIER";
+ t[CKA_OTP_SERVICE_LOGO] = "CKA_OTP_SERVICE_LOGO";
+ t[CKA_OTP_SERVICE_LOGO_TYPE] = "CKA_OTP_SERVICE_LOGO_TYPE";
+ t[CKA_GOSTR3410_PARAMS] = "CKA_GOSTR3410_PARAMS";
+ t[CKA_GOSTR3411_PARAMS] = "CKA_GOSTR3411_PARAMS";
+ t[CKA_GOST28147_PARAMS] = "CKA_GOST28147_PARAMS";
+ t[CKA_HW_FEATURE_TYPE] = "CKA_HW_FEATURE_TYPE";
+ t[CKA_RESET_ON_INIT] = "CKA_RESET_ON_INIT";
+ t[CKA_HAS_RESET] = "CKA_HAS_RESET";
+ t[CKA_PIXEL_X] = "CKA_PIXEL_X";
+ t[CKA_PIXEL_Y] = "CKA_PIXEL_Y";
+ t[CKA_RESOLUTION] = "CKA_RESOLUTION";
+ t[CKA_CHAR_ROWS] = "CKA_CHAR_ROWS";
+ t[CKA_CHAR_COLUMNS] = "CKA_CHAR_COLUMNS";
+ t[CKA_COLOR] = "CKA_COLOR";
+ t[CKA_BITS_PER_PIXEL] = "CKA_BITS_PER_PIXEL";
+ t[CKA_CHAR_SETS] = "CKA_CHAR_SETS";
+ t[CKA_ENCODING_METHODS] = "CKA_ENCODING_METHODS";
+ t[CKA_MIME_TYPES] = "CKA_MIME_TYPES";
+ t[CKA_MECHANISM_TYPE] = "CKA_MECHANISM_TYPE";
+ t[CKA_REQUIRED_CMS_ATTRIBUTES] = "CKA_REQUIRED_CMS_ATTRIBUTES";
+ t[CKA_DEFAULT_CMS_ATTRIBUTES] = "CKA_DEFAULT_CMS_ATTRIBUTES";
+ t[CKA_SUPPORTED_CMS_ATTRIBUTES] = "CKA_SUPPORTED_CMS_ATTRIBUTES";
+ t[CKA_ALLOWED_MECHANISMS] = "CKA_ALLOWED_MECHANISMS";
+ // local extensions
+ t[CKA_VENDOR_SOFTHSM] = "CKA_VENDOR_SOFTHSM";
+ t[CKA_OS_TOKENLABEL] = "CKA_OS_TOKENLABEL";
+ t[CKA_OS_TOKENSERIAL] = "CKA_OS_TOKENSERIAL";
+ t[CKA_OS_TOKENFLAGS] = "CKA_OS_TOKENFLAGS";
+ t[CKA_OS_SOPIN] = "CKA_OS_SOPIN";
+ t[CKA_OS_USERPIN] = "CKA_OS_USERPIN";
+}
+
+void fill_CKM_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKM_RSA_PKCS_KEY_PAIR_GEN] = "CKM_RSA_PKCS_KEY_PAIR_GEN";
+ t[CKM_RSA_PKCS] = "CKM_RSA_PKCS";
+ t[CKM_RSA_9796] = "CKM_RSA_9796";
+ t[CKM_RSA_X_509] = "CKM_RSA_X_509";
+ t[CKM_MD2_RSA_PKCS] = "CKM_MD2_RSA_PKCS";
+ t[CKM_MD5_RSA_PKCS] = "CKM_MD5_RSA_PKCS";
+ t[CKM_SHA1_RSA_PKCS] = "CKM_SHA1_RSA_PKCS";
+ t[CKM_RIPEMD128_RSA_PKCS] = "CKM_RIPEMD128_RSA_PKCS";
+ t[CKM_RIPEMD160_RSA_PKCS] = "CKM_RIPEMD160_RSA_PKCS";
+ t[CKM_RSA_PKCS_OAEP] = "CKM_RSA_PKCS_OAEP";
+ t[CKM_RSA_X9_31_KEY_PAIR_GEN] = "CKM_RSA_X9_31_KEY_PAIR_GEN";
+ t[CKM_RSA_X9_31] = "CKM_RSA_X9_31";
+ t[CKM_SHA1_RSA_X9_31] = "CKM_SHA1_RSA_X9_31";
+ t[CKM_RSA_PKCS_PSS] = "CKM_RSA_PKCS_PSS";
+ t[CKM_SHA1_RSA_PKCS_PSS] = "CKM_SHA1_RSA_PKCS_PSS";
+ t[CKM_DSA_KEY_PAIR_GEN] = "CKM_DSA_KEY_PAIR_GEN";
+ t[CKM_DSA] = "CKM_DSA";
+ t[CKM_DSA_SHA1] = "CKM_DSA_SHA1";
+ t[CKM_DSA_SHA224] = "CKM_DSA_SHA224";
+ t[CKM_DSA_SHA256] = "CKM_DSA_SHA256";
+ t[CKM_DSA_SHA384] = "CKM_DSA_SHA384";
+ t[CKM_DSA_SHA512] = "CKM_DSA_SHA512";
+ t[CKM_DH_PKCS_KEY_PAIR_GEN] = "CKM_DH_PKCS_KEY_PAIR_GEN";
+ t[CKM_DH_PKCS_DERIVE] = "CKM_DH_PKCS_DERIVE";
+ t[CKM_X9_42_DH_KEY_PAIR_GEN] = "CKM_X9_42_DH_KEY_PAIR_GEN";
+ t[CKM_X9_42_DH_DERIVE] = "CKM_X9_42_DH_DERIVE";
+ t[CKM_X9_42_DH_HYBRID_DERIVE] = "CKM_X9_42_DH_HYBRID_DERIVE";
+ t[CKM_X9_42_MQV_DERIVE] = "CKM_X9_42_MQV_DERIVE";
+ t[CKM_SHA256_RSA_PKCS] = "CKM_SHA256_RSA_PKCS";
+ t[CKM_SHA384_RSA_PKCS] = "CKM_SHA384_RSA_PKCS";
+ t[CKM_SHA512_RSA_PKCS] = "CKM_SHA512_RSA_PKCS";
+ t[CKM_SHA256_RSA_PKCS_PSS] = "CKM_SHA256_RSA_PKCS_PSS";
+ t[CKM_SHA384_RSA_PKCS_PSS] = "CKM_SHA384_RSA_PKCS_PSS";
+ t[CKM_SHA512_RSA_PKCS_PSS] = "CKM_SHA512_RSA_PKCS_PSS";
+ t[CKM_SHA224_RSA_PKCS] = "CKM_SHA224_RSA_PKCS";
+ t[CKM_SHA224_RSA_PKCS_PSS] = "CKM_SHA224_RSA_PKCS_PSS";
+ t[CKM_SHA512_224] = "CKM_SHA512_224";
+ t[CKM_SHA512_224_HMAC] = "CKM_SHA512_224_HMAC";
+ t[CKM_SHA512_224_HMAC_GENERAL] = "CKM_SHA512_224_HMAC_GENERAL";
+ t[CKM_SHA512_224_KEY_DERIVATION] = "CKM_SHA512_224_KEY_DERIVATION";
+ t[CKM_SHA512_256] = "CKM_SHA512_256";
+ t[CKM_SHA512_256_HMAC] = "CKM_SHA512_256_HMAC";
+ t[CKM_SHA512_256_HMAC_GENERAL] = "CKM_SHA512_256_HMAC_GENERAL";
+ t[CKM_SHA512_256_KEY_DERIVATION] = "CKM_SHA512_256_KEY_DERIVATION";
+ t[CKM_SHA512_T] = "CKM_SHA512_T";
+ t[CKM_SHA512_T_HMAC] = "CKM_SHA512_T_HMAC";
+ t[CKM_SHA512_T_HMAC_GENERAL] = "CKM_SHA512_T_HMAC_GENERAL";
+ t[CKM_SHA512_T_KEY_DERIVATION] = "CKM_SHA512_T_KEY_DERIVATION";
+ t[CKM_RC2_KEY_GEN] = "CKM_RC2_KEY_GEN";
+ t[CKM_RC2_ECB] = "CKM_RC2_ECB";
+ t[CKM_RC2_CBC] = "CKM_RC2_CBC";
+ t[CKM_RC2_MAC] = "CKM_RC2_MAC";
+ t[CKM_RC2_MAC_GENERAL] = "CKM_RC2_MAC_GENERAL";
+ t[CKM_RC2_CBC_PAD] = "CKM_RC2_CBC_PAD";
+ t[CKM_RC4_KEY_GEN] = "CKM_RC4_KEY_GEN";
+ t[CKM_RC4] = "CKM_RC4";
+ t[CKM_DES_KEY_GEN] = "CKM_DES_KEY_GEN";
+ t[CKM_DES_ECB] = "CKM_DES_ECB";
+ t[CKM_DES_CBC] = "CKM_DES_CBC";
+ t[CKM_DES_MAC] = "CKM_DES_MAC";
+ t[CKM_DES_MAC_GENERAL] = "CKM_DES_MAC_GENERAL";
+ t[CKM_DES_CBC_PAD] = "CKM_DES_CBC_PAD";
+ t[CKM_DES2_KEY_GEN] = "CKM_DES2_KEY_GEN";
+ t[CKM_DES3_KEY_GEN] = "CKM_DES3_KEY_GEN";
+ t[CKM_DES3_ECB] = "CKM_DES3_ECB";
+ t[CKM_DES3_CBC] = "CKM_DES3_CBC";
+ t[CKM_DES3_MAC] = "CKM_DES3_MAC";
+ t[CKM_DES3_MAC_GENERAL] = "CKM_DES3_MAC_GENERAL";
+ t[CKM_DES3_CBC_PAD] = "CKM_DES3_CBC_PAD";
+ t[CKM_DES3_CMAC_GENERAL] = "CKM_DES3_CMAC_GENERAL";
+ t[CKM_DES3_CMAC] = "CKM_DES3_CMAC";
+ t[CKM_CDMF_KEY_GEN] = "CKM_CDMF_KEY_GEN";
+ t[CKM_CDMF_ECB] = "CKM_CDMF_ECB";
+ t[CKM_CDMF_CBC] = "CKM_CDMF_CBC";
+ t[CKM_CDMF_MAC] = "CKM_CDMF_MAC";
+ t[CKM_CDMF_MAC_GENERAL] = "CKM_CDMF_MAC_GENERAL";
+ t[CKM_CDMF_CBC_PAD] = "CKM_CDMF_CBC_PAD";
+ t[CKM_DES_OFB64] = "CKM_DES_OFB64";
+ t[CKM_DES_OFB8] = "CKM_DES_OFB8";
+ t[CKM_DES_CFB64] = "CKM_DES_CFB64";
+ t[CKM_DES_CFB8] = "CKM_DES_CFB8";
+ t[CKM_MD2] = "CKM_MD2";
+ t[CKM_MD2_HMAC] = "CKM_MD2_HMAC";
+ t[CKM_MD2_HMAC_GENERAL] = "CKM_MD2_HMAC_GENERAL";
+ t[CKM_MD5] = "CKM_MD5";
+ t[CKM_MD5_HMAC] = "CKM_MD5_HMAC";
+ t[CKM_MD5_HMAC_GENERAL] = "CKM_MD5_HMAC_GENERAL";
+ t[CKM_SHA_1] = "CKM_SHA_1";
+ t[CKM_SHA_1_HMAC] = "CKM_SHA_1_HMAC";
+ t[CKM_SHA_1_HMAC_GENERAL] = "CKM_SHA_1_HMAC_GENERAL";
+ t[CKM_RIPEMD128] = "CKM_RIPEMD128";
+ t[CKM_RIPEMD128_HMAC] = "CKM_RIPEMD128_HMAC";
+ t[CKM_RIPEMD128_HMAC_GENERAL] = "CKM_RIPEMD128_HMAC_GENERAL";
+ t[CKM_RIPEMD160] = "CKM_RIPEMD160";
+ t[CKM_RIPEMD160_HMAC] = "CKM_RIPEMD160_HMAC";
+ t[CKM_RIPEMD160_HMAC_GENERAL] = "CKM_RIPEMD160_HMAC_GENERAL";
+ t[CKM_SHA256] = "CKM_SHA256";
+ t[CKM_SHA256_HMAC] = "CKM_SHA256_HMAC";
+ t[CKM_SHA256_HMAC_GENERAL] = "CKM_SHA256_HMAC_GENERAL";
+ t[CKM_SHA224] = "CKM_SHA224";
+ t[CKM_SHA224_HMAC] = "CKM_SHA224_HMAC";
+ t[CKM_SHA224_HMAC_GENERAL] = "CKM_SHA224_HMAC_GENERAL";
+ t[CKM_SHA384] = "CKM_SHA384";
+ t[CKM_SHA384_HMAC] = "CKM_SHA384_HMAC";
+ t[CKM_SHA384_HMAC_GENERAL] = "CKM_SHA384_HMAC_GENERAL";
+ t[CKM_SHA512] = "CKM_SHA512";
+ t[CKM_SHA512_HMAC] = "CKM_SHA512_HMAC";
+ t[CKM_SHA512_HMAC_GENERAL] = "CKM_SHA512_HMAC_GENERAL";
+ t[CKM_SECURID_KEY_GEN] = "CKM_SECURID_KEY_GEN";
+ t[CKM_SECURID] = "CKM_SECURID";
+ t[CKM_HOTP_KEY_GEN] = "CKM_HOTP_KEY_GEN";
+ t[CKM_HOTP] = "CKM_HOTP";
+ t[CKM_ACTI] = "CKM_ACTI";
+ t[CKM_ACTI_KEY_GEN] = "CKM_ACTI_KEY_GEN";
+ t[CKM_CAST_KEY_GEN] = "CKM_CAST_KEY_GEN";
+ t[CKM_CAST_ECB] = "CKM_CAST_ECB";
+ t[CKM_CAST_CBC] = "CKM_CAST_CBC";
+ t[CKM_CAST_MAC] = "CKM_CAST_MAC";
+ t[CKM_CAST_MAC_GENERAL] = "CKM_CAST_MAC_GENERAL";
+ t[CKM_CAST_CBC_PAD] = "CKM_CAST_CBC_PAD";
+ t[CKM_CAST3_KEY_GEN] = "CKM_CAST3_KEY_GEN";
+ t[CKM_CAST3_ECB] = "CKM_CAST3_ECB";
+ t[CKM_CAST3_CBC] = "CKM_CAST3_CBC";
+ t[CKM_CAST3_MAC] = "CKM_CAST3_MAC";
+ t[CKM_CAST3_MAC_GENERAL] = "CKM_CAST3_MAC_GENERAL";
+ t[CKM_CAST3_CBC_PAD] = "CKM_CAST3_CBC_PAD";
+ t[CKM_CAST128_KEY_GEN] = "CKM_CAST128_KEY_GEN";
+ t[CKM_CAST128_ECB] = "CKM_CAST128_ECB";
+ t[CKM_CAST128_CBC] = "CKM_CAST128_CBC";
+ t[CKM_CAST128_MAC] = "CKM_CAST128_MAC";
+ t[CKM_CAST128_MAC_GENERAL] = "CKM_CAST128_MAC_GENERAL";
+ t[CKM_CAST128_CBC_PAD] = "CKM_CAST128_CBC_PAD";
+ t[CKM_RC5_KEY_GEN] = "CKM_RC5_KEY_GEN";
+ t[CKM_RC5_ECB] = "CKM_RC5_ECB";
+ t[CKM_RC5_CBC] = "CKM_RC5_CBC";
+ t[CKM_RC5_MAC] = "CKM_RC5_MAC";
+ t[CKM_RC5_MAC_GENERAL] = "CKM_RC5_MAC_GENERAL";
+ t[CKM_RC5_CBC_PAD] = "CKM_RC5_CBC_PAD";
+ t[CKM_IDEA_KEY_GEN] = "CKM_IDEA_KEY_GEN";
+ t[CKM_IDEA_ECB] = "CKM_IDEA_ECB";
+ t[CKM_IDEA_CBC] = "CKM_IDEA_CBC";
+ t[CKM_IDEA_MAC] = "CKM_IDEA_MAC";
+ t[CKM_IDEA_MAC_GENERAL] = "CKM_IDEA_MAC_GENERAL";
+ t[CKM_IDEA_CBC_PAD] = "CKM_IDEA_CBC_PAD";
+ t[CKM_GENERIC_SECRET_KEY_GEN] = "CKM_GENERIC_SECRET_KEY_GEN";
+ t[CKM_CONCATENATE_BASE_AND_KEY] = "CKM_CONCATENATE_BASE_AND_KEY";
+ t[CKM_CONCATENATE_BASE_AND_DATA] = "CKM_CONCATENATE_BASE_AND_DATA";
+ t[CKM_CONCATENATE_DATA_AND_BASE] = "CKM_CONCATENATE_DATA_AND_BASE";
+ t[CKM_XOR_BASE_AND_DATA] = "CKM_XOR_BASE_AND_DATA";
+ t[CKM_EXTRACT_KEY_FROM_KEY] = "CKM_EXTRACT_KEY_FROM_KEY";
+ t[CKM_SSL3_PRE_MASTER_KEY_GEN] = "CKM_SSL3_PRE_MASTER_KEY_GEN";
+ t[CKM_SSL3_MASTER_KEY_DERIVE] = "CKM_SSL3_MASTER_KEY_DERIVE";
+ t[CKM_SSL3_KEY_AND_MAC_DERIVE] = "CKM_SSL3_KEY_AND_MAC_DERIVE";
+ t[CKM_SSL3_MASTER_KEY_DERIVE_DH] = "CKM_SSL3_MASTER_KEY_DERIVE_DH";
+ t[CKM_TLS_PRE_MASTER_KEY_GEN] = "CKM_TLS_PRE_MASTER_KEY_GEN";
+ t[CKM_TLS_MASTER_KEY_DERIVE] = "CKM_TLS_MASTER_KEY_DERIVE";
+ t[CKM_TLS_KEY_AND_MAC_DERIVE] = "CKM_TLS_KEY_AND_MAC_DERIVE";
+ t[CKM_TLS_MASTER_KEY_DERIVE_DH] = "CKM_TLS_MASTER_KEY_DERIVE_DH";
+ t[CKM_TLS_PRF] = "CKM_TLS_PRF";
+ t[CKM_SSL3_MD5_MAC] = "CKM_SSL3_MD5_MAC";
+ t[CKM_SSL3_SHA1_MAC] = "CKM_SSL3_SHA1_MAC";
+ t[CKM_MD5_KEY_DERIVATION] = "CKM_MD5_KEY_DERIVATION";
+ t[CKM_MD2_KEY_DERIVATION] = "CKM_MD2_KEY_DERIVATION";
+ t[CKM_SHA1_KEY_DERIVATION] = "CKM_SHA1_KEY_DERIVATION";
+ t[CKM_SHA256_KEY_DERIVATION] = "CKM_SHA256_KEY_DERIVATION";
+ t[CKM_SHA384_KEY_DERIVATION] = "CKM_SHA384_KEY_DERIVATION";
+ t[CKM_SHA512_KEY_DERIVATION] = "CKM_SHA512_KEY_DERIVATION";
+ t[CKM_SHA224_KEY_DERIVATION] = "CKM_SHA224_KEY_DERIVATION";
+ t[CKM_PBE_MD2_DES_CBC] = "CKM_PBE_MD2_DES_CBC";
+ t[CKM_PBE_MD5_DES_CBC] = "CKM_PBE_MD5_DES_CBC";
+ t[CKM_PBE_MD5_CAST_CBC] = "CKM_PBE_MD5_CAST_CBC";
+ t[CKM_PBE_MD5_CAST3_CBC] = "CKM_PBE_MD5_CAST3_CBC";
+ t[CKM_PBE_MD5_CAST128_CBC] = "CKM_PBE_MD5_CAST128_CBC";
+ t[CKM_PBE_SHA1_CAST128_CBC] = "CKM_PBE_SHA1_CAST128_CBC";
+ t[CKM_PBE_SHA1_RC4_128] = "CKM_PBE_SHA1_RC4_128";
+ t[CKM_PBE_SHA1_RC4_40] = "CKM_PBE_SHA1_RC4_40";
+ t[CKM_PBE_SHA1_DES3_EDE_CBC] = "CKM_PBE_SHA1_DES3_EDE_CBC";
+ t[CKM_PBE_SHA1_DES2_EDE_CBC] = "CKM_PBE_SHA1_DES2_EDE_CBC";
+ t[CKM_PBE_SHA1_RC2_128_CBC] = "CKM_PBE_SHA1_RC2_128_CBC";
+ t[CKM_PBE_SHA1_RC2_40_CBC] = "CKM_PBE_SHA1_RC2_40_CBC";
+ t[CKM_PKCS5_PBKD2] = "CKM_PKCS5_PBKD2";
+ t[CKM_PBA_SHA1_WITH_SHA1_HMAC] = "CKM_PBA_SHA1_WITH_SHA1_HMAC";
+ t[CKM_WTLS_PRE_MASTER_KEY_GEN] = "CKM_WTLS_PRE_MASTER_KEY_GEN";
+ t[CKM_WTLS_MASTER_KEY_DERIVE] = "CKM_WTLS_MASTER_KEY_DERIVE";
+ t[CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC] = "CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC";
+ t[CKM_WTLS_PRF] = "CKM_WTLS_PRF";
+ t[CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE] = "CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE";
+ t[CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE] = "CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE";
+ t[CKM_TLS10_MAC_SERVER] = "CKM_TLS10_MAC_SERVER";
+ t[CKM_TLS10_MAC_CLIENT] = "CKM_TLS10_MAC_CLIENT";
+ t[CKM_TLS12_MAC] = "CKM_TLS12_MAC";
+ t[CKM_TLS12_KDF] = "CKM_TLS12_KDF";
+ t[CKM_TLS12_MASTER_KEY_DERIVE] = "CKM_TLS12_MASTER_KEY_DERIVE";
+ t[CKM_TLS12_KEY_AND_MAC_DERIVE] = "CKM_TLS12_KEY_AND_MAC_DERIVE";
+ t[CKM_TLS12_MASTER_KEY_DERIVE_DH] = "CKM_TLS12_MASTER_KEY_DERIVE_DH";
+ t[CKM_TLS12_KEY_SAFE_DERIVE] = "CKM_TLS12_KEY_SAFE_DERIVE";
+ t[CKM_TLS_MAC] = "CKM_TLS_MAC";
+ t[CKM_TLS_KDF] = "CKM_TLS_KDF";
+ t[CKM_KEY_WRAP_LYNKS] = "CKM_KEY_WRAP_LYNKS";
+ t[CKM_KEY_WRAP_SET_OAEP] = "CKM_KEY_WRAP_SET_OAEP";
+ t[CKM_CMS_SIG] = "CKM_CMS_SIG";
+ t[CKM_KIP_DERIVE] = "CKM_KIP_DERIVE";
+ t[CKM_KIP_WRAP] = "CKM_KIP_WRAP";
+ t[CKM_KIP_MAC] = "CKM_KIP_MAC";
+ t[CKM_CAMELLIA_KEY_GEN] = "CKM_CAMELLIA_KEY_GEN";
+ t[CKM_CAMELLIA_ECB] = "CKM_CAMELLIA_ECB";
+ t[CKM_CAMELLIA_CBC] = "CKM_CAMELLIA_CBC";
+ t[CKM_CAMELLIA_MAC] = "CKM_CAMELLIA_MAC";
+ t[CKM_CAMELLIA_MAC_GENERAL] = "CKM_CAMELLIA_MAC_GENERAL";
+ t[CKM_CAMELLIA_CBC_PAD] = "CKM_CAMELLIA_CBC_PAD";
+ t[CKM_CAMELLIA_ECB_ENCRYPT_DATA] = "CKM_CAMELLIA_ECB_ENCRYPT_DATA";
+ t[CKM_CAMELLIA_CBC_ENCRYPT_DATA] = "CKM_CAMELLIA_CBC_ENCRYPT_DATA";
+ t[CKM_CAMELLIA_CTR] = "CKM_CAMELLIA_CTR";
+ t[CKM_ARIA_KEY_GEN] = "CKM_ARIA_KEY_GEN";
+ t[CKM_ARIA_ECB] = "CKM_ARIA_ECB";
+ t[CKM_ARIA_CBC] = "CKM_ARIA_CBC";
+ t[CKM_ARIA_MAC] = "CKM_ARIA_MAC";
+ t[CKM_ARIA_MAC_GENERAL] = "CKM_ARIA_MAC_GENERAL";
+ t[CKM_ARIA_CBC_PAD] = "CKM_ARIA_CBC_PAD";
+ t[CKM_ARIA_ECB_ENCRYPT_DATA] = "CKM_ARIA_ECB_ENCRYPT_DATA";
+ t[CKM_ARIA_CBC_ENCRYPT_DATA] = "CKM_ARIA_CBC_ENCRYPT_DATA";
+ t[CKM_SEED_KEY_GEN] = "CKM_SEED_KEY_GEN";
+ t[CKM_SEED_ECB] = "CKM_SEED_ECB";
+ t[CKM_SEED_CBC] = "CKM_SEED_CBC";
+ t[CKM_SEED_MAC] = "CKM_SEED_MAC";
+ t[CKM_SEED_MAC_GENERAL] = "CKM_SEED_MAC_GENERAL";
+ t[CKM_SEED_CBC_PAD] = "CKM_SEED_CBC_PAD";
+ t[CKM_SEED_ECB_ENCRYPT_DATA] = "CKM_SEED_ECB_ENCRYPT_DATA";
+ t[CKM_SEED_CBC_ENCRYPT_DATA] = "CKM_SEED_CBC_ENCRYPT_DATA";
+ t[CKM_SKIPJACK_KEY_GEN] = "CKM_SKIPJACK_KEY_GEN";
+ t[CKM_SKIPJACK_ECB64] = "CKM_SKIPJACK_ECB64";
+ t[CKM_SKIPJACK_CBC64] = "CKM_SKIPJACK_CBC64";
+ t[CKM_SKIPJACK_OFB64] = "CKM_SKIPJACK_OFB64";
+ t[CKM_SKIPJACK_CFB64] = "CKM_SKIPJACK_CFB64";
+ t[CKM_SKIPJACK_CFB32] = "CKM_SKIPJACK_CFB32";
+ t[CKM_SKIPJACK_CFB16] = "CKM_SKIPJACK_CFB16";
+ t[CKM_SKIPJACK_CFB8] = "CKM_SKIPJACK_CFB8";
+ t[CKM_SKIPJACK_WRAP] = "CKM_SKIPJACK_WRAP";
+ t[CKM_SKIPJACK_PRIVATE_WRAP] = "CKM_SKIPJACK_PRIVATE_WRAP";
+ t[CKM_SKIPJACK_RELAYX] = "CKM_SKIPJACK_RELAYX";
+ t[CKM_KEA_KEY_PAIR_GEN] = "CKM_KEA_KEY_PAIR_GEN";
+ t[CKM_KEA_KEY_DERIVE] = "CKM_KEA_KEY_DERIVE";
+ t[CKM_FORTEZZA_TIMESTAMP] = "CKM_FORTEZZA_TIMESTAMP";
+ t[CKM_BATON_KEY_GEN] = "CKM_BATON_KEY_GEN";
+ t[CKM_BATON_ECB128] = "CKM_BATON_ECB128";
+ t[CKM_BATON_ECB96] = "CKM_BATON_ECB96";
+ t[CKM_BATON_CBC128] = "CKM_BATON_CBC128";
+ t[CKM_BATON_COUNTER] = "CKM_BATON_COUNTER";
+ t[CKM_BATON_SHUFFLE] = "CKM_BATON_SHUFFLE";
+ t[CKM_BATON_WRAP] = "CKM_BATON_WRAP";
+ t[CKM_EC_KEY_PAIR_GEN] = "CKM_EC_KEY_PAIR_GEN";
+ t[CKM_ECDSA] = "CKM_ECDSA";
+ t[CKM_ECDSA_SHA1] = "CKM_ECDSA_SHA1";
+ t[CKM_ECDSA_SHA224] = "CKM_ECDSA_SHA224";
+ t[CKM_ECDSA_SHA256] = "CKM_ECDSA_SHA256";
+ t[CKM_ECDSA_SHA384] = "CKM_ECDSA_SHA384";
+ t[CKM_ECDSA_SHA512] = "CKM_ECDSA_SHA512";
+ t[CKM_ECDH1_DERIVE] = "CKM_ECDH1_DERIVE";
+ t[CKM_ECDH1_COFACTOR_DERIVE] = "CKM_ECDH1_COFACTOR_DERIVE";
+ t[CKM_ECMQV_DERIVE] = "CKM_ECMQV_DERIVE";
+ t[CKM_ECDH_AES_KEY_WRAP] = "CKM_ECDH_AES_KEY_WRAP";
+ t[CKM_RSA_AES_KEY_WRAP] = "CKM_RSA_AES_KEY_WRAP";
+ t[CKM_JUNIPER_KEY_GEN] = "CKM_JUNIPER_KEY_GEN";
+ t[CKM_JUNIPER_ECB128] = "CKM_JUNIPER_ECB128";
+ t[CKM_JUNIPER_CBC128] = "CKM_JUNIPER_CBC128";
+ t[CKM_JUNIPER_COUNTER] = "CKM_JUNIPER_COUNTER";
+ t[CKM_JUNIPER_SHUFFLE] = "CKM_JUNIPER_SHUFFLE";
+ t[CKM_JUNIPER_WRAP] = "CKM_JUNIPER_WRAP";
+ t[CKM_FASTHASH] = "CKM_FASTHASH";
+ t[CKM_AES_KEY_GEN] = "CKM_AES_KEY_GEN";
+ t[CKM_AES_ECB] = "CKM_AES_ECB";
+ t[CKM_AES_CBC] = "CKM_AES_CBC";
+ t[CKM_AES_MAC] = "CKM_AES_MAC";
+ t[CKM_AES_MAC_GENERAL] = "CKM_AES_MAC_GENERAL";
+ t[CKM_AES_CBC_PAD] = "CKM_AES_CBC_PAD";
+ t[CKM_AES_CTR] = "CKM_AES_CTR";
+ t[CKM_AES_GCM] = "CKM_AES_GCM";
+ t[CKM_AES_CCM] = "CKM_AES_CCM";
+ t[CKM_AES_CTS] = "CKM_AES_CTS";
+ t[CKM_AES_CMAC] = "CKM_AES_CMAC";
+ t[CKM_AES_CMAC_GENERAL] = "CKM_AES_CMAC_GENERAL";
+ t[CKM_AES_XCBC_MAC] = "CKM_AES_XCBC_MAC";
+ t[CKM_AES_XCBC_MAC_96] = "CKM_AES_XCBC_MAC_96";
+ t[CKM_AES_GMAC] = "CKM_AES_GMAC";
+ t[CKM_BLOWFISH_KEY_GEN] = "CKM_BLOWFISH_KEY_GEN";
+ t[CKM_BLOWFISH_CBC] = "CKM_BLOWFISH_CBC";
+ t[CKM_TWOFISH_KEY_GEN] = "CKM_TWOFISH_KEY_GEN";
+ t[CKM_TWOFISH_CBC] = "CKM_TWOFISH_CBC";
+ t[CKM_BLOWFISH_CBC_PAD] = "CKM_BLOWFISH_CBC_PAD";
+ t[CKM_TWOFISH_CBC_PAD] = "CKM_TWOFISH_CBC_PAD";
+ t[CKM_DES_ECB_ENCRYPT_DATA] = "CKM_DES_ECB_ENCRYPT_DATA";
+ t[CKM_DES_CBC_ENCRYPT_DATA] = "CKM_DES_CBC_ENCRYPT_DATA";
+ t[CKM_DES3_ECB_ENCRYPT_DATA] = "CKM_DES3_ECB_ENCRYPT_DATA";
+ t[CKM_DES3_CBC_ENCRYPT_DATA] = "CKM_DES3_CBC_ENCRYPT_DATA";
+ t[CKM_AES_ECB_ENCRYPT_DATA] = "CKM_AES_ECB_ENCRYPT_DATA";
+ t[CKM_AES_CBC_ENCRYPT_DATA] = "CKM_AES_CBC_ENCRYPT_DATA";
+ t[CKM_GOSTR3410_KEY_PAIR_GEN] = "CKM_GOSTR3410_KEY_PAIR_GEN";
+ t[CKM_GOSTR3410] = "CKM_GOSTR3410";
+ t[CKM_GOSTR3410_WITH_GOSTR3411] = "CKM_GOSTR3410_WITH_GOSTR3411";
+ t[CKM_GOSTR3410_KEY_WRAP] = "CKM_GOSTR3410_KEY_WRAP";
+ t[CKM_GOSTR3410_DERIVE] = "CKM_GOSTR3410_DERIVE";
+ t[CKM_GOSTR3411] = "CKM_GOSTR3411";
+ t[CKM_GOSTR3411_HMAC] = "CKM_GOSTR3411_HMAC";
+ t[CKM_GOST28147_KEY_GEN] = "CKM_GOST28147_KEY_GEN";
+ t[CKM_GOST28147_ECB] = "CKM_GOST28147_ECB";
+ t[CKM_GOST28147] = "CKM_GOST28147";
+ t[CKM_GOST28147_MAC] = "CKM_GOST28147_MAC";
+ t[CKM_GOST28147_KEY_WRAP] = "CKM_GOST28147_KEY_WRAP";
+ t[CKM_DSA_PARAMETER_GEN] = "CKM_DSA_PARAMETER_GEN";
+ t[CKM_DH_PKCS_PARAMETER_GEN] = "CKM_DH_PKCS_PARAMETER_GEN";
+ t[CKM_X9_42_DH_PARAMETER_GEN] = "CKM_X9_42_DH_PARAMETER_GEN";
+ t[CKM_DSA_PROBABLISTIC_PARAMETER_GEN] = "CKM_DSA_PROBABLISTIC_PARAMETER_GEN";
+ t[CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN] = "CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN";
+ t[CKM_AES_OFB] = "CKM_AES_OFB";
+ t[CKM_AES_CFB64] = "CKM_AES_CFB64";
+ t[CKM_AES_CFB8] = "CKM_AES_CFB8";
+ t[CKM_AES_CFB128] = "CKM_AES_CFB128";
+ t[CKM_AES_CFB1] = "CKM_AES_CFB1";
+ t[CKM_AES_KEY_WRAP] = "CKM_AES_KEY_WRAP";
+ t[CKM_AES_KEY_WRAP_PAD] = "CKM_AES_KEY_WRAP_PAD";
+ t[CKM_RSA_PKCS_TPM_1_1] = "CKM_RSA_PKCS_TPM_1_1";
+ t[CKM_RSA_PKCS_OAEP_TPM_1_1] = "CKM_RSA_PKCS_OAEP_TPM_1_1";
+}
+
+void fill_CKO_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKO_DATA] = "CKO_DATA";
+ t[CKO_CERTIFICATE] = "CKO_CERTIFICATE";
+ t[CKO_PUBLIC_KEY] = "CKO_PUBLIC_KEY";
+ t[CKO_PRIVATE_KEY] = "CKO_PRIVATE_KEY";
+ t[CKO_SECRET_KEY] = "CKO_SECRET_KEY";
+ t[CKO_HW_FEATURE] = "CKO_HW_FEATURE";
+ t[CKO_DOMAIN_PARAMETERS] = "CKO_DOMAIN_PARAMETERS";
+ t[CKO_MECHANISM] = "CKO_MECHANISM";
+ t[CKO_OTP_KEY] = "CKO_OTP_KEY";
+}
+
+void fill_CKH_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKH_MONOTONIC_COUNTER] = "CKH_MONOTONIC_COUNTER";
+ t[CKH_CLOCK] = "CKH_CLOCK";
+ t[CKH_USER_INTERFACE] = "CKH_USER_INTERFACE";
+}
+
+void fill_CKK_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKK_RSA] = "CKK_RSA";
+ t[CKK_DSA] = "CKK_DSA";
+ t[CKK_DH] = "CKK_DH";
+ t[CKK_EC] = "CKK_EC";
+ t[CKK_X9_42_DH] = "CKK_X9_42_DH";
+ t[CKK_KEA] = "CKK_KEA";
+ t[CKK_GENERIC_SECRET] = "CKK_GENERIC_SECRET";
+ t[CKK_RC2] = "CKK_RC2";
+ t[CKK_RC4] = "CKK_RC4";
+ t[CKK_DES] = "CKK_DES";
+ t[CKK_DES2] = "CKK_DES2";
+ t[CKK_DES3] = "CKK_DES3";
+ t[CKK_CAST] = "CKK_CAST";
+ t[CKK_CAST3] = "CKK_CAST3";
+ t[CKK_CAST128] = "CKK_CAST128";
+ t[CKK_RC5] = "CKK_RC5";
+ t[CKK_IDEA] = "CKK_IDEA";
+ t[CKK_SKIPJACK] = "CKK_SKIPJACK";
+ t[CKK_BATON] = "CKK_BATON";
+ t[CKK_JUNIPER] = "CKK_JUNIPER";
+ t[CKK_CDMF] = "CKK_CDMF";
+ t[CKK_AES] = "CKK_AES";
+ t[CKK_BLOWFISH] = "CKK_BLOWFISH";
+ t[CKK_TWOFISH] = "CKK_TWOFISH";
+ t[CKK_SECURID] = "CKK_SECURID";
+ t[CKK_HOTP] = "CKK_HOTP";
+ t[CKK_ACTI] = "CKK_ACTI";
+ t[CKK_CAMELLIA] = "CKK_CAMELLIA";
+ t[CKK_ARIA] = "CKK_ARIA";
+ t[CKK_MD5_HMAC] = "CKK_MD5_HMAC";
+ t[CKK_SHA_1_HMAC] = "CKK_SHA_1_HMAC";
+ t[CKK_RIPEMD128_HMAC] = "CKK_RIPEMD128_HMAC";
+ t[CKK_RIPEMD160_HMAC] = "CKK_RIPEMD160_HMAC";
+ t[CKK_SHA256_HMAC] = "CKK_SHA256_HMAC";
+ t[CKK_SHA384_HMAC] = "CKK_SHA384_HMAC";
+ t[CKK_SHA512_HMAC] = "CKK_SHA512_HMAC";
+ t[CKK_SHA224_HMAC] = "CKK_SHA224_HMAC";
+ t[CKK_SEED] = "CKK_SEED";
+ t[CKK_GOSTR3410] = "CKK_GOSTR3410";
+ t[CKK_GOSTR3411] = "CKK_GOSTR3411";
+ t[CKK_GOST28147] = "CKK_GOST28147";
+}
+
+void fill_CKC_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKC_X_509] = "CKC_X_509";
+ t[CKC_X_509_ATTR_CERT] = "CKC_X_509_ATTR_CERT";
+ t[CKC_WTLS] = "CKC_WTLS";
+ t[CKC_OPENPGP] = "CKC_OPENPGP";
+}
+
+#endif // !_SOFTHSM_V2_TABLES_H
diff --git a/SoftHSMv2/src/bin/keyconv/Makefile.am b/SoftHSMv2/src/bin/keyconv/Makefile.am
new file mode 100644
index 0000000..b4268c2
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/Makefile.am
@@ -0,0 +1,26 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib/crypto \
+ @CRYPTO_INCLUDES@
+
+dist_man_MANS = softhsm2-keyconv.1
+
+bin_PROGRAMS = softhsm2-keyconv
+
+softhsm2_keyconv_SOURCES = softhsm2-keyconv.cpp \
+ base64.c
+softhsm2_keyconv_LDADD = @CRYPTO_LIBS@
+
+# Compile with OpenSSL support
+if WITH_OPENSSL
+softhsm2_keyconv_SOURCES += softhsm2-keyconv-ossl.cpp \
+ ../../lib/crypto/OSSLComp.cpp
+endif
+
+# Compile with Botan support
+if WITH_BOTAN
+softhsm2_keyconv_SOURCES += softhsm2-keyconv-botan.cpp
+endif
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/*.cpp
diff --git a/SoftHSMv2/src/bin/keyconv/base64.c b/SoftHSMv2/src/bin/keyconv/base64.c
new file mode 100644
index 0000000..3eb1201
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/base64.c
@@ -0,0 +1,311 @@
+/* $OpenBSD: base64.c,v 1.3 2002/06/09 08:13:07 todd Exp $ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$ISC: base64.c,v 8.6 1999/01/08 19:25:18 vixie Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/param.h>
+#include <sys/socket.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(unsigned char const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ unsigned char input[3];
+ unsigned char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(char const *src, unsigned char *target, size_t targsize) {
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace(ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex+1] = ((pos - Base64) & 0x0f)
+ << 4 ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex+1] = ((pos - Base64) & 0x03)
+ << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp
new file mode 100644
index 0000000..cb5700f
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-keyconv-botan.cpp
+
+ Code specific for Botan
+ *****************************************************************************/
+
+#include <config.h>
+#define KEYCONV_BOTAN
+#include "softhsm2-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/pkcs8.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/bigint.h>
+#include <botan/version.h>
+
+// Init Botan
+void crypto_init()
+{
+ Botan::LibraryInitializer::initialize();
+}
+
+// Final Botan
+void crypto_final()
+{
+ Botan::LibraryInitializer::deinitialize();
+}
+
+// Save the RSA key as a PKCS#8 file
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ int result = 0;
+ Botan::Private_Key* priv_key = NULL;
+ Botan::AutoSeeded_RNG* rng = NULL;
+ Botan::BigInt bigE, bigP, bigQ, bigN, bigD;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_MODULUS].size <= 0 ||
+ pkey[TAG_PUBEXP].size <= 0 ||
+ pkey[TAG_PRIVEXP].size <= 0 ||
+ pkey[TAG_PRIME1].size <= 0 ||
+ pkey[TAG_PRIME2].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ bigE = Botan::BigInt((Botan::byte*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size);
+ bigP = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size);
+ bigQ = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size);
+ bigN = Botan::BigInt((Botan::byte*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size);
+ bigD = Botan::BigInt((Botan::byte*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size);
+
+ rng = new Botan::AutoSeeded_RNG();
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34)
+ priv_key = new Botan::RSA_PrivateKey(bigP, bigQ, bigE, bigD, bigN);
+#else
+ priv_key = new Botan::RSA_PrivateKey(*rng, bigP, bigQ, bigE, bigD, bigN);
+#endif
+ }
+ catch(std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not extract the private key from the file.\n");
+ delete rng;
+ return 1;
+ }
+
+ std::ofstream priv_file(out_path);
+ if (!priv_file.is_open())
+ {
+ fprintf(stderr, "ERROR: Could not open file for output.\n");
+ delete rng;
+ delete priv_key;
+ return 1;
+ }
+
+ try
+ {
+ if (file_pin == NULL)
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key);
+ }
+ else
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, std::chrono::milliseconds(300), "PBE-PKCS5v15(MD5,DES/CBC)");
+#else
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, "PBE-PKCS5v15(MD5,DES/CBC)");
+#endif
+ }
+
+ printf("The key has been written to %s\n", out_path);
+ }
+ catch(std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not write to file.\n");
+ result = 1;
+ }
+
+ delete rng;
+ delete priv_key;
+ priv_file.close();
+
+ return result;
+}
+
+// Save the DSA key as a PKCS#8 file
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ int result = 0;
+ Botan::Private_Key* priv_key = NULL;
+ Botan::AutoSeeded_RNG* rng = NULL;
+ Botan::BigInt bigDP, bigDQ, bigDG, bigDX;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_PRIME].size <= 0 ||
+ pkey[TAG_SUBPRIME].size <= 0 ||
+ pkey[TAG_BASE].size <= 0 ||
+ pkey[TAG_PRIVVAL].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ bigDP = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size);
+ bigDQ = Botan::BigInt((Botan::byte*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size);
+ bigDG = Botan::BigInt((Botan::byte*)pkey[TAG_BASE].big, pkey[TAG_BASE].size);
+ bigDX = Botan::BigInt((Botan::byte*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size);
+
+ rng = new Botan::AutoSeeded_RNG();
+
+ try
+ {
+ priv_key = new Botan::DSA_PrivateKey(*rng, Botan::DL_Group(bigDP, bigDQ, bigDG), bigDX);
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not extract the private key from the file.\n");
+ delete rng;
+ return 1;
+ }
+
+ std::ofstream priv_file(out_path);
+ if (!priv_file.is_open())
+ {
+ fprintf(stderr, "ERROR: Could not open file for output.\n");
+ delete rng;
+ delete priv_key;
+ return 1;
+ }
+
+ try
+ {
+ if (file_pin == NULL)
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key);
+ }
+ else
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, std::chrono::milliseconds(300), "PBE-PKCS5v15(MD5,DES/CBC)");
+#else
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, "PBE-PKCS5v15(MD5,DES/CBC)");
+#endif
+ }
+
+ printf("The key has been written to %s\n", out_path);
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not write to file.\n");
+ result = 1;
+ }
+
+ delete rng;
+ delete priv_key;
+ priv_file.close();
+
+ return result;
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp
new file mode 100644
index 0000000..a5cd8eb
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-keyconv-ossl.cpp
+
+ Code specific for OpenSSL
+ *****************************************************************************/
+
+#include <config.h>
+#define KEYCONV_OSSL
+#include "softhsm2-keyconv.h"
+#include "OSSLComp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+
+// Init OpenSSL
+void crypto_init()
+{
+ OpenSSL_add_all_algorithms();
+#ifdef WITH_FIPS
+ if (!FIPS_mode_set(1))
+ {
+ fprintf(stderr, "ERROR: can't enter into FIPS mode.\n");
+ exit(0);
+ }
+#endif
+}
+
+// Final OpenSSL
+void crypto_final()
+{
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+// Save the RSA key as a PKCS#8 file
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ RSA* rsa = NULL;
+ EVP_PKEY* ossl_pkey = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ BIO* out = NULL;
+ X509_SIG* p8 = NULL;
+ int result = 0;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_MODULUS].size <= 0 ||
+ pkey[TAG_PUBEXP].size <= 0 ||
+ pkey[TAG_PRIVEXP].size <= 0 ||
+ pkey[TAG_PRIME1].size <= 0 ||
+ pkey[TAG_PRIME2].size <= 0 ||
+ pkey[TAG_EXP1].size <= 0 ||
+ pkey[TAG_EXP2].size <= 0 ||
+ pkey[TAG_COEFF].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ rsa = RSA_new();
+ BIGNUM* bn_p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size, NULL);
+ BIGNUM* bn_q = BN_bin2bn((unsigned char*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size, NULL);
+ BIGNUM* bn_d = BN_bin2bn((unsigned char*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size, NULL);
+ BIGNUM* bn_n = BN_bin2bn((unsigned char*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size, NULL);
+ BIGNUM* bn_e = BN_bin2bn((unsigned char*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size, NULL);
+ BIGNUM* bn_dmp1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP1].big, pkey[TAG_EXP1].size, NULL);
+ BIGNUM* bn_dmq1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP2].big, pkey[TAG_EXP2].size, NULL);
+ BIGNUM* bn_iqmp = BN_bin2bn((unsigned char*)pkey[TAG_COEFF].big, pkey[TAG_COEFF].size, NULL);
+ RSA_set0_factors(rsa, bn_p, bn_q);
+ RSA_set0_crt_params(rsa, bn_dmp1, bn_dmq1, bn_iqmp);
+ RSA_set0_key(rsa, bn_n, bn_e, bn_d);
+
+ ossl_pkey = EVP_PKEY_new();
+
+ // Convert RSA to EVP_PKEY
+ if (!EVP_PKEY_set1_RSA(ossl_pkey, rsa))
+ {
+ fprintf(stderr, "ERROR: Could not convert RSA key to EVP_PKEY.\n");
+ RSA_free(rsa);
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ RSA_free(rsa);
+
+ // Convert EVP_PKEY to PKCS#8
+ if (!(p8inf = EVP_PKEY2PKCS8(ossl_pkey)))
+ {
+ fprintf(stderr, "ERROR: Could not convert EVP_PKEY to PKCS#8.\n");
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ EVP_PKEY_free(ossl_pkey);
+
+ // Open output file
+ if (!(out = BIO_new_file (out_path, "wb")))
+ {
+ fprintf(stderr, "ERROR: Could not open the output file.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 1;
+ }
+
+ // Write to disk
+ if (file_pin == NULL)
+ {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ printf("The key has been written to %s\n", out_path);
+ }
+ else
+ {
+ // Encrypt p8
+ if (!(p8 = PKCS8_encrypt(NID_pbeWithMD5AndDES_CBC, NULL,
+ file_pin, strlen(file_pin), NULL,
+ 0, PKCS12_DEFAULT_ITER, p8inf)))
+ {
+ fprintf(stderr, "ERROR: Could not encrypt the PKCS#8 file\n");
+ result = 1;
+ }
+ else
+ {
+ PEM_write_bio_PKCS8(out, p8);
+ X509_SIG_free(p8);
+ printf("The key has been written to %s\n", out_path);
+ }
+ }
+
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ BIO_free_all(out);
+
+ return result;
+}
+
+// Save the DSA key as a PKCS#8 file
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ DSA* dsa = NULL;
+ EVP_PKEY* ossl_pkey = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ BIO* out = NULL;
+ X509_SIG* p8 = NULL;
+ int result = 0;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_PRIME].size <= 0 ||
+ pkey[TAG_SUBPRIME].size <= 0 ||
+ pkey[TAG_BASE].size <= 0 ||
+ pkey[TAG_PRIVVAL].size <= 0 ||
+ pkey[TAG_PUBVAL].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ dsa = DSA_new();
+ BIGNUM* bn_p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size, NULL);
+ BIGNUM* bn_q = BN_bin2bn((unsigned char*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size, NULL);
+ BIGNUM* bn_g = BN_bin2bn((unsigned char*)pkey[TAG_BASE].big, pkey[TAG_BASE].size, NULL);
+ BIGNUM* bn_priv_key = BN_bin2bn((unsigned char*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size, NULL);
+ BIGNUM* bn_pub_key = BN_bin2bn((unsigned char*)pkey[TAG_PUBVAL].big, pkey[TAG_PUBVAL].size, NULL);
+
+ DSA_set0_pqg(dsa, bn_p, bn_q, bn_g);
+ DSA_set0_key(dsa, bn_pub_key, bn_priv_key);
+
+ ossl_pkey = EVP_PKEY_new();
+
+ // Convert DSA to EVP_PKEY
+ if (!EVP_PKEY_set1_DSA(ossl_pkey, dsa))
+ {
+ fprintf(stderr, "ERROR: Could not convert DSA key to EVP_PKEY.\n");
+ DSA_free(dsa);
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ DSA_free(dsa);
+
+ // Convert EVP_PKEY to PKCS#8
+ if (!(p8inf = EVP_PKEY2PKCS8(ossl_pkey)))
+ {
+ fprintf(stderr, "ERROR: Could not convert EVP_PKEY to PKCS#8.\n");
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ EVP_PKEY_free(ossl_pkey);
+
+ // Open output file
+ if (!(out = BIO_new_file (out_path, "wb")))
+ {
+ fprintf(stderr, "ERROR: Could not open the output file.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 1;
+ }
+
+ // Write to disk
+ if (file_pin == NULL)
+ {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ printf("The key has been written to %s\n", out_path);
+ }
+ else
+ {
+ // Encrypt p8
+ if (!(p8 = PKCS8_encrypt(NID_pbeWithMD5AndDES_CBC, NULL,
+ file_pin, strlen(file_pin), NULL,
+ 0, PKCS12_DEFAULT_ITER, p8inf)))
+ {
+ fprintf(stderr, "ERROR: Could not encrypt the PKCS#8 file\n");
+ result = 1;
+ }
+ else
+ {
+ PEM_write_bio_PKCS8(out, p8);
+ X509_SIG_free(p8);
+ printf("The key has been written to %s\n", out_path);
+ }
+ }
+
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ BIO_free_all(out);
+
+ return result;
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1 b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1
new file mode 100644
index 0000000..b716bc8
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1
@@ -0,0 +1,63 @@
+.TH SOFTHSM2-KEYCONV 1 "20 March 2014" "SoftHSM"
+.SH NAME
+softhsm2-keyconv \- converting from BIND to PKCS#8 key file format
+.SH SYNOPSIS
+.B softhsm2-keyconv
+.B \-\-in
+.I path
+.B \-\-out
+.I path
+.RB [ \-\-pin
+.IR PIN ]
+.SH DESCRIPTION
+.B softhsm2-keyconv
+can convert BIND .private-key files to the PKCS#8 file format.
+This is so that you can import the PKCS#8 file into
+libsofthsm using the command
+.BR softhsm2\-util .
+If you have another file format, then
+.B openssl
+probably can help you to convert it into the PKCS#8 file format.
+.SH OPTIONS
+.B \-\-help\fR, \fB\-h\fR
+Shows the help screen.
+.TP
+.B \-\-in \fIpath\fR
+The
+.I path
+to the input file.
+.TP
+.B \-\-out \fIpath\fR
+The
+.I path
+to the output file.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+will be used to encrypt the PKCS#8 file.
+If not given then the PKCS#8 file will be unencrypted.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH EXAMPLES
+The following command can be used to convert a BIND .private-key file to a PKCS#8 file:
+.LP
+.RS
+.nf
+softhsm2-keyconv \-\-in Kexample.com.+007+05474.private \\
+.ti +0.7i
+\-\-out rsa.pem
+.fi
+.RE
+.LP
+.SH AUTHORS
+Written by Rickard Bellgrim, Francis Dupont, René Post, and Roland van Rijswijk.
+.SH "SEE ALSO"
+.IR softhsm2-migrate (1),
+.IR softhsm2-util (1),
+.IR softhsm2.conf (5),
+.IR openssl (1),
+.IR named (1),
+.IR dnssec-keygen (1),
+.IR dnssec-signzone (1)
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp
new file mode 100644
index 0000000..aeb75c3
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/************************************************************
+*
+* softhsm2-keyconv
+*
+* This program is for converting from BIND .private-key
+* format to PKCS#8 key file format. So that keys can be
+* imported from BIND to SoftHSM.
+*
+* Some of the design/code is from keyconv.c written by
+* Hakan Olsson and Jakob Schlyter in 2000 and 2001.
+*
+************************************************************/
+
+#include <config.h>
+#include "softhsm2-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#define open _open
+#define close _close
+#endif
+#include <iostream>
+#include <fstream>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void usage()
+{
+ printf("Converting from BIND .private-key format to PKCS#8 key file format.\n");
+ printf("Usage: softhsm2-keyconv [OPTIONS]\n");
+ printf("Options:\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --in <path> The path to the input file.\n");
+ printf(" --out <path> The path to the output file.\n");
+ printf(" --pin <PIN> To encrypt PKCS#8 file. Optional.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+}
+
+// Give a number to each option
+enum {
+ OPT_HELP = 0x100,
+ OPT_IN,
+ OPT_OUT,
+ OPT_PIN,
+ OPT_VERSION
+};
+
+// Define the options
+static const struct option long_options[] = {
+ { "help", 0, NULL, OPT_HELP },
+ { "in", 1, NULL, OPT_IN },
+ { "out", 1, NULL, OPT_OUT },
+ { "pin", 1, NULL, OPT_PIN },
+ { "version", 0, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt, result;
+
+ char* in_path = NULL;
+ char* out_path = NULL;
+ char* file_pin = NULL;
+
+ if (argc == 1)
+ {
+ usage();
+ exit(0);
+ }
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_IN:
+ in_path = optarg;
+ break;
+ case OPT_OUT:
+ out_path = optarg;
+ break;
+ case OPT_PIN:
+ file_pin = optarg;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // We should convert to PKCS#8
+ result = to_pkcs8(in_path, out_path, file_pin);
+
+ return result;
+}
+
+// Convert from BIND to PKCS#8
+int to_pkcs8(char* in_path, char* out_path, char* file_pin)
+{
+ FILE* file_pointer = NULL;
+ char line[MAX_LINE], data[MAX_LINE];
+ char* value_pointer = NULL;
+ int lineno = 0, m, n, error = 0, found, algorithm = DNS_KEYALG_ERROR, data_length;
+ uint32_t bitfield = 0;
+ key_material_t pkey[TAG_MAX];
+
+ if (in_path == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the input file must be supplied. Use --in <path>\n");
+ return 1;
+ }
+
+ if (out_path == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the output file must be supplied. Use --out <path>\n");
+ return 1;
+ }
+
+ file_pointer = fopen(in_path, "r");
+ if (file_pointer == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open input file %.100s for reading.\n", in_path);
+ return 1;
+ }
+
+ // Loop over all of the lines
+ while (fgets(line, MAX_LINE, file_pointer) != NULL)
+ {
+ lineno++;
+
+ // Find the current text field in the BIND file.
+ for (m = 0, found = -1; found == -1 && file_tags[m]; m++)
+ {
+ if (strncasecmp(line, file_tags[m], strlen(file_tags[m])) == 0)
+ {
+ found = m;
+ }
+ }
+
+ // The text files is not recognized.
+ if (found == -1)
+ {
+ fprintf(stderr, "ERROR: Unrecognized input line %i\n", lineno);
+ fprintf(stderr, "ERROR: --> %s", line);
+ continue;
+ }
+
+ // Point to the data for this text field.
+ value_pointer = line + strlen(file_tags[found]) + 1;
+
+ // Continue if we are at the end of the string
+ if (*value_pointer == 0)
+ {
+ continue;
+ }
+
+ // Check that we do not get duplicates.
+ if (bitfield & (1 << found))
+ {
+ fprintf(stderr, "ERROR: Duplicate \"%s\" field, line %i - ignored\n",
+ file_tags[found], lineno);
+ continue;
+ }
+ bitfield |= (1 << found);
+
+ // Handle the data for this text field.
+ switch (found)
+ {
+ case TAG_VERSION:
+ if (sscanf(value_pointer, "v%i.%i", &m, &n) != 2)
+ {
+ fprintf(stderr, "ERROR: Invalid/unknown version string "
+ "(%.100s).\n", value_pointer);
+ error = 1;
+ break;
+ }
+ if (m > FILE_MAJOR_VERSION || (m == FILE_MAJOR_VERSION && n > FILE_MINOR_VERSION))
+ {
+ fprintf(stderr, "ERROR: Cannot parse this version of file format, "
+ "v%i.%i.\n", m, n);
+ error = 1;
+ }
+ break;
+ case TAG_ALGORITHM:
+ algorithm = strtol(value_pointer, NULL, 10);
+ break;
+ // RSA
+ case TAG_MODULUS:
+ case TAG_PUBEXP:
+ case TAG_PRIVEXP:
+ case TAG_PRIME1:
+ case TAG_PRIME2:
+ case TAG_EXP1:
+ case TAG_EXP2:
+ case TAG_COEFF:
+ // DSA
+ case TAG_PRIME:
+ case TAG_SUBPRIME:
+ case TAG_BASE:
+ case TAG_PRIVVAL:
+ case TAG_PUBVAL:
+ data_length = b64_pton(value_pointer, (unsigned char*)data, MAX_LINE);
+ if (data_length == -1)
+ {
+ error = 1;
+ fprintf(stderr, "ERROR: Could not parse the base64 string on line %i.\n", lineno);
+ }
+ else
+ {
+ pkey[found].big = malloc(data_length);
+ if (!pkey[found].big)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ error = 1;
+ break;
+ }
+ memcpy(pkey[found].big, data, data_length);
+ pkey[found].size = data_length;
+ }
+ break;
+ // Do not need these
+ case TAG_CREATED:
+ case TAG_PUBLISH:
+ case TAG_ACTIVATE:
+ default:
+ break;
+ }
+ }
+
+ fclose(file_pointer);
+
+ // Something went wrong. Clean up and quit.
+ if (error)
+ {
+ free_key_material(pkey);
+ return error;
+ }
+
+ // Create and set file permissions if the file does not exist.
+ int fd = open(out_path, O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1)
+ {
+ fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+ out_path, errno);
+ free_key_material(pkey);
+ return 1;
+ }
+ ::close(fd);
+
+ crypto_init();
+
+ // Save the the key to the disk
+ switch (algorithm)
+ {
+ case DNS_KEYALG_ERROR:
+ fprintf(stderr, "ERROR: The algorithm %i was not given in the file.\n",
+ algorithm);
+ error = 1;
+ break;
+ case DNS_KEYALG_RSAMD5:
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_RSASHA1_NSEC3_SHA1:
+ case DNS_KEYALG_RSASHA256:
+ case DNS_KEYALG_RSASHA512:
+ error = save_rsa_pkcs8(out_path, file_pin, pkey);
+ break;
+ case DNS_KEYALG_DSA:
+ case DNS_KEYALG_DSA_NSEC3_SHA1:
+ error = save_dsa_pkcs8(out_path, file_pin, pkey);
+ break;
+ case DNS_KEYALG_ECC:
+ case DNS_KEYALG_ECC_GOST:
+ default:
+ fprintf(stderr, "ERROR: The algorithm %i is not supported.\n",
+ algorithm);
+ error = 1;
+ break;
+ }
+
+ crypto_final();
+ free_key_material(pkey);
+
+ return error;
+}
+
+// Free allocated memory
+void free_key_material(key_material_t* pkey)
+{
+ int i;
+
+ if (!pkey)
+ {
+ return;
+ }
+
+ for (i = 0; i < TAG_MAX; i++)
+ {
+ if (pkey[i].big)
+ {
+ free(pkey[i].big);
+ }
+ }
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h
new file mode 100644
index 0000000..fdeb719
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_KEYCONV_H
+#define _SOFTHSM_V2_SOFTHSM2_KEYCONV_H 1
+
+#include <stdlib.h>
+
+typedef struct key_material_t {
+ unsigned long size;
+ void* big;
+ key_material_t() {
+ size = 0;
+ big = NULL;
+ }
+} key_material_t;
+
+// Main functions
+
+void usage();
+int to_pkcs8(char* in_path, char* out_path, char* file_pin);
+
+// Support functions
+
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey);
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey);
+void free_key_material(key_material_t* pkey);
+void crypto_init();
+void crypto_final();
+
+// base64.c prototypes
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int b64_pton(const char* , unsigned char*, size_t);
+int b64_ntop(const unsigned char*, size_t, char*, size_t);
+#ifdef __cplusplus
+}
+#endif
+
+// The BIND file version number.
+#define FILE_MAJOR_VERSION 1
+#define FILE_MINOR_VERSION 3
+
+// Key algorithm number
+#define DNS_KEYALG_ERROR -1
+#define DNS_KEYALG_RSAMD5 1
+#define DNS_KEYALG_DSA 3
+#define DNS_KEYALG_ECC 4
+#define DNS_KEYALG_RSASHA1 5
+#define DNS_KEYALG_DSA_NSEC3_SHA1 6
+#define DNS_KEYALG_RSASHA1_NSEC3_SHA1 7
+#define DNS_KEYALG_RSASHA256 8
+#define DNS_KEYALG_RSASHA512 10
+#define DNS_KEYALG_ECC_GOST 12
+
+// Maximum number of lines / line length
+#define MAX_LINE 4096
+
+// The text fields supported
+#if !defined(KEYCONV_BOTAN) && !defined(KEYCONV_OSSL)
+static const char* file_tags[] = {
+ "Private-key-format:",
+ "Algorithm:",
+ "Modulus:",
+ "PublicExponent:",
+ "PrivateExponent:",
+ "Prime1:",
+ "Prime2:",
+ "Exponent1:",
+ "Exponent2:",
+ "Coefficient:",
+ "Prime(p):",
+ "Private_value(x):",
+ "Public_value(y):",
+ "Subprime(q):",
+ "Base(g):",
+ "Created:",
+ "Publish:",
+ "Activate:",
+ NULL
+};
+#endif
+
+// The number of each text field.
+// Must match the tags above.
+enum FILE_TAGS {
+ TAG_VERSION = 0,
+ TAG_ALGORITHM,
+ TAG_MODULUS,
+ TAG_PUBEXP,
+ TAG_PRIVEXP,
+ TAG_PRIME1,
+ TAG_PRIME2,
+ TAG_EXP1,
+ TAG_EXP2,
+ TAG_COEFF,
+ TAG_PRIME,
+ TAG_PRIVVAL,
+ TAG_PUBVAL,
+ TAG_SUBPRIME,
+ TAG_BASE,
+ TAG_CREATED,
+ TAG_PUBLISH,
+ TAG_ACTIVATE,
+ // So we know how long this list is
+ TAG_MAX
+};
+
+#endif /* _SOFTHSM_V2_SOFTHSM2_KEYCONV_H */
diff --git a/SoftHSMv2/src/bin/migrate/Makefile.am b/SoftHSMv2/src/bin/migrate/Makefile.am
new file mode 100644
index 0000000..020c6a7
--- /dev/null
+++ b/SoftHSMv2/src/bin/migrate/Makefile.am
@@ -0,0 +1,20 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib/pkcs11 \
+ -I$(srcdir)/../common \
+ @SQLITE3_INCLUDES@
+
+dist_man_MANS = softhsm2-migrate.1
+
+bin_PROGRAMS = softhsm2-migrate
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+softhsm2_migrate_SOURCES = softhsm2-migrate.cpp \
+ ../common/findslot.cpp \
+ ../common/getpw.cpp \
+ ../common/library.cpp
+softhsm2_migrate_LDADD = @SQLITE3_LIBS@ \
+ @YIELD_LIB@
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.1 b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.1
new file mode 100644
index 0000000..65dc00c
--- /dev/null
+++ b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.1
@@ -0,0 +1,67 @@
+.TH SOFTHSM2-MIGRATE 1 "20 April 2016" "SoftHSM"
+.SH NAME
+softhsm2-migrate \- SoftHSM v1 migration tool
+.SH SYNOPSIS
+.PP
+.B softhsm2-migrate \-\-db
+.I path
+.B \-\-token
+.I label
+.RB [ \-\-pin
+.I PIN
+.B \-\-no\-public\-key]
+.SH DESCRIPTION
+.B softhsm2-migrate
+is a tool that can migrate SoftHSM v1 databases to PKCS#11.
+The default HSM is SoftHSM v2, but can be used with other
+PKCS#11 libraries by using the option
+.B \-\-module
+.LP
+.SH OPTIONS
+.TP
+.B \-\-db \fIpath\fR
+The SoftHSM v1 database that is going to be migrated.
+The location of the token database can be found in
+the configuration file for SoftHSM v1.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
+.TP
+.B \-\-module \fIpath\fR
+Use another PKCS#11 library than SoftHSM.
+.TP
+.B \-\-no\-public\-key
+Do not migrate the public key.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+for the normal user.
+.TP
+.B \-\-serial \fInumber\fR
+Will use the token with a matching serial number.
+.TP
+.B \-\-slot \fInumber\fR
+The database will be migrated to this slot.
+.TP
+.B \-\-token \fIlabel\fR
+Will use the token with a matching token label.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH EXAMPLE
+.LP
+A token database can be migrated with the following command:
+.LP
+.RS
+.nf
+softhsm2-migrate \-\-db /home/user/token.db \-\-token mytoken
+.fi
+.RE
+.SH AUTHORS
+Written by Rickard Bellgrim, Francis Dupont, René Post, and Roland van Rijswijk.
+.LP
+.SH "SEE ALSO"
+.IR softhsm2-keyconv (1),
+.IR softhsm2-util (1),
+.IR softhsm2.conf (5)
diff --git a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp
new file mode 100644
index 0000000..0e6dc90
--- /dev/null
+++ b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-migrate.cpp
+
+ This program can be used for migrating SoftHSM v1 databases to any
+ PKCS#11 library. The default library is the libsofthsm2.so
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm2-migrate.h"
+#include "findslot.h"
+#include "getpw.h"
+#include "library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <iostream>
+#include <fstream>
+#include <sched.h>
+
+#ifdef _WIN32
+#define sched_yield() SleepEx(0, 0)
+#endif
+
+// Display the usage
+void usage()
+{
+ printf("SoftHSM migration tool. From SoftHSM v1 database to PKCS#11.\n");
+ printf("Usage: softhsm2-migrate [OPTIONS]\n");
+ printf("Options:\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --db <path> The SoftHSM v1 database that is going to be migrated.\n");
+ printf(" --module <path> Use another PKCS#11 library than SoftHSM.\n");
+ printf(" --no-public-key Do not migrate the public key.\n");
+ printf(" --pin <PIN> The PIN for the normal user.\n");
+ printf(" --serial <number> Will use the token with a matching serial number.\n");
+ printf(" --slot <number> The slot where the token is located.\n");
+ printf(" --token <label> Will use the token with a matching token label.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+}
+
+// Enumeration of the long options
+enum {
+ OPT_HELP = 0x100,
+ OPT_DB,
+ OPT_MODULE,
+ OPT_NO_PUBLIC_KEY,
+ OPT_PIN,
+ OPT_SERIAL,
+ OPT_SLOT,
+ OPT_TOKEN,
+ OPT_VERSION
+};
+
+// Text representation of the long options
+static const struct option long_options[] = {
+ { "help", 0, NULL, OPT_HELP },
+ { "db", 1, NULL, OPT_DB },
+ { "module", 1, NULL, OPT_MODULE },
+ { "no-public-key", 0, NULL, OPT_NO_PUBLIC_KEY },
+ { "pin", 1, NULL, OPT_PIN },
+ { "serial", 1, NULL, OPT_SERIAL },
+ { "slot", 1, NULL, OPT_SLOT },
+ { "token" , 1, NULL, OPT_TOKEN },
+ { "version", 0, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+CK_FUNCTION_LIST_PTR p11;
+
+// Prepared statements
+sqlite3_stmt* select_an_attribute_sql = NULL;
+sqlite3_stmt* select_object_ids_sql = NULL;
+sqlite3_stmt* count_object_id_sql = NULL;
+
+
+// The main function
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt;
+
+ char* dbPath = NULL;
+ char* userPIN = NULL;
+ char* module = NULL;
+ char* slot = NULL;
+ char* serial = NULL;
+ char* token = NULL;
+ char *errMsg = NULL;
+ int noPublicKey = 0;
+
+ int result = 0;
+ CK_RV rv;
+
+ moduleHandle = NULL;
+ p11 = NULL;
+ CK_SLOT_ID slotID = 0;
+
+ if (argc == 1)
+ {
+ usage();
+ exit(0);
+ }
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_DB:
+ dbPath = optarg;
+ break;
+ case OPT_SLOT:
+ slot = optarg;
+ break;
+ case OPT_SERIAL:
+ serial = optarg;
+ break;
+ case OPT_TOKEN:
+ token = optarg;
+ break;
+ case OPT_MODULE:
+ module = optarg;
+ break;
+ case OPT_NO_PUBLIC_KEY:
+ noPublicKey = 1;
+ break;
+ case OPT_PIN:
+ userPIN = optarg;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // Get a pointer to the function list for PKCS#11 library
+ CK_C_GetFunctionList pGetFunctionList = loadLibrary(module, &moduleHandle, &errMsg);
+ if (pGetFunctionList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not load the PKCS#11 library/module: %s\n", errMsg);
+ fprintf(stderr, "ERROR: Please check log files for additional information.\n");
+ exit(1);
+ }
+
+ // Load the function list
+ (*pGetFunctionList)(&p11);
+
+ // Initialize the library
+ rv = p11->C_Initialize(NULL_PTR);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the PKCS#11 library/module: %s\n", module ? module : DEFAULT_PKCS11_LIB);
+ fprintf(stderr, "ERROR: Please check log files for additional information.\n");
+ exit(1);
+ }
+
+ // Get the slotID
+ result = findSlot(slot, serial, token, slotID);
+
+ if (!result)
+ {
+ // Migrate the database
+ result = migrate(dbPath, slotID, userPIN, noPublicKey);
+ }
+
+ // Finalize the library
+ p11->C_Finalize(NULL_PTR);
+ unloadLibrary(moduleHandle);
+
+ return result;
+}
+
+// Migrate the database
+int migrate(char* dbPath, CK_SLOT_ID slotID, char* userPIN, int noPublicKey)
+{
+ CK_SESSION_HANDLE hSession;
+ sqlite3* db = NULL;
+ int result;
+
+ if (dbPath == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the database must be supplied. "
+ "Use --db <path>\n");
+ return 1;
+ }
+
+ // Open the database
+ db = openDB(dbPath);
+ if (db == NULL)
+ {
+ return 1;
+ }
+
+ // Connect to the PKCS#11 library
+ result = openP11(slotID, userPIN, &hSession);
+ if (result)
+ {
+ sqlite3_close(db);
+ return result;
+ }
+
+ // Prepare the statements
+ if (prepStatements(db))
+ {
+ fprintf(stderr, "ERROR: Could not prepare the statements\n");
+ finalStatements();
+ sqlite3_close(db);
+ return 1;
+ }
+
+ // Start the migration
+ result = db2session(db, hSession, noPublicKey);
+
+ // Finalize the statements
+ finalStatements();
+
+ sqlite3_close(db);
+
+ if (result)
+ {
+ fprintf(stderr, "ERROR: Unable to migrate all of the objects.\n");
+ }
+ else
+ {
+ printf("The database has been migrated to the new HSM\n");
+ }
+
+ return result;
+}
+
+// Prepare the statements
+int prepStatements(sqlite3* db)
+{
+ select_an_attribute_sql = NULL;
+ select_object_ids_sql = NULL;
+ count_object_id_sql = NULL;
+
+ const char select_an_attribute_str[] = "SELECT value,length FROM Attributes WHERE objectID = ? AND type = ?;";
+ const char select_object_ids_str[] = "SELECT objectID FROM Objects;";
+ const char count_object_id_str[] = "SELECT COUNT(objectID) FROM Objects;";
+
+ if
+ (
+ sqlite3_prepare_v2(db, select_an_attribute_str, -1, &select_an_attribute_sql, NULL) ||
+ sqlite3_prepare_v2(db, select_object_ids_str, -1, &select_object_ids_sql, NULL) ||
+ sqlite3_prepare_v2(db, count_object_id_str, -1, &count_object_id_sql, NULL)
+ )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+// Finalize the statements
+void finalStatements()
+{
+ if (select_an_attribute_sql) sqlite3_finalize(select_an_attribute_sql);
+ if (select_object_ids_sql) sqlite3_finalize(select_object_ids_sql);
+ if (count_object_id_sql) sqlite3_finalize(count_object_id_sql);
+}
+
+// Open a connection to a valid SoftHSM v1 database
+sqlite3* openDB(char* dbPath)
+{
+ int result;
+ sqlite3* db = NULL;
+ sqlite3_stmt* pragStatem = NULL;
+ int dbVersion;
+
+ // Open the database
+ result = sqlite3_open(dbPath, &db);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: Could not open token database. "
+ "Probably wrong path or privileges: %s\n", dbPath);
+ return NULL;
+ }
+
+ // Check the schema version
+ if (sqlite3_prepare_v2(db, "PRAGMA user_version;", -1, &pragStatem, NULL))
+ {
+ fprintf(stderr, "ERROR: Could not prepare a SQL statement\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+ if (sqlite3_step(pragStatem) == SQLITE_ROW)
+ {
+ dbVersion = sqlite3_column_int(pragStatem, 0);
+ sqlite3_finalize(pragStatem);
+
+ if (dbVersion != 100)
+ {
+ fprintf(stderr, "ERROR: Wrong database schema version: %s\n", dbPath);
+ sqlite3_close(db);
+ return NULL;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: The token database has not been initialized by SoftHSM\n");
+ sqlite3_finalize(pragStatem);
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Token table exist
+ result = sqlite3_exec(db, "SELECT COUNT(variableID) FROM Token;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Token table is missing the in database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Objects table exist
+ result = sqlite3_exec(db, "SELECT COUNT(objectID) FROM Objects;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Objects table is missing the in database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Attributes table exist
+ result = sqlite3_exec(db, "SELECT COUNT(attributeID) FROM Attributes;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Attributes table is missing in the database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ return db;
+}
+
+// Connect and login to the token
+int openP11(CK_SLOT_ID slotID, char* userPIN, CK_SESSION_HANDLE* hSession)
+{
+ char user_pin_copy[MAX_PIN_LEN+1];
+ CK_RV rv;
+
+ rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL_PTR, NULL_PTR, hSession);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_SLOT_ID_INVALID)
+ {
+ fprintf(stderr, "ERROR: The given slot does not exist.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
+ }
+ return 1;
+ }
+
+ // Get the password
+ if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get user PIN\n");
+ return 1;
+ }
+
+ rv = p11->C_Login(*hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_PIN_INCORRECT) {
+ fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+// Migrate the database to the session
+int db2session(sqlite3* db, CK_SESSION_HANDLE hSession, int noPublicKey)
+{
+ CK_ULONG objectCount;
+ int result = 0, rv;
+ CK_OBJECT_HANDLE* objects = NULL;
+ CK_OBJECT_CLASS ckClass;
+
+ // Get all objects
+ objects = getObjects(db, &objectCount);
+ if (objects == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not find any objects in the database.\n");
+ return 1;
+ }
+
+ // Loop over all objects
+ for (unsigned i = 0; i < objectCount; i++)
+ {
+ ckClass = getObjectClass(objects[i]);
+
+ switch (ckClass)
+ {
+ case CKO_PUBLIC_KEY:
+ if (noPublicKey) continue;
+ if (getKeyType(objects[i]) != CKK_RSA)
+ {
+ fprintf(stderr, "ERROR: Cannot export object %lu. Only supporting RSA keys. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ }
+ rv = dbRSAPub2session(db, objects[i], hSession);
+ if (rv) result = 1;
+ break;
+ case CKO_PRIVATE_KEY:
+ if (getKeyType(objects[i]) != CKK_RSA)
+ {
+ fprintf(stderr, "ERROR: Cannot export object %lu. Only supporting RSA keys. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ }
+ rv = dbRSAPriv2session(db, objects[i], hSession);
+ if (rv) result = 1;
+ break;
+ case CKO_VENDOR_DEFINED:
+ fprintf(stderr, "ERROR: Could not get the class of object %lu. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ default:
+ fprintf(stderr, "ERROR: Not supporting class %lu in object %lu. "
+ "Continuing.\n", ckClass, objects[i]);
+ result = 1;
+ break;
+ }
+ }
+
+ free(objects);
+
+ return result;
+}
+
+// Get the key type from key objects
+CK_KEY_TYPE getKeyType(CK_OBJECT_HANDLE objectRef)
+{
+ int retSQL = 0;
+ CK_KEY_TYPE retVal = CKK_VENDOR_DEFINED;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, CKA_KEY_TYPE);
+
+ // Get result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (pValue != NULL_PTR && length == sizeof(CK_KEY_TYPE))
+ {
+ retVal = *(CK_KEY_TYPE*)pValue;
+ }
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Get the class of the object
+CK_OBJECT_CLASS getObjectClass(CK_OBJECT_HANDLE objectRef)
+{
+ int retSQL = 0;
+ CK_OBJECT_CLASS retVal = CKO_VENDOR_DEFINED;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, CKA_CLASS);
+
+ // Get the result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (pValue != NULL_PTR && length == sizeof(CK_OBJECT_CLASS))
+ {
+ retVal = *(CK_OBJECT_CLASS*)pValue;
+ }
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Get all object IDs
+CK_OBJECT_HANDLE* getObjects(sqlite3* /*db*/, CK_ULONG* objectCount)
+{
+ CK_ULONG objectsInDB;
+ CK_ULONG counter = 0;
+ CK_OBJECT_HANDLE* objectRefs = NULL;
+ int retSQL = 0;
+
+ *objectCount = 0;
+
+ // Find out how many objects we have.
+ while ((retSQL = sqlite3_step(count_object_id_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ if (retSQL != SQLITE_ROW)
+ {
+ fprintf(stderr, "ERROR: Could not count the number of objects in the database\n");
+ sqlite3_reset(count_object_id_sql);
+ return NULL;
+ }
+
+ // Get the number of objects
+ objectsInDB = sqlite3_column_int(count_object_id_sql, 0);
+ sqlite3_reset(count_object_id_sql);
+
+ if (!objectsInDB)
+ {
+ fprintf(stderr, "ERROR: There are not objects in the database\n");
+ return NULL;
+ }
+
+ // Create the object-reference buffer
+ objectRefs = (CK_OBJECT_HANDLE*)malloc(objectsInDB * sizeof(CK_OBJECT_HANDLE));
+ if (objectRefs == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory\n");
+ return NULL;
+ }
+
+ // Get all the object ids
+ while
+ (
+ ((retSQL = sqlite3_step(select_object_ids_sql)) == SQLITE_BUSY || retSQL == SQLITE_ROW) &&
+ counter < objectsInDB
+ )
+ {
+ if(retSQL == SQLITE_BUSY)
+ {
+ sched_yield();
+ continue;
+ }
+
+ objectRefs[counter++] = sqlite3_column_int(select_object_ids_sql, 0);
+ }
+
+ *objectCount = counter;
+
+ sqlite3_reset(select_object_ids_sql);
+
+ return objectRefs;
+}
+
+// Extract the information about the public RSA key and save it in the token
+int dbRSAPub2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession)
+{
+ int result = 0;
+ int i;
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv;
+
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_MODIFIABLE, NULL, 0 },
+ { CKA_LABEL, NULL, 0 },
+ { CKA_ID, NULL, 0 },
+ { CKA_START_DATE, NULL, 0 },
+ { CKA_END_DATE, NULL, 0 },
+ { CKA_DERIVE, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_ENCRYPT, NULL, 0 },
+ { CKA_VERIFY, NULL, 0 },
+ { CKA_VERIFY_RECOVER, NULL, 0 },
+ { CKA_WRAP, NULL, 0 },
+ { CKA_MODULUS, NULL, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL, 0 }
+ };
+
+ for (i = 0; i < 17; i++)
+ {
+ result = getAttribute(objectID, &pubTemplate[i]);
+ if (result)
+ {
+ freeTemplate(pubTemplate, 17);
+ return 1;
+ }
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 17, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR %X: Could not save the public key in the token. "
+ "Skipping object %lu\n", (unsigned int)rv, objectID);
+ result = 1;
+ }
+ else
+ {
+ printf("Object %lu has been migrated\n", objectID);
+ }
+
+ freeTemplate(pubTemplate, 17);
+
+ return result;
+}
+
+// Extract the information about the private RSA key and save it in the token
+int dbRSAPriv2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession)
+{
+ int result = 0;
+ int i;
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv;
+
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_MODIFIABLE, NULL, 0 },
+ { CKA_LABEL, NULL, 0 },
+ { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_ID, NULL, 0 },
+ { CKA_START_DATE, NULL, 0 },
+ { CKA_END_DATE, NULL, 0 },
+ { CKA_DERIVE, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_SENSITIVE, NULL, 0 },
+ { CKA_DECRYPT, NULL, 0 },
+ { CKA_SIGN, NULL, 0 },
+ { CKA_SIGN_RECOVER, NULL, 0 },
+ { CKA_UNWRAP, NULL, 0 },
+ { CKA_EXTRACTABLE, NULL, 0 },
+ { CKA_WRAP_WITH_TRUSTED, NULL, 0 },
+ { CKA_MODULUS, NULL, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL, 0 },
+ { CKA_PRIVATE_EXPONENT, NULL, 0 },
+ { CKA_PRIME_1, NULL, 0 },
+ { CKA_PRIME_2, NULL, 0 }
+// SoftHSM v1 did not store these values
+// { CKA_EXPONENT_1, NULL, 0 },
+// { CKA_EXPONENT_2, NULL, 0 },
+// { CKA_COEFFICIENT, NULL, 0 }
+ };
+
+ for (i = 0; i < 23; i++)
+ {
+ result = getAttribute(objectID, &privTemplate[i]);
+ if (result)
+ {
+ freeTemplate(privTemplate, 23);
+ return 1;
+ }
+ }
+
+ rv = p11->C_CreateObject(hSession, privTemplate, 23, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR %X: Could not save the private key in the token. "
+ "Skipping object %lu\n", (unsigned int)rv, objectID);
+ result = 1;
+ }
+ else
+ {
+ printf("Object %lu has been migrated\n", objectID);
+ }
+
+ freeTemplate(privTemplate, 23);
+
+ return result;
+}
+
+// Get the value of the given attribute
+int getAttribute(CK_OBJECT_HANDLE objectRef, CK_ATTRIBUTE* attTemplate)
+{
+ int retSQL = 0;
+ int retVal = 0;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, attTemplate->type);
+
+ // Get result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get the attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (length)
+ {
+ attTemplate->pValue = malloc(length);
+ if (!attTemplate->pValue)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory. "
+ "Skipping object %lu\n", objectRef);
+ retVal = 1;
+ }
+ else
+ {
+ // Copy data
+ memcpy(attTemplate->pValue, pValue, length);
+ }
+ }
+
+ attTemplate->ulValueLen = length;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Do not have attribute %lu. "
+ "Skipping object %lu\n", attTemplate->type, objectRef);
+ retVal = 1;
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Free allocated memory in the template
+void freeTemplate(CK_ATTRIBUTE* attTemplate, int size)
+{
+ int i;
+
+ if (!attTemplate) return;
+
+ for (i = 0; i < size; i++)
+ {
+ if(attTemplate[i].pValue)
+ {
+ free(attTemplate[i].pValue);
+ }
+ }
+}
diff --git a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h
new file mode 100644
index 0000000..1b5a066
--- /dev/null
+++ b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-migrate.h
+
+ This program can be used for migrating SoftHSM v1 databases to any
+ PKCS#11 library. The default library is the libsofthsm2.so
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_MIGRATE_H
+#define _SOFTHSM_V2_SOFTHSM2_MIGRATE_H
+
+#include "cryptoki.h"
+#include <sqlite3.h>
+
+// Main functions
+
+void usage();
+int migrate(char* dbPath, CK_SLOT_ID slotID, char* userPIN, int noPublicKey);
+
+// Support functions
+
+sqlite3* openDB(char* dbPath);
+int openP11(CK_SLOT_ID slotID, char* userPIN, CK_SESSION_HANDLE* hSession);
+int db2session(sqlite3* db, CK_SESSION_HANDLE hSession, int noPublicKey);
+int dbRSAPub2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession);
+int dbRSAPriv2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession);
+void freeTemplate(CK_ATTRIBUTE* attTemplate, int size);
+
+// Database functions
+
+CK_OBJECT_HANDLE* getObjects(sqlite3* db, CK_ULONG* objectCount);
+CK_OBJECT_CLASS getObjectClass(CK_OBJECT_HANDLE objectRef);
+CK_KEY_TYPE getKeyType(CK_OBJECT_HANDLE objectRef);
+int getAttribute(CK_OBJECT_HANDLE objectRef, CK_ATTRIBUTE* attTemplate);
+int prepStatements(sqlite3* db);
+void finalStatements();
+
+// Library
+
+static void* moduleHandle;
+extern CK_FUNCTION_LIST_PTR p11;
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_MIGRATE_H
diff --git a/SoftHSMv2/src/bin/util/Makefile.am b/SoftHSMv2/src/bin/util/Makefile.am
new file mode 100644
index 0000000..a552e14
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/Makefile.am
@@ -0,0 +1,40 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../common \
+ -I$(srcdir)/../../lib/ \
+ -I$(srcdir)/../../lib/common \
+ -I$(srcdir)/../../lib/crypto \
+ -I$(srcdir)/../../lib/data_mgr \
+ -I$(srcdir)/../../lib/object_store \
+ -I$(srcdir)/../../lib/pkcs11 \
+ @CRYPTO_INCLUDES@ \
+ @SQLITE3_INCLUDES@
+
+dist_man_MANS = softhsm2-util.1
+
+bin_PROGRAMS = softhsm2-util
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+softhsm2_util_SOURCES = softhsm2-util.cpp \
+ ../common/findslot.cpp \
+ ../common/getpw.cpp \
+ ../common/library.cpp
+
+softhsm2_util_LDADD = @CRYPTO_LIBS@ \
+ @SQLITE3_LIBS@ \
+ ../../lib/libsofthsm_convarch.la
+
+# Compile with support of OpenSSL
+if WITH_OPENSSL
+softhsm2_util_SOURCES += softhsm2-util-ossl.cpp \
+ ../../lib/crypto/OSSLComp.cpp
+endif
+
+# Compile with support of Botan
+if WITH_BOTAN
+softhsm2_util_SOURCES += softhsm2-util-botan.cpp
+endif
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/*.cpp
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp b/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp
new file mode 100644
index 0000000..cecc0ce
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-util-botan.cpp
+
+ Code specific for Botan
+ *****************************************************************************/
+
+#include <config.h>
+#define UTIL_BOTAN
+#include "softhsm2-util.h"
+#include "softhsm2-util-botan.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/pkcs8.h>
+#include <botan/bigint.h>
+#include <botan/version.h>
+#include <botan/der_enc.h>
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+#include <botan/libstate.h>
+bool wasInitialized = false;
+#endif
+
+// Init Botan
+void crypto_init()
+{
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ // The PKCS#11 library might be using Botan
+ // Check if it has already initialized Botan
+ if (Botan::Global_State_Management::global_state_exists())
+ {
+ wasInitialized = true;
+ }
+
+ if (!wasInitialized)
+ {
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+ }
+#else
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+#endif
+}
+
+// Final Botan
+void crypto_final()
+{
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ if (!wasInitialized)
+ {
+ Botan::LibraryInitializer::deinitialize();
+ }
+#else
+ Botan::LibraryInitializer::deinitialize();
+#endif
+}
+
+// Import a aes secret key from given path
+int crypto_import_aes_key
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* label,
+ char* objID,
+ size_t objIDLen
+)
+{
+ const size_t cMaxAesKeySize = 1024 + 1; // including null-character
+ char aesKeyValue[cMaxAesKeySize];
+ FILE* fp = fopen(filePath, "rb");
+ if (fp == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open the secret key file.\n");
+ return 1;
+ }
+ if (fgets(aesKeyValue, cMaxAesKeySize, fp) == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not read the secret key file.\n");
+ fclose(fp);
+ return 1;
+ }
+ fclose(fp);
+
+ CK_BBOOL ckTrue = CK_TRUE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_AES;
+ CK_ATTRIBUTE keyTemplate[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_VALUE, &aesKeyValue, strlen(aesKeyValue) }
+ };
+
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv = p11->C_CreateObject(hSession, keyTemplate, 9, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the secret key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+// Import a key pair from given path
+int crypto_import_key_pair
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* filePIN,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey
+)
+{
+ Botan::Private_Key* pkey = crypto_read_file(filePath, filePIN);
+ if (pkey == NULL)
+ {
+ return 1;
+ }
+
+ Botan::RSA_PrivateKey* rsa = NULL;
+ Botan::DSA_PrivateKey* dsa = NULL;
+#ifdef WITH_ECC
+ Botan::ECDSA_PrivateKey* ecdsa = NULL;
+#endif
+
+ if (pkey->algo_name().compare("RSA") == 0)
+ {
+ rsa = dynamic_cast<Botan::RSA_PrivateKey*>(pkey);
+ }
+ else if (pkey->algo_name().compare("DSA") == 0)
+ {
+ dsa = dynamic_cast<Botan::DSA_PrivateKey*>(pkey);
+ }
+#ifdef WITH_ECC
+ else if (pkey->algo_name().compare("ECDSA") == 0)
+ {
+ ecdsa = dynamic_cast<Botan::ECDSA_PrivateKey*>(pkey);
+ }
+#endif
+ else
+ {
+ fprintf(stderr, "ERROR: %s is not a supported algorithm.\n",
+ pkey->algo_name().c_str());
+ delete pkey;
+ return 1;
+ }
+
+ int result = 0;
+
+ if (rsa)
+ {
+ result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa);
+ }
+ else if (dsa)
+ {
+ result = crypto_save_dsa(hSession, label, objID, objIDLen, noPublicKey, dsa);
+ }
+#ifdef WITH_ECC
+ else if (ecdsa)
+ {
+ result = crypto_save_ecdsa(hSession, label, objID, objIDLen, noPublicKey, ecdsa);
+ }
+#endif
+ else
+ {
+ fprintf(stderr, "ERROR: Could not get the key material.\n");
+ result = 1;
+ }
+
+ delete pkey;
+ return result;
+}
+
+// Read the key from file
+Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN)
+{
+ if (filePath == NULL)
+ {
+ return NULL;
+ }
+
+ Botan::AutoSeeded_RNG* rng = new Botan::AutoSeeded_RNG();
+ Botan::Private_Key* pkey = NULL;
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ if (filePIN == NULL)
+ {
+ pkey = Botan::PKCS8::load_key(std::string(filePath), *rng);
+ }
+ else
+ {
+ pkey = Botan::PKCS8::load_key(std::string(filePath), *rng, std::string(filePIN));
+ }
+#else
+ if (filePIN == NULL)
+ {
+ pkey = Botan::PKCS8::load_key(filePath, *rng);
+ }
+ else
+ {
+ pkey = Botan::PKCS8::load_key(filePath, *rng, filePIN);
+ }
+#endif
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Perhaps wrong path to file, wrong file format, "
+ "or wrong PIN to file (--file-pin <PIN>).\n");
+ delete rng;
+ return NULL;
+ }
+ delete rng;
+
+ return pkey;
+}
+
+// Save the key data in PKCS#11
+int crypto_save_rsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ Botan::RSA_PrivateKey* rsa
+)
+{
+ rsa_key_material_t* keyMat = crypto_malloc_rsa(rsa);
+ if (!keyMat)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_WRAP, &ckTrue, sizeof(ckTrue) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_UNWRAP, &ckTrue, sizeof(ckTrue) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN },
+ { CKA_PRIVATE_EXPONENT, keyMat->bigD, keyMat->sizeD },
+ { CKA_PRIME_1, keyMat->bigP, keyMat->sizeP },
+ { CKA_PRIME_2, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_EXPONENT_1, keyMat->bigDMP1, keyMat->sizeDMP1 },
+ { CKA_EXPONENT_2, keyMat->bigDMQ1, keyMat->sizeDMQ1 },
+ { CKA_COEFFICIENT, keyMat->bigIQMP, keyMat->sizeIQMP }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 19, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_rsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_rsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the Botan key to binary
+rsa_key_material_t* crypto_malloc_rsa(Botan::RSA_PrivateKey* rsa)
+{
+ if (rsa == NULL)
+ {
+ return NULL;
+ }
+
+ rsa_key_material_t* keyMat = (rsa_key_material_t*)malloc(sizeof(rsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeE = rsa->get_e().bytes();
+ keyMat->sizeN = rsa->get_n().bytes();
+ keyMat->sizeD = rsa->get_d().bytes();
+ keyMat->sizeP = rsa->get_p().bytes();
+ keyMat->sizeQ = rsa->get_q().bytes();
+ keyMat->sizeDMP1 = rsa->get_d1().bytes();
+ keyMat->sizeDMQ1 = rsa->get_d2().bytes();
+ keyMat->sizeIQMP = rsa->get_c().bytes();
+
+ keyMat->bigE = (CK_VOID_PTR)malloc(keyMat->sizeE);
+ keyMat->bigN = (CK_VOID_PTR)malloc(keyMat->sizeN);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigDMP1 = (CK_VOID_PTR)malloc(keyMat->sizeDMP1);
+ keyMat->bigDMQ1 = (CK_VOID_PTR)malloc(keyMat->sizeDMQ1);
+ keyMat->bigIQMP = (CK_VOID_PTR)malloc(keyMat->sizeIQMP);
+
+ if
+ (
+ !keyMat->bigE ||
+ !keyMat->bigN ||
+ !keyMat->bigD ||
+ !keyMat->bigP ||
+ !keyMat->bigQ ||
+ !keyMat->bigDMP1 ||
+ !keyMat->bigDMQ1 ||
+ !keyMat->bigIQMP
+ )
+ {
+ crypto_free_rsa(keyMat);
+ return NULL;
+ }
+
+ rsa->get_e().binary_encode((Botan::byte*)keyMat->bigE);
+ rsa->get_n().binary_encode((Botan::byte*)keyMat->bigN);
+ rsa->get_d().binary_encode((Botan::byte*)keyMat->bigD);
+ rsa->get_p().binary_encode((Botan::byte*)keyMat->bigP);
+ rsa->get_q().binary_encode((Botan::byte*)keyMat->bigQ);
+ rsa->get_d1().binary_encode((Botan::byte*)keyMat->bigDMP1);
+ rsa->get_d2().binary_encode((Botan::byte*)keyMat->bigDMQ1);
+ rsa->get_c().binary_encode((Botan::byte*)keyMat->bigIQMP);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_rsa(rsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigE) free(keyMat->bigE);
+ if (keyMat->bigN) free(keyMat->bigN);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigDMP1) free(keyMat->bigDMP1);
+ if (keyMat->bigDMQ1) free(keyMat->bigDMQ1);
+ if (keyMat->bigIQMP) free(keyMat->bigIQMP);
+ free(keyMat);
+}
+
+// Save the key data in PKCS#11
+int crypto_save_dsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ Botan::DSA_PrivateKey* dsa
+)
+{
+ dsa_key_material_t* keyMat = crypto_malloc_dsa(dsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_DSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigY, keyMat->sizeY }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigX, keyMat->sizeX }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 15, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_dsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 12, &hKey2);
+ crypto_free_dsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the Botan key to binary
+dsa_key_material_t* crypto_malloc_dsa(Botan::DSA_PrivateKey* dsa)
+{
+ if (dsa == NULL)
+ {
+ return NULL;
+ }
+
+ dsa_key_material_t *keyMat = (dsa_key_material_t *)malloc(sizeof(dsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeP = dsa->group_p().bytes();
+ keyMat->sizeQ = dsa->group_q().bytes();
+ keyMat->sizeG = dsa->group_g().bytes();
+ keyMat->sizeX = dsa->get_x().bytes();
+ keyMat->sizeY = dsa->get_y().bytes();
+
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigG = (CK_VOID_PTR)malloc(keyMat->sizeG);
+ keyMat->bigX = (CK_VOID_PTR)malloc(keyMat->sizeX);
+ keyMat->bigY = (CK_VOID_PTR)malloc(keyMat->sizeY);
+
+ if (!keyMat->bigP || !keyMat->bigQ || !keyMat->bigG || !keyMat->bigX || !keyMat->bigY)
+ {
+ crypto_free_dsa(keyMat);
+ return NULL;
+ }
+
+ dsa->group_p().binary_encode((Botan::byte*)keyMat->bigP);
+ dsa->group_q().binary_encode((Botan::byte*)keyMat->bigQ);
+ dsa->group_g().binary_encode((Botan::byte*)keyMat->bigG);
+ dsa->get_x().binary_encode((Botan::byte*)keyMat->bigX);
+ dsa->get_y().binary_encode((Botan::byte*)keyMat->bigY);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_dsa(dsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigG) free(keyMat->bigG);
+ if (keyMat->bigX) free(keyMat->bigX);
+ if (keyMat->bigY) free(keyMat->bigY);
+ free(keyMat);
+}
+
+#ifdef WITH_ECC
+// Save the key data in PKCS#11
+int crypto_save_ecdsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ Botan::ECDSA_PrivateKey* ecdsa
+)
+{
+ ecdsa_key_material_t* keyMat = crypto_malloc_ecdsa(ecdsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_ECDSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams },
+ { CKA_EC_POINT, keyMat->derQ, keyMat->sizeQ }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams },
+ { CKA_VALUE, keyMat->bigD, keyMat->sizeD }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 13, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_ecdsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_ecdsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the Botan key to binary
+ecdsa_key_material_t* crypto_malloc_ecdsa(Botan::ECDSA_PrivateKey* ecdsa)
+{
+ if (ecdsa == NULL)
+ {
+ return NULL;
+ }
+
+ ecdsa_key_material_t *keyMat = (ecdsa_key_material_t *)malloc(sizeof(ecdsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> derEC = ecdsa->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ Botan::secure_vector<Botan::byte> derPoint;
+#else
+ Botan::SecureVector<Botan::byte> derEC = ecdsa->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ Botan::SecureVector<Botan::byte> derPoint;
+#endif
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> repr = Botan::EC2OSP(ecdsa->public_point(),
+ Botan::PointGFp::UNCOMPRESSED);
+#else
+ Botan::SecureVector<Botan::byte> repr = Botan::EC2OSP(ecdsa->public_point(),
+ Botan::PointGFp::UNCOMPRESSED);
+#endif
+
+ derPoint = Botan::DER_Encoder()
+ .encode(repr, Botan::OCTET_STRING)
+ .get_contents();
+ }
+ catch (...)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeParams = derEC.size();
+ keyMat->sizeD = ecdsa->private_value().bytes();
+ keyMat->sizeQ = derPoint.size();
+
+ keyMat->derParams = (CK_VOID_PTR)malloc(keyMat->sizeParams);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+
+ if (!keyMat->derParams || !keyMat->bigD || !keyMat->derQ)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+
+ memcpy(keyMat->derParams, &derEC[0], derEC.size());
+ ecdsa->private_value().binary_encode((Botan::byte*)keyMat->bigD);
+ memcpy(keyMat->derQ, &derPoint[0], derPoint.size());
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_ecdsa(ecdsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->derParams) free(keyMat->derParams);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->derQ) free(keyMat->derQ);
+ free(keyMat);
+}
+#endif
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-botan.h b/SoftHSMv2/src/bin/util/softhsm2-util-botan.h
new file mode 100644
index 0000000..8cd4a5e
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-botan.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-util-botan.h
+
+ Header file for Botan implemented
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_UTIL_BOTAN_H
+#define _SOFTHSM_V2_SOFTHSM2_UTIL_BOTAN_H
+
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#ifdef WITH_ECC
+#include <botan/ecdsa.h>
+#endif
+
+typedef struct rsa_key_material_t {
+ CK_ULONG sizeE;
+ CK_ULONG sizeN;
+ CK_ULONG sizeD;
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeDMP1;
+ CK_ULONG sizeDMQ1;
+ CK_ULONG sizeIQMP;
+ CK_VOID_PTR bigE;
+ CK_VOID_PTR bigN;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigDMP1;
+ CK_VOID_PTR bigDMQ1;
+ CK_VOID_PTR bigIQMP;
+ rsa_key_material_t() {
+ sizeE = 0;
+ sizeN = 0;
+ sizeD = 0;
+ sizeP = 0;
+ sizeQ = 0;
+ sizeDMP1 = 0;
+ sizeDMQ1 = 0;
+ sizeIQMP = 0;
+ bigE = NULL_PTR;
+ bigN = NULL_PTR;
+ bigD = NULL_PTR;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigDMP1 = NULL_PTR;
+ bigDMQ1 = NULL_PTR;
+ bigIQMP = NULL_PTR;
+ }
+} rsa_key_material_t;
+
+typedef struct dsa_key_material_t {
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeG;
+ CK_ULONG sizeX;
+ CK_ULONG sizeY;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigG;
+ CK_VOID_PTR bigX;
+ CK_VOID_PTR bigY;
+ dsa_key_material_t() {
+ sizeP = 0;
+ sizeQ = 0;
+ sizeG = 0;
+ sizeX = 0;
+ sizeY = 0;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigG = NULL_PTR;
+ bigX = NULL_PTR;
+ bigY = NULL_PTR;
+ }
+} dsa_key_material_t;
+
+#ifdef WITH_ECC
+typedef struct ecdsa_key_material_t {
+ CK_ULONG sizeParams;
+ CK_ULONG sizeD;
+ CK_ULONG sizeQ;
+ CK_VOID_PTR derParams;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR derQ;
+ ecdsa_key_material_t() {
+ sizeParams = 0;
+ sizeD = 0;
+ sizeQ = 0;
+ derParams = NULL_PTR;
+ bigD = NULL_PTR;
+ derQ = NULL_PTR;
+ }
+} ecdsa_key_material_t;
+#endif
+
+Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN);
+
+// RSA
+int crypto_save_rsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, Botan::RSA_PrivateKey* rsa);
+rsa_key_material_t* crypto_malloc_rsa(Botan::RSA_PrivateKey* rsa);
+void crypto_free_rsa(rsa_key_material_t* keyMat);
+
+// DSA
+int crypto_save_dsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, Botan::DSA_PrivateKey* dsa);
+dsa_key_material_t* crypto_malloc_dsa(Botan::DSA_PrivateKey* dsa);
+void crypto_free_dsa(dsa_key_material_t* keyMat);
+
+// ECDSA
+#ifdef WITH_ECC
+int crypto_save_ecdsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, Botan::ECDSA_PrivateKey* ecdsa);
+ecdsa_key_material_t* crypto_malloc_ecdsa(Botan::ECDSA_PrivateKey* ecdsa);
+void crypto_free_ecdsa(ecdsa_key_material_t* keyMat);
+#endif
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp
new file mode 100644
index 0000000..fedfd28
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp
@@ -0,0 +1,790 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-util-ossl.cpp
+
+ Code specific for OpenSSL
+ *****************************************************************************/
+
+#include <config.h>
+#define UTIL_OSSL
+#include "softhsm2-util.h"
+#include "softhsm2-util-ossl.h"
+#include "OSSLComp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+
+// Init OpenSSL
+void crypto_init()
+{
+ // We do not need to do this one
+ // OpenSSL_add_all_algorithms();
+#ifdef WITH_FIPS
+ // The PKCS#11 library might be using a FIPS capable OpenSSL
+ if (FIPS_mode())
+ return;
+ if (!FIPS_mode_set(1))
+ {
+ fprintf(stderr, "ERROR: can't enter into FIPS mode.\n");
+ exit(0);
+ }
+#endif
+}
+
+// Final OpenSSL
+void crypto_final()
+{
+ // EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+int crypto_import_aes_key
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* label,
+ char* objID,
+ size_t objIDLen
+)
+{
+ const size_t cMaxAesKeySize = 1024 + 1; // including null-character
+ char aesKeyValue[cMaxAesKeySize];
+ FILE* fp = fopen(filePath, "rb");
+ if (fp == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open the secret key file.\n");
+ return 1;
+ }
+ if (fgets(aesKeyValue, cMaxAesKeySize, fp) == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not read the secret key file.\n");
+ fclose(fp);
+ return 1;
+ }
+ fclose(fp);
+
+ CK_BBOOL ckTrue = CK_TRUE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_AES;
+ CK_ATTRIBUTE keyTemplate[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_VALUE, &aesKeyValue, strlen(aesKeyValue) }
+ };
+
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv = p11->C_CreateObject(hSession, keyTemplate, 9, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the secret key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+// Import a key pair from given path
+int crypto_import_key_pair
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* filePIN,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey
+)
+{
+ EVP_PKEY* pkey = crypto_read_file(filePath, filePIN);
+ if (pkey == NULL)
+ {
+ return 1;
+ }
+
+ RSA* rsa = NULL;
+ DSA* dsa = NULL;
+#ifdef WITH_ECC
+ EC_KEY* ecdsa = NULL;
+#endif
+
+ switch (EVP_PKEY_type(EVP_PKEY_id(pkey)))
+ {
+ case EVP_PKEY_RSA:
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ break;
+ case EVP_PKEY_DSA:
+ dsa = EVP_PKEY_get1_DSA(pkey);
+ break;
+#ifdef WITH_ECC
+ case EVP_PKEY_EC:
+ ecdsa = EVP_PKEY_get1_EC_KEY(pkey);
+ break;
+#endif
+ default:
+ fprintf(stderr, "ERROR: Cannot handle this algorithm.\n");
+ EVP_PKEY_free(pkey);
+ return 1;
+ break;
+ }
+ EVP_PKEY_free(pkey);
+
+ int result = 0;
+
+ if (rsa)
+ {
+ result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa);
+ RSA_free(rsa);
+ }
+ else if (dsa)
+ {
+ result = crypto_save_dsa(hSession, label, objID, objIDLen, noPublicKey, dsa);
+ DSA_free(dsa);
+ }
+#ifdef WITH_ECC
+ else if (ecdsa)
+ {
+ result = crypto_save_ecdsa(hSession, label, objID, objIDLen, noPublicKey, ecdsa);
+ EC_KEY_free(ecdsa);
+ }
+#endif
+ else
+ {
+ fprintf(stderr, "ERROR: Could not get the key material.\n");
+ result = 1;
+ }
+
+ return result;
+}
+
+// Read the key from file
+EVP_PKEY* crypto_read_file(char* filePath, char* filePIN)
+{
+ BIO* in = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ EVP_PKEY* pkey = NULL;
+ X509_SIG* p8 = NULL;
+
+ if (!(in = BIO_new_file(filePath, "rb")))
+ {
+ fprintf(stderr, "ERROR: Could open the PKCS#8 file: %s\n", filePath);
+ return NULL;
+ }
+
+ // The PKCS#8 file is encrypted
+ if (filePIN)
+ {
+ p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
+ BIO_free(in);
+
+ if (!p8)
+ {
+ fprintf(stderr, "ERROR: Could not read the PKCS#8 file. "
+ "Maybe the file is not encrypted.\n");
+ return NULL;
+ }
+
+ p8inf = PKCS8_decrypt(p8, filePIN, strlen(filePIN));
+ X509_SIG_free(p8);
+
+ if (!p8inf)
+ {
+ fprintf(stderr, "ERROR: Could not decrypt the PKCS#8 file. "
+ "Maybe wrong PIN to file (--file-pin <PIN>)\n");
+ return NULL;
+ }
+ }
+ else
+ {
+ p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
+ BIO_free(in);
+
+ if (!p8inf)
+ {
+ fprintf(stderr, "ERROR: Could not read the PKCS#8 file. "
+ "Maybe it is encypted (--file-pin <PIN>)\n");
+ return NULL;
+ }
+ }
+
+ // Convert the PKCS#8 to OpenSSL
+ pkey = EVP_PKCS82PKEY(p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (!pkey)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key.\n");
+ return NULL;
+ }
+
+ return pkey;
+}
+
+// Save the key data in PKCS#11
+int crypto_save_rsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ RSA* rsa
+)
+{
+ rsa_key_material_t* keyMat = crypto_malloc_rsa(rsa);
+ if (!keyMat)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_WRAP, &ckTrue, sizeof(ckTrue) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_UNWRAP, &ckTrue, sizeof(ckTrue) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN },
+ { CKA_PRIVATE_EXPONENT, keyMat->bigD, keyMat->sizeD },
+ { CKA_PRIME_1, keyMat->bigP, keyMat->sizeP },
+ { CKA_PRIME_2, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_EXPONENT_1, keyMat->bigDMP1, keyMat->sizeDMP1 },
+ { CKA_EXPONENT_2, keyMat->bigDMQ1, keyMat->sizeDMQ1 },
+ { CKA_COEFFICIENT, keyMat->bigIQMP, keyMat->sizeIQMP }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 19, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_rsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_rsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the OpenSSL key to binary
+rsa_key_material_t* crypto_malloc_rsa(RSA* rsa)
+{
+ if (rsa == NULL)
+ {
+ return NULL;
+ }
+
+ rsa_key_material_t* keyMat = (rsa_key_material_t*)malloc(sizeof(rsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ const BIGNUM* bn_e = NULL;
+ const BIGNUM* bn_n = NULL;
+ const BIGNUM* bn_d = NULL;
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_q = NULL;
+ const BIGNUM* bn_dmp1 = NULL;
+ const BIGNUM* bn_dmq1 = NULL;
+ const BIGNUM* bn_iqmp = NULL;
+ RSA_get0_factors(rsa, &bn_p, &bn_q);
+ RSA_get0_crt_params(rsa, &bn_dmp1, &bn_dmq1, &bn_iqmp);
+ RSA_get0_key(rsa, &bn_n, &bn_e, &bn_d);
+
+ keyMat->sizeE = BN_num_bytes(bn_e);
+ keyMat->sizeN = BN_num_bytes(bn_n);
+ keyMat->sizeD = BN_num_bytes(bn_d);
+ keyMat->sizeP = BN_num_bytes(bn_p);
+ keyMat->sizeQ = BN_num_bytes(bn_q);
+ keyMat->sizeDMP1 = BN_num_bytes(bn_dmp1);
+ keyMat->sizeDMQ1 = BN_num_bytes(bn_dmq1);
+ keyMat->sizeIQMP = BN_num_bytes(bn_iqmp);
+
+ keyMat->bigE = (CK_VOID_PTR)malloc(keyMat->sizeE);
+ keyMat->bigN = (CK_VOID_PTR)malloc(keyMat->sizeN);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigDMP1 = (CK_VOID_PTR)malloc(keyMat->sizeDMP1);
+ keyMat->bigDMQ1 = (CK_VOID_PTR)malloc(keyMat->sizeDMQ1);
+ keyMat->bigIQMP = (CK_VOID_PTR)malloc(keyMat->sizeIQMP);
+
+ if
+ (
+ !keyMat->bigE ||
+ !keyMat->bigN ||
+ !keyMat->bigD ||
+ !keyMat->bigP ||
+ !keyMat->bigQ ||
+ !keyMat->bigDMP1 ||
+ !keyMat->bigDMQ1 ||
+ !keyMat->bigIQMP
+ )
+ {
+ crypto_free_rsa(keyMat);
+ return NULL;
+ }
+
+ BN_bn2bin(bn_e, (unsigned char*)keyMat->bigE);
+ BN_bn2bin(bn_n, (unsigned char*)keyMat->bigN);
+ BN_bn2bin(bn_d, (unsigned char*)keyMat->bigD);
+ BN_bn2bin(bn_p, (unsigned char*)keyMat->bigP);
+ BN_bn2bin(bn_q, (unsigned char*)keyMat->bigQ);
+ BN_bn2bin(bn_dmp1, (unsigned char*)keyMat->bigDMP1);
+ BN_bn2bin(bn_dmq1, (unsigned char*)keyMat->bigDMQ1);
+ BN_bn2bin(bn_iqmp, (unsigned char*)keyMat->bigIQMP);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_rsa(rsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigE) free(keyMat->bigE);
+ if (keyMat->bigN) free(keyMat->bigN);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigDMP1) free(keyMat->bigDMP1);
+ if (keyMat->bigDMQ1) free(keyMat->bigDMQ1);
+ if (keyMat->bigIQMP) free(keyMat->bigIQMP);
+ free(keyMat);
+}
+
+// Save the key data in PKCS#11
+int crypto_save_dsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ DSA* dsa
+)
+{
+ dsa_key_material_t* keyMat = crypto_malloc_dsa(dsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_DSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigY, keyMat->sizeY }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigX, keyMat->sizeX }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 15, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_dsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 12, &hKey2);
+ crypto_free_dsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the OpenSSL key to binary
+dsa_key_material_t* crypto_malloc_dsa(DSA* dsa)
+{
+ if (dsa == NULL)
+ {
+ return NULL;
+ }
+
+ dsa_key_material_t* keyMat = (dsa_key_material_t*)malloc(sizeof(dsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_q = NULL;
+ const BIGNUM* bn_g = NULL;
+ const BIGNUM* bn_priv_key = NULL;
+ const BIGNUM* bn_pub_key = NULL;
+ DSA_get0_pqg(dsa, &bn_p, &bn_q, &bn_g);
+ DSA_get0_key(dsa, &bn_pub_key, &bn_priv_key);
+
+ keyMat->sizeP = BN_num_bytes(bn_p);
+ keyMat->sizeQ = BN_num_bytes(bn_q);
+ keyMat->sizeG = BN_num_bytes(bn_g);
+ keyMat->sizeX = BN_num_bytes(bn_priv_key);
+ keyMat->sizeY = BN_num_bytes(bn_pub_key);
+
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigG = (CK_VOID_PTR)malloc(keyMat->sizeG);
+ keyMat->bigX = (CK_VOID_PTR)malloc(keyMat->sizeX);
+ keyMat->bigY = (CK_VOID_PTR)malloc(keyMat->sizeY);
+
+ if (!keyMat->bigP || !keyMat->bigQ || !keyMat->bigG || !keyMat->bigX || !keyMat->bigY)
+ {
+ crypto_free_dsa(keyMat);
+ return NULL;
+ }
+
+ BN_bn2bin(bn_p, (unsigned char*)keyMat->bigP);
+ BN_bn2bin(bn_q, (unsigned char*)keyMat->bigQ);
+ BN_bn2bin(bn_g, (unsigned char*)keyMat->bigG);
+ BN_bn2bin(bn_priv_key, (unsigned char*)keyMat->bigX);
+ BN_bn2bin(bn_pub_key, (unsigned char*)keyMat->bigY);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_dsa(dsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigG) free(keyMat->bigG);
+ if (keyMat->bigX) free(keyMat->bigX);
+ if (keyMat->bigY) free(keyMat->bigY);
+ free(keyMat);
+}
+
+#ifdef WITH_ECC
+
+// Save the key data in PKCS#11
+int crypto_save_ecdsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ EC_KEY* ecdsa
+)
+{
+ ecdsa_key_material_t* keyMat = crypto_malloc_ecdsa(ecdsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_EC;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams },
+ { CKA_EC_POINT, keyMat->derQ, keyMat->sizeQ },
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams },
+ { CKA_VALUE, keyMat->bigD, keyMat->sizeD }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 13, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_ecdsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_ecdsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the OpenSSL key to binary
+ecdsa_key_material_t* crypto_malloc_ecdsa(EC_KEY* ec_key)
+{
+ int result;
+
+ if (ec_key == NULL)
+ {
+ return NULL;
+ }
+
+ ecdsa_key_material_t* keyMat = (ecdsa_key_material_t*)malloc(sizeof(ecdsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ const BIGNUM *d = EC_KEY_get0_private_key(ec_key);
+ const EC_GROUP *group = EC_KEY_get0_group(ec_key);
+ const EC_POINT *point = EC_KEY_get0_public_key(ec_key);
+
+ keyMat->sizeParams = i2d_ECPKParameters(group, NULL);
+ keyMat->sizeD = BN_num_bytes(d);
+
+ keyMat->derParams = (CK_VOID_PTR)malloc(keyMat->sizeParams);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->derQ = NULL;
+
+ if (!keyMat->derParams || !keyMat->bigD)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+
+ /*
+ * i2d functions increment the pointer, so we have to use a
+ * sacrificial pointer
+ */
+ unsigned char *derParams = (unsigned char*) keyMat->derParams;
+ result = i2d_ECPKParameters(group, &derParams);
+ if (result == 0)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+ BN_bn2bin(d, (unsigned char*)keyMat->bigD);
+
+ size_t point_length = EC_POINT_point2oct(group,
+ point,
+ POINT_CONVERSION_UNCOMPRESSED,
+ NULL,
+ 0,
+ NULL);
+
+ // Definite, short
+ if (point_length <= 0x7f)
+ {
+ keyMat->sizeQ = 2 + point_length;
+ keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ if (!keyMat->derQ)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+
+ unsigned char *derQ = (unsigned char *)keyMat->derQ;
+ derQ[0] = V_ASN1_OCTET_STRING;
+ derQ[1] = point_length & 0x7f;
+ result = EC_POINT_point2oct(group,
+ point,
+ POINT_CONVERSION_UNCOMPRESSED,
+ &derQ[2],
+ point_length,
+ NULL);
+ if (result == 0)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+ }
+ // Definite, long
+ else
+ {
+ // Count significate bytes
+ size_t bytes = sizeof(size_t);
+ for(; bytes > 0; bytes--)
+ {
+ size_t value = point_length >> ((bytes - 1) * 8);
+ if (value & 0xFF) break;
+ }
+
+ keyMat->sizeQ = 2 + bytes + point_length;
+ keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ if (!keyMat->derQ)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+
+ unsigned char *derQ = (unsigned char *)keyMat->derQ;
+ derQ[0] = V_ASN1_OCTET_STRING;
+ derQ[1] = 0x80 | bytes;
+
+ size_t len = point_length;
+ for (size_t i = 1; i <= bytes; i++)
+ {
+ derQ[2+bytes-i] = (unsigned char) (len & 0xFF);
+ len >>= 8;
+ }
+
+ result = EC_POINT_point2oct(group,
+ point,
+ POINT_CONVERSION_UNCOMPRESSED,
+ &derQ[2+bytes],
+ point_length,
+ NULL);
+ if (result == 0)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+ }
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_ecdsa(ecdsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->derParams) free(keyMat->derParams);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->derQ) free(keyMat->derQ);
+ free(keyMat);
+}
+
+#endif
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h
new file mode 100644
index 0000000..7a2a31a
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-util-ossl.h
+
+ Header file for OpenSSL implemented
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H
+#define _SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#ifdef WITH_ECC
+#include <openssl/ec.h>
+#endif
+
+typedef struct rsa_key_material_t {
+ CK_ULONG sizeE;
+ CK_ULONG sizeN;
+ CK_ULONG sizeD;
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeDMP1;
+ CK_ULONG sizeDMQ1;
+ CK_ULONG sizeIQMP;
+ CK_VOID_PTR bigE;
+ CK_VOID_PTR bigN;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigDMP1;
+ CK_VOID_PTR bigDMQ1;
+ CK_VOID_PTR bigIQMP;
+ rsa_key_material_t() {
+ sizeE = 0;
+ sizeN = 0;
+ sizeD = 0;
+ sizeP = 0;
+ sizeQ = 0;
+ sizeDMP1 = 0;
+ sizeDMQ1 = 0;
+ sizeIQMP = 0;
+ bigE = NULL_PTR;
+ bigN = NULL_PTR;
+ bigD = NULL_PTR;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigDMP1 = NULL_PTR;
+ bigDMQ1 = NULL_PTR;
+ bigIQMP = NULL_PTR;
+ }
+} rsa_key_material_t;
+
+typedef struct dsa_key_material_t {
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeG;
+ CK_ULONG sizeX;
+ CK_ULONG sizeY;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigG;
+ CK_VOID_PTR bigX;
+ CK_VOID_PTR bigY;
+ dsa_key_material_t() {
+ sizeP = 0;
+ sizeQ = 0;
+ sizeG = 0;
+ sizeX = 0;
+ sizeY = 0;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigG = NULL_PTR;
+ bigX = NULL_PTR;
+ bigY = NULL_PTR;
+ }
+} dsa_key_material_t;
+
+#ifdef WITH_ECC
+typedef struct ecdsa_key_material_t {
+ CK_ULONG sizeParams;
+ CK_ULONG sizeD;
+ CK_ULONG sizeQ;
+ CK_VOID_PTR derParams;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR derQ;
+ ecdsa_key_material_t() {
+ sizeParams = 0;
+ sizeD = 0;
+ sizeQ = 0;
+ derParams = NULL_PTR;
+ bigD = NULL_PTR;
+ derQ = NULL_PTR;
+ }
+} ecdsa_key_material_t;
+#endif
+
+EVP_PKEY* crypto_read_file(char* filePath, char* filePIN);
+
+// RSA
+int crypto_save_rsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, RSA* rsa);
+rsa_key_material_t* crypto_malloc_rsa(RSA* rsa);
+void crypto_free_rsa(rsa_key_material_t* keyMat);
+
+// DSA
+int crypto_save_dsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, DSA* dsa);
+dsa_key_material_t* crypto_malloc_dsa(DSA* dsa);
+void crypto_free_dsa(dsa_key_material_t* keyMat);
+
+#ifdef WITH_ECC
+// ECDSA
+int crypto_save_ecdsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, EC_KEY* ecdsa);
+ecdsa_key_material_t* crypto_malloc_ecdsa(EC_KEY* ecdsa);
+void crypto_free_ecdsa(ecdsa_key_material_t* keyMat);
+#endif
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util.1 b/SoftHSMv2/src/bin/util/softhsm2-util.1
new file mode 100644
index 0000000..1998226
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util.1
@@ -0,0 +1,259 @@
+.TH SOFTHSM2-UTIL 1 "22 September 2017" "SoftHSM"
+.SH NAME
+softhsm2-util \- support tool for libsofthsm2
+.SH SYNOPSIS
+.B softhsm2-util \-\-show-slots
+.PP
+.B softhsm2-util \-\-init-token
+.B \-\-free
+.B \-\-label
+.I text
+\\
+.ti +0.7i
+.RB [ \-\-so-pin
+.I PIN
+.B \-\-pin
+.IR PIN ]
+.PP
+.B softhsm2-util \-\-import
+.I path
+.RB [ \-\-file-pin
+.IR PIN ]
+.B \-\-token
+.I label
+\\
+.ti +0.7i
+.RB [ \-\-pin
+.I PIN
+.B \-\-no\-public\-key]
+.B \-\-label
+.I text
+.B \-\-id
+.I hex
+.PP
+.B softhsm2-util \-\-import
+.I path
+.B \-\-aes
+.B \-\-token
+.I label
+\\
+.ti +0.7i
+.RB [ \-\-pin
+.I PIN]
+.B \-\-label
+.I text
+.B \-\-id
+.I hex
+.PP
+.B softhsm2-util \-\-delete\-token
+.B \-\-token
+.I text
+.SH DESCRIPTION
+.B softhsm2-util
+is a support tool mainly for libsofthsm2. It can also
+be used with other PKCS#11 libraries by using the option
+.B \-\-module
+.PP
+Read the sections below to get more information on
+the libsofthsm2 and PKCS#11.
+Most applications assumes that the token they want
+to use is already initialized.
+It is then up to the user
+to initialize the PKCS#11 token.
+This is done by using the PKCS#11 interface,
+but instead of writing your own
+tool you can use the
+.B softhsm2-util
+tool.
+.PP
+Keys are usually created directly in the token,
+but the user may want to use an existing key pair.
+Keys can be imported to a token by using the PKCS#11 interface,
+but this tool can also be used if the
+user has the key pair in a PKCS#8 file.
+If you need to convert keys from
+BIND .private-key format over to PKCS#8,
+one can
+use
+.BR softhsm2-keyconv .
+.LP
+The libary
+.BR libsofthsm2 ,
+known as SoftHSM, provides cryptographic functionality
+by using the PKCS#11 API.
+It was developed as a part of the OpenDNSSEC project,
+thus designed to meet the requirements
+of OpenDNSSEC,
+but can also work together with other
+software that want to use the functionality
+of the PKCS#11 API.
+.PP
+SoftHSM is a software implementation of a generic cryptographic device with a PKCS#11 interface.
+These devices are often called tokens.
+Read in the manual softhsm2.conf(5) on how to create these
+tokens and how they are added to a slot in SoftHSM.
+.LP
+The
+.B PKCS#11
+API
+can be used to handle and store cryptographic keys.
+This interface
+specifies how to communicate with cryptographic devices such as HSMs
+(Hardware Security Modules) and smart cards.
+The purpose of these devices
+is, among others,
+to generate cryptographic keys and sign information without
+revealing private-key material to the outside world.
+They are often designed
+to perform well on these specific tasks
+compared to ordinary processes in a normal computer.
+.LP
+.SH ACTIONS
+.TP
+.B \-\-delete\-token
+Delete the token at a given slot.
+Use with
+.BR \-\-token
+or
+.BR \-\-serial .
+Any content in token will be erased.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
+.TP
+.B \-\-import \fIpath\fR
+Import a key pair from the given
+.IR path .
+The file must be in PKCS#8-format.
+.br
+Use with
+.BR \-\-slot
+or
+.BR \-\-token
+or
+.BR \-\-serial ,
+.BR \-\-file-pin ,
+.BR \-\-pin ,
+.BR \-\-no\-public\-key ,
+.BR \-\-label ,
+and
+.BR \-\-id .
+.br
+Can also be used with
+.BR \-\-aes
+to use file as is and import it as AES.
+.TP
+.B \-\-init-token
+Initialize the token at a given slot, token label or token serial.
+If the token is already initialized then this command
+will reinitialize it, thus erasing all the objects in the token.
+The matching Security Officer (SO) PIN must also
+be provided when doing reinitialization.
+Initialized tokens will be reassigned to another slot (based on
+the token serial number).
+.br
+Use with
+.BR \-\-slot
+or
+.BR \-\-token
+or
+.BR \-\-serial
+or
+.BR \-\-free ,
+.BR \-\-label ,
+.BR \-\-so-pin ,
+and
+.BR \-\-pin .
+.LP
+.TP
+.B \-\-show-slots
+Display all the available slots and their current status.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH OPTIONS
+.TP
+.B \-\-aes
+Used to tell import to use file as is and import it as AES.
+.TP
+.B \-\-file-pin \fIPIN\fR
+The
+.I PIN
+will be used to decrypt the PKCS#8 file.
+If not given then the PKCS#8 file is assumed to be unencrypted.
+.TP
+.B \-\-force
+Use this option to override the warnings and force the given action.
+.TP
+.B \-\-free
+Use the first free/uninitialized token.
+.TP
+.B \-\-id \fIhex\fR
+Choose an ID of the key pair.
+The ID is in hexadecimal with a variable length.
+Use with
+.B \-\-force
+when importing a key pair if the ID already exists.
+.TP
+.B \-\-label \fItext\fR
+Defines the
+.I label
+of the object or the token that will be set.
+.TP
+.B \-\-module \fIpath\fR
+Use another PKCS#11 library than SoftHSM.
+.TP
+.B \-\-no\-public\-key
+Do not import the public key.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+for the normal user.
+.TP
+.B \-\-serial \fInumber\fR
+Will use the token with a matching serial number.
+.TP
+.B \-\-slot \fInumber\fR
+The slot where the token is located.
+.TP
+.B \-\-so-pin \fIPIN\fR
+The
+.I PIN
+for the Security Officer (SO).
+.TP
+.B \-\-token \fIlabel\fR
+Will use the token with a matching token label.
+.SH EXAMPLES
+.LP
+The token can be initialized using this command:
+.LP
+.RS
+.nf
+softhsm2-util \-\-init-token \-\-slot 1 \-\-label "mytoken"
+.fi
+.RE
+.LP
+A key pair can be imported using the softhsm tool where you specify the path
+to the key file, slot number, label and ID of the new objects, and the
+user PIN.
+The file must be in PKCS#8 format.
+.LP
+.RS
+.nf
+softhsm2-util \-\-import key1.pem \-\-token "mytoken" \-\-label "My key" \\
+.ti +0.7i
+\-\-id A1B2 \-\-pin 123456
+.fi
+(Add, \-\-file-pin
+.IR PIN ,
+if the key file is encrypted.)
+.RE
+.LP
+.SH AUTHORS
+Written by Rickard Bellgrim, Francis Dupont, René Post, and Roland van Rijswijk.
+.LP
+.SH "SEE ALSO"
+.IR softhsm2-keyconv (1),
+.IR softhsm2-migrate (1),
+.IR softhsm2.conf (5)
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util.cpp b/SoftHSMv2/src/bin/util/softhsm2-util.cpp
new file mode 100644
index 0000000..465df4a
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util.cpp
@@ -0,0 +1,1318 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-util.cpp
+
+ This program can be used for interacting with HSMs using PKCS#11.
+ The default library is the libsofthsm2.so
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm2-util.h"
+#include "findslot.h"
+#include "getpw.h"
+#include "library.h"
+#include "log.h"
+#include "Configuration.h"
+#include "SimpleConfigLoader.h"
+#include "Directory.h"
+#include "MutexFactory.h"
+#include "ObjectStoreToken.h"
+#include "OSPathSep.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#else
+#include <direct.h>
+#include <io.h>
+#endif
+#include <iostream>
+#include <fstream>
+
+// Initialise the one-and-only instance
+
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#endif
+
+// Display the usage
+void usage()
+{
+ printf("Support tool for PKCS#11\n");
+ printf("Usage: softhsm2-util [ACTION] [OPTIONS]\n");
+ printf("Action:\n");
+ printf(" --delete-token Delete the token at a given slot.\n");
+ printf(" Use with --token or --serial.\n");
+ printf(" WARNING: Any content in token will be erased.\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --import <path> Import a key pair from the given path.\n");
+ printf(" The file must be in PKCS#8-format.\n");
+ printf(" Use with --slot or --token or --serial, --file-pin,\n");
+ printf(" --label, --id, --no-public-key, and --pin.\n");
+ printf(" --init-token Initialize the token at a given slot.\n");
+ printf(" Use with --slot or --token or --serial or --free,\n");
+ printf(" --label, --so-pin, and --pin.\n");
+ printf(" WARNING: Any content in token will be erased.\n");
+ printf(" --show-slots Display all the available slots.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+ printf("Options:\n");
+ printf(" --aes Used to tell import to use file as is and import it as AES.\n");
+ printf(" --file-pin <PIN> Supply a PIN if the file is encrypted.\n");
+ printf(" --force Used to override a warning.\n");
+ printf(" --free Use the first free/uninitialized token.\n");
+ printf(" --id <hex> Defines the ID of the object. Hexadecimal characters.\n");
+ printf(" Use with --force if multiple key pairs may share\n");
+ printf(" the same ID.\n");
+ printf(" --label <text> Defines the label of the object or the token.\n");
+ printf(" --module <path> Use another PKCS#11 library than SoftHSM.\n");
+ printf(" --no-public-key Do not import the public key.\n");
+ printf(" --pin <PIN> The PIN for the normal user.\n");
+ printf(" --serial <number> Will use the token with a matching serial number.\n");
+ printf(" --slot <number> The slot where the token is located.\n");
+ printf(" --so-pin <PIN> The PIN for the Security Officer (SO).\n");
+ printf(" --token <label> Will use the token with a matching token label.\n");
+}
+
+// Enumeration of the long options
+enum {
+ OPT_DELETE_TOKEN = 0x100,
+ OPT_FILE_PIN,
+ OPT_FORCE,
+ OPT_FREE,
+ OPT_HELP,
+ OPT_ID,
+ OPT_IMPORT,
+ OPT_INIT_TOKEN,
+ OPT_LABEL,
+ OPT_MODULE,
+ OPT_NO_PUBLIC_KEY,
+ OPT_PIN,
+ OPT_SERIAL,
+ OPT_SHOW_SLOTS,
+ OPT_SLOT,
+ OPT_SO_PIN,
+ OPT_TOKEN,
+ OPT_VERSION,
+ OPT_AES
+};
+
+// Text representation of the long options
+static const struct option long_options[] = {
+ { "delete-token", 0, NULL, OPT_DELETE_TOKEN },
+ { "file-pin", 1, NULL, OPT_FILE_PIN },
+ { "force", 0, NULL, OPT_FORCE },
+ { "free", 0, NULL, OPT_FREE },
+ { "help", 0, NULL, OPT_HELP },
+ { "id", 1, NULL, OPT_ID },
+ { "import", 1, NULL, OPT_IMPORT },
+ { "init-token", 0, NULL, OPT_INIT_TOKEN },
+ { "label", 1, NULL, OPT_LABEL },
+ { "module", 1, NULL, OPT_MODULE },
+ { "no-public-key", 0, NULL, OPT_NO_PUBLIC_KEY },
+ { "pin", 1, NULL, OPT_PIN },
+ { "serial", 1, NULL, OPT_SERIAL },
+ { "show-slots", 0, NULL, OPT_SHOW_SLOTS },
+ { "slot", 1, NULL, OPT_SLOT },
+ { "so-pin", 1, NULL, OPT_SO_PIN },
+ { "token", 1, NULL, OPT_TOKEN },
+ { "version", 0, NULL, OPT_VERSION },
+ { "aes", 0, NULL, OPT_AES },
+ { NULL, 0, NULL, 0 }
+};
+
+CK_FUNCTION_LIST_PTR p11;
+
+// The main function
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt;
+
+ char* inPath = NULL;
+ char* soPIN = NULL;
+ char* userPIN = NULL;
+ char* filePIN = NULL;
+ char* label = NULL;
+ char* module = NULL;
+ char* objectID = NULL;
+ char* slot = NULL;
+ char* serial = NULL;
+ char* token = NULL;
+ char* errMsg = NULL;
+ int forceExec = 0;
+ bool freeToken = false;
+ int noPublicKey = 0;
+ bool importAES = false;
+
+ int doInitToken = 0;
+ int doShowSlots = 0;
+ int doImport = 0;
+ int doDeleteToken = 0;
+ int action = 0;
+ bool needP11 = false;
+ int rv = 0;
+ CK_SLOT_ID slotID = 0;
+
+ moduleHandle = NULL;
+ p11 = NULL;
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_SHOW_SLOTS:
+ doShowSlots = 1;
+ action++;
+ needP11 = true;
+ break;
+ case OPT_INIT_TOKEN:
+ doInitToken = 1;
+ action++;
+ needP11 = true;
+ break;
+ case OPT_IMPORT:
+ doImport = 1;
+ action++;
+ inPath = optarg;
+ needP11 = true;
+ break;
+ case OPT_AES:
+ importAES = true;
+ break;
+ case OPT_DELETE_TOKEN:
+ doDeleteToken = 1;
+ action++;
+ break;
+ case OPT_SLOT:
+ slot = optarg;
+ break;
+ case OPT_LABEL:
+ label = optarg;
+ break;
+ case OPT_SERIAL:
+ serial = optarg;
+ break;
+ case OPT_TOKEN:
+ token = optarg;
+ break;
+ case OPT_MODULE:
+ module = optarg;
+ break;
+ case OPT_NO_PUBLIC_KEY:
+ noPublicKey = 1;
+ break;
+ case OPT_ID:
+ objectID = optarg;
+ break;
+ case OPT_SO_PIN:
+ soPIN = optarg;
+ break;
+ case OPT_PIN:
+ userPIN = optarg;
+ break;
+ case OPT_FILE_PIN:
+ filePIN = optarg;
+ break;
+ case OPT_FORCE:
+ forceExec = 1;
+ break;
+ case OPT_FREE:
+ freeToken = true;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // No action given, display the usage.
+ if (action != 1)
+ {
+ usage();
+ exit(1);
+ }
+
+ if (needP11)
+ {
+ // Check the basic setup of SoftHSM
+ if (!checkSetup())
+ {
+ fprintf(stderr, "ERROR: Please verify that the SoftHSM configuration is correct.\n");
+ exit(1);
+ }
+
+ // Get a pointer to the function list for PKCS#11 library
+ CK_C_GetFunctionList pGetFunctionList = loadLibrary(module, &moduleHandle, &errMsg);
+ if (!pGetFunctionList)
+ {
+ fprintf(stderr, "ERROR: Could not load the PKCS#11 library/module: %s\n", errMsg);
+ fprintf(stderr, "ERROR: Please check log files for additional information.\n");
+ exit(1);
+ }
+
+ // Load the function list
+ (*pGetFunctionList)(&p11);
+
+ // Initialize the library
+ CK_RV p11rv = p11->C_Initialize(NULL_PTR);
+ if (p11rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the PKCS#11 library/module: %s\n", module ? module : DEFAULT_PKCS11_LIB);
+ fprintf(stderr, "ERROR: Please check log files for additional information.\n");
+ exit(1);
+ }
+ }
+
+ // We should create the token.
+ if (doInitToken)
+ {
+ // Get the slotID
+ rv = findSlot(slot, serial, token, freeToken, slotID);
+ if (!rv)
+ {
+ rv = initToken(slotID, label, soPIN, userPIN);
+ }
+ }
+
+ // Show all available slots
+ if (!rv && doShowSlots)
+ {
+ rv = showSlots();
+ }
+
+ // Import a key pair from the given path
+ if (!rv && doImport)
+ {
+ // Get the slotID
+ rv = findSlot(slot, serial, token, slotID);
+ if (!rv)
+ {
+ rv = importAES ? importSecretKey(inPath, slotID, userPIN, label, objectID)
+ : importKeyPair(inPath, filePIN, slotID, userPIN, label, objectID, forceExec, noPublicKey);
+ }
+ }
+
+ // We should delete the token.
+ if (!rv && doDeleteToken)
+ {
+ if (deleteToken(serial, token))
+ {
+ rv = 0;
+ }
+ else
+ {
+ rv = 1;
+ }
+ }
+
+ // Finalize the library
+ if (needP11)
+ {
+ p11->C_Finalize(NULL_PTR);
+ unloadLibrary(moduleHandle);
+ }
+
+ return rv;
+}
+
+// Check the basic setup of SoftHSM
+bool checkSetup()
+{
+ // Initialize the SoftHSM internal functions
+ if (!initSoftHSM())
+ {
+ finalizeSoftHSM();
+ return false;
+ }
+
+ std::string basedir = Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR);
+
+ // Try open the token directory
+ Directory storeDir(basedir);
+ if (!storeDir.isValid())
+ {
+ fprintf(stderr, "ERROR: Failed to enumerate object store in %s\n", basedir.c_str());
+ finalizeSoftHSM();
+ return false;
+ }
+
+ finalizeSoftHSM();
+ return true;
+}
+
+// Initialize the token
+int initToken(CK_SLOT_ID slotID, char* label, char* soPIN, char* userPIN)
+{
+ char so_pin_copy[MAX_PIN_LEN+1];
+ char user_pin_copy[MAX_PIN_LEN+1];
+
+ if (label == NULL)
+ {
+ fprintf(stderr, "ERROR: A label for the token must be supplied. "
+ "Use --label <text>\n");
+ return 1;
+ }
+
+ if (strlen(label) > 32)
+ {
+ fprintf(stderr, "ERROR: The token label must not have a length "
+ "greater than 32 chars.\n");
+ return 1;
+ }
+
+ // Get the passwords
+ if (getPW(soPIN, so_pin_copy, CKU_SO) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get SO PIN\n");
+ return 1;
+ }
+ if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get user PIN\n");
+ return 1;
+ }
+
+ // Load the variables
+ CK_UTF8CHAR paddedLabel[32];
+ memset(paddedLabel, ' ', sizeof(paddedLabel));
+ memcpy(paddedLabel, label, strlen(label));
+
+ CK_RV rv = p11->C_InitToken(slotID, (CK_UTF8CHAR_PTR)so_pin_copy, strlen(so_pin_copy), paddedLabel);
+
+ switch (rv)
+ {
+ case CKR_OK:
+ break;
+ case CKR_SLOT_ID_INVALID:
+ fprintf(stderr, "CKR_SLOT_ID_INVALID: Slot %lu does not exist.\n", slotID);
+ return 1;
+ break;
+ case CKR_PIN_INCORRECT:
+ fprintf(stderr, "CKR_PIN_INCORRECT: The given SO PIN does not match the "
+ "one in the token. Needed when reinitializing the token.\n");
+ return 1;
+ break;
+ case CKR_TOKEN_NOT_PRESENT:
+ fprintf(stderr, "CKR_TOKEN_NOT_PRESENT: The token is not present. "
+ "Please read the HSM manual for further assistance.\n");
+ return 1;
+ break;
+ default:
+ fprintf(stderr, "ERROR rv=0x%08X: Could not initialize the token.\n", (unsigned int)rv);
+ fprintf(stderr, "Please check log files for additional information.\n");
+ return 1;
+ break;
+ }
+
+ CK_SESSION_HANDLE hSession;
+ rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not open a session with the library.\n");
+ return 1;
+ }
+
+ rv = p11->C_Login(hSession, CKU_SO, (CK_UTF8CHAR_PTR)so_pin_copy, strlen(so_pin_copy));
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ return 1;
+ }
+
+ rv = p11->C_InitPIN(hSession, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the user PIN.\n");
+ return 1;
+ }
+
+ // Get the token info
+ CK_TOKEN_INFO tokenInfo;
+ rv = p11->C_GetTokenInfo(slotID, &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the initialized token in slot %lu.\n", slotID);
+ return 1;
+ }
+
+ // Reload the library
+ p11->C_Finalize(NULL_PTR);
+ rv = p11->C_Initialize(NULL_PTR);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the library.\n");
+ return 1;
+ }
+
+ // Get the slotID
+ CK_SLOT_ID newSlotID;
+ if (findSlot(tokenInfo, newSlotID))
+ {
+ return 1;
+ }
+
+ if (slotID == newSlotID)
+ {
+ printf("The token has been initialized on slot %lu\n", newSlotID);
+ }
+ else
+ {
+ printf("The token has been initialized and is reassigned to slot %lu\n", newSlotID);
+ }
+
+ return 0;
+}
+
+// Delete the token
+bool deleteToken(char* serial, char* token)
+{
+ if (serial == NULL && token == NULL)
+ {
+ fprintf(stderr, "ERROR: A token must be supplied. "
+ "Use --serial <serial> or --token <label>\n");
+ return false;
+ }
+
+ // Initialize the SoftHSM internal functions
+ if (!initSoftHSM())
+ {
+ finalizeSoftHSM();
+ return false;
+ }
+
+ bool rv = true;
+ std::string basedir = Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR);
+ std::string tokendir;
+
+ rv = findTokenDirectory(basedir, tokendir, serial, token);
+
+ if (rv)
+ {
+ std::string fulldir = basedir;
+ if (fulldir.find_last_of(OS_PATHSEP) != (fulldir.size()-1))
+ {
+ fulldir += OS_PATHSEP + tokendir;
+ }
+ else
+ {
+ fulldir += tokendir;
+ }
+
+ rv = rmdir(fulldir);
+ if (rv)
+ {
+ printf("The token (%s) has been deleted.\n", fulldir.c_str());
+ }
+ }
+
+ finalizeSoftHSM();
+
+ return rv;
+}
+
+bool initSoftHSM()
+{
+ // Not using threading
+ MutexFactory::i()->disable();
+
+ // Initiate SecureMemoryRegistry
+ if (SecureMemoryRegistry::i() == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not initiate SecureMemoryRegistry.\n");
+ return false;
+ }
+
+ // Build the CryptoFactory
+ if (CryptoFactory::i() == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not initiate CryptoFactory.\n");
+ return false;
+ }
+
+#ifdef WITH_FIPS
+ // Check the FIPS status
+ if (!CryptoFactory::i()->getFipsSelfTestStatus())
+ {
+ fprintf(stderr, "ERROR: FIPS self test failed.\n");
+ return false;
+ }
+#endif
+
+ // Load the configuration
+ if (!Configuration::i()->reload(SimpleConfigLoader::i()))
+ {
+ fprintf(stderr, "ERROR: Could not load the SoftHSM configuration.\n");
+ return false;
+ }
+
+ // Configure the log level
+ if (!setLogLevel(Configuration::i()->getString("log.level", DEFAULT_LOG_LEVEL)))
+ {
+ fprintf(stderr, "ERROR: Could not configure the log level.\n");
+ return false;
+ }
+
+ // Configure object store storage backend used by all tokens.
+ if (!ObjectStoreToken::selectBackend(Configuration::i()->getString("objectstore.backend", DEFAULT_OBJECTSTORE_BACKEND)))
+ {
+ fprintf(stderr, "ERROR: Could not select token backend.\n");
+ return false;
+ }
+
+ return true;
+}
+
+void finalizeSoftHSM()
+{
+ CryptoFactory::reset();
+ SecureMemoryRegistry::reset();
+}
+
+// Find the token directory
+bool findTokenDirectory(std::string basedir, std::string& tokendir, char* serial, char* label)
+{
+ if (serial == NULL && label == NULL)
+ {
+ return false;
+ }
+
+ // Load the variables
+ CK_UTF8CHAR paddedSerial[16];
+ CK_UTF8CHAR paddedLabel[32];
+ if (serial != NULL)
+ {
+ size_t inSize = strlen(serial);
+ size_t outSize = sizeof(paddedSerial);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --serial is too long.\n");
+ return false;
+ }
+ memset(paddedSerial, ' ', outSize);
+ memcpy(paddedSerial, serial, inSize);
+ }
+ if (label != NULL)
+ {
+ size_t inSize = strlen(label);
+ size_t outSize = sizeof(paddedLabel);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --token is too long.\n");
+ return false;
+ }
+ memset(paddedLabel, ' ', outSize);
+ memcpy(paddedLabel, label, inSize);
+ }
+
+ // Find all tokens in the specified path
+ Directory storeDir(basedir);
+
+ if (!storeDir.isValid())
+ {
+ fprintf(stderr, "Failed to enumerate object store in %s\n", basedir.c_str());
+
+ return false;
+ }
+
+ // Assume that all subdirectories are tokens
+ std::vector<std::string> dirs = storeDir.getSubDirs();
+
+ ByteString tokenLabel;
+ ByteString tokenSerial;
+ CK_UTF8CHAR paddedTokenSerial[16];
+ CK_UTF8CHAR paddedTokenLabel[32];
+ size_t counter = 0;
+ for (std::vector<std::string>::iterator i = dirs.begin(); i != dirs.end(); i++)
+ {
+ memset(paddedTokenSerial, ' ', sizeof(paddedTokenSerial));
+ memset(paddedTokenLabel, ' ', sizeof(paddedTokenLabel));
+
+ // Create a token instance
+ ObjectStoreToken* token = ObjectStoreToken::accessToken(basedir, *i);
+
+ if (!token->isValid())
+ {
+ delete token;
+ continue;
+ }
+
+ if (token->getTokenLabel(tokenLabel) && tokenLabel.size() <= sizeof(paddedTokenLabel))
+ {
+ strncpy((char*) paddedTokenLabel, (char*) tokenLabel.byte_str(), tokenLabel.size());
+ }
+ if (token->getTokenSerial(tokenSerial) && tokenSerial.size() <= sizeof(paddedTokenSerial))
+ {
+ strncpy((char*) paddedTokenSerial, (char*) tokenSerial.byte_str(), tokenSerial.size());
+ }
+
+ if (serial != NULL && label == NULL &&
+ memcmp(paddedTokenSerial, paddedSerial, sizeof(paddedSerial)) == 0)
+ {
+ printf("Found token (%s) with matching serial.\n", i->c_str());
+ tokendir = i->c_str();
+ counter++;
+ }
+ if (serial == NULL && label != NULL &&
+ memcmp(paddedTokenLabel, paddedLabel, sizeof(paddedLabel)) == 0)
+ {
+ printf("Found token (%s) with matching token label.\n", i->c_str());
+ tokendir = i->c_str();
+ counter++;
+ }
+ if (serial != NULL && label != NULL &&
+ memcmp(paddedTokenSerial, paddedSerial, sizeof(paddedSerial)) == 0 &&
+ memcmp(paddedTokenLabel, paddedLabel, sizeof(paddedLabel)) == 0)
+ {
+ printf("Found token (%s) with matching serial and token label.\n", i->c_str());
+ tokendir = i->c_str();
+ counter++;
+ }
+
+ delete token;
+ }
+
+ if (counter == 1) return true;
+ if (counter > 1)
+ {
+ fprintf(stderr, "ERROR: Found multiple matching tokens.\n");
+ return false;
+ }
+
+ fprintf(stderr, "ERROR: Could not find a token using --serial or --token.\n");
+ return false;
+}
+
+
+// Delete a directory
+bool rmdir(std::string path)
+{
+ bool rv = true;
+
+#ifndef _WIN32
+ // Enumerate the directory
+ DIR* dir = opendir(path.c_str());
+
+ if (dir == NULL)
+ {
+ fprintf(stderr, "ERROR: Failed to open directory %s\n", path.c_str());
+ return false;
+ }
+
+ // Enumerate the directory
+ struct dirent* entry = NULL;
+
+ while ((entry = readdir(dir)) != NULL)
+ {
+ bool handled = false;
+
+ // Check if this is the . or .. entry
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
+ {
+ continue;
+ }
+
+ // Convert the name of the entry to a C++ string
+ std::string name(entry->d_name);
+ std::string fullPath = path + OS_PATHSEP + name;
+
+#if defined(_DIRENT_HAVE_D_TYPE) && defined(_BSD_SOURCE)
+ // Determine the type of the entry
+ switch(entry->d_type)
+ {
+ case DT_DIR:
+ // This is a directory
+ rv = rmdir(fullPath);
+ handled = true;
+ break;
+ case DT_REG:
+ // This is a regular file
+ rv = rm(fullPath);
+ handled = true;
+ break;
+ default:
+ break;
+ }
+#endif
+
+ if (rv == false)
+ break;
+
+ if (!handled)
+ {
+ // The entry type has to be determined using lstat
+ struct stat entryStatus;
+
+ if (!lstat(fullPath.c_str(), &entryStatus))
+ {
+ if (S_ISDIR(entryStatus.st_mode))
+ {
+ // This is a directory
+ rv = rmdir(fullPath);
+ }
+ else if (S_ISREG(entryStatus.st_mode))
+ {
+ // This is a regular file
+ rv = rm(fullPath);
+ }
+ }
+
+ if (rv == false)
+ break;
+ }
+ }
+
+ // Close the directory
+ closedir(dir);
+#else
+ // Enumerate the directory
+ std::string pattern;
+ intptr_t h;
+ struct _finddata_t fi;
+
+ if ((path.back() == '/') || (path.back() == '\\'))
+ pattern = path + "*";
+ else
+ pattern = path + "/*";
+ memset(&fi, 0, sizeof(fi));
+ h = _findfirst(pattern.c_str(), &fi);
+ if (h == -1)
+ {
+ // empty directory
+ if (errno == ENOENT)
+ goto finished;
+
+ fprintf(stderr, "ERROR: Failed to open directory %s\n", path.c_str());
+
+ return false;
+ }
+
+ // scan files & subdirs
+ do
+ {
+ // Check if this is the . or .. entry
+ if (!strcmp(fi.name, ".") || !strcmp(fi.name, ".."))
+ continue;
+
+ std::string fullPath = path + OS_PATHSEP + fi.name;
+ if ((fi.attrib & _A_SUBDIR) == 0)
+ {
+ // This is a regular file
+ rv = rm(fullPath);
+ }
+ else
+ {
+ // This is a directory
+ rv = rmdir(fullPath);
+ }
+
+ memset(&fi, 0, sizeof(fi));
+
+ if (rv == false)
+ break;
+ } while (_findnext(h, &fi) == 0);
+
+ (void) _findclose(h);
+
+ finished:
+#endif
+
+ if (rv == false)
+ return false;
+
+ int result;
+#ifndef _WIN32
+ result = ::rmdir(path.c_str());
+#else
+ result = _rmdir(path.c_str());
+#endif
+
+ if (result != 0)
+ {
+ fprintf(stderr, "ERROR: Could not delete the directory: %s\n", path.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Delete a file
+bool rm(std::string path)
+{
+ int result;
+
+#ifndef _WIN32
+ result = ::remove(path.c_str());
+#else
+ result = _unlink(path.c_str());
+#endif
+
+ if (result != 0)
+ {
+ fprintf(stderr, "ERROR: Could not delete the file: %s\n", path.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Show what slots are available
+int showSlots()
+{
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (!pSlotList)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ printf("Available slots:\n");
+
+ for (CK_ULONG i = 0; i < ulSlotCount; i++)
+ {
+ CK_SLOT_INFO slotInfo;
+ CK_TOKEN_INFO tokenInfo;
+
+ rv = p11->C_GetSlotInfo(pSlotList[i], &slotInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about slot %lu.\n", pSlotList[i]);
+ continue;
+ }
+
+ printf("Slot %lu\n", pSlotList[i]);
+ printf(" Slot info:\n");
+ printf(" Description: %.*s\n", 64, slotInfo.slotDescription);
+ printf(" Manufacturer ID: %.*s\n", 32, slotInfo.manufacturerID);
+ printf(" Hardware version: %i.%i\n", slotInfo.hardwareVersion.major,
+ slotInfo.hardwareVersion.minor);
+ printf(" Firmware version: %i.%i\n", slotInfo.firmwareVersion.major,
+ slotInfo.firmwareVersion.minor);
+ printf(" Token present: ");
+ if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0)
+ {
+ printf("no\n");
+ continue;
+ }
+
+ printf("yes\n");
+ printf(" Token info:\n");
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ continue;
+ }
+
+ printf(" Manufacturer ID: %.*s\n", 32, tokenInfo.manufacturerID);
+ printf(" Model: %.*s\n", 16, tokenInfo.model);
+ printf(" Hardware version: %i.%i\n", tokenInfo.hardwareVersion.major,
+ tokenInfo.hardwareVersion.minor);
+ printf(" Firmware version: %i.%i\n", tokenInfo.firmwareVersion.major,
+ tokenInfo.firmwareVersion.minor);
+ printf(" Serial number: %.*s\n", 16, tokenInfo.serialNumber);
+ printf(" Initialized: ");
+ if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0)
+ {
+ printf("no\n");
+ }
+ else
+ {
+ printf("yes\n");
+ }
+
+ printf(" User PIN init.: ");
+ if ((tokenInfo.flags & CKF_USER_PIN_INITIALIZED) == 0)
+ {
+ printf("no\n");
+ }
+ else
+ {
+ printf("yes\n");
+ }
+
+ printf(" Label: %.*s\n", 32, tokenInfo.label);
+
+ }
+
+ free(pSlotList);
+
+ return 0;
+}
+
+// Import a key pair from given path
+int importKeyPair
+(
+ char* filePath,
+ char* filePIN,
+ CK_SLOT_ID slotID,
+ char* userPIN,
+ char* label,
+ char* objectID,
+ int forceExec,
+ int noPublicKey
+)
+{
+ char user_pin_copy[MAX_PIN_LEN+1];
+
+ if (label == NULL)
+ {
+ fprintf(stderr, "ERROR: A label for the object must be supplied. "
+ "Use --label <text>\n");
+ return 1;
+ }
+
+ if (objectID == NULL)
+ {
+ fprintf(stderr, "ERROR: An ID for the object must be supplied. "
+ "Use --id <hex>\n");
+ return 1;
+ }
+
+ size_t objIDLen = 0;
+ char* objID = hexStrToBin(objectID, strlen(objectID), &objIDLen);
+ if (objID == NULL)
+ {
+ fprintf(stderr, "Please edit --id <hex> to correct error.\n");
+ return 1;
+ }
+
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_SLOT_ID_INVALID)
+ {
+ fprintf(stderr, "ERROR: The given slot does not exist.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
+ }
+ free(objID);
+ return 1;
+ }
+
+ // Get the password
+ if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get user PIN\n");
+ free(objID);
+ return 1;
+ }
+
+ rv = p11->C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_PIN_INCORRECT) {
+ fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ }
+ free(objID);
+ return 1;
+ }
+
+ CK_OBJECT_HANDLE oHandle = searchObject(hSession, objID, objIDLen);
+ if (oHandle != CK_INVALID_HANDLE && forceExec == 0)
+ {
+ free(objID);
+ fprintf(stderr, "ERROR: The ID is already assigned to another object. "
+ "Use --force to override this message.\n");
+ return 1;
+ }
+
+ crypto_init();
+ int result = crypto_import_key_pair(hSession, filePath, filePIN, label, objID, objIDLen, noPublicKey);
+ crypto_final();
+
+ free(objID);
+
+ return result;
+}
+
+// Import a secret key from given path
+int importSecretKey(char* filePath, CK_SLOT_ID slotID, char* userPIN, char* label, char* objectID)
+{
+ char user_pin_copy[MAX_PIN_LEN+1];
+
+ if (label == NULL)
+ {
+ fprintf(stderr, "ERROR: A label for the object must be supplied. "
+ "Use --label <text>\n");
+ return 1;
+ }
+
+ if (objectID == NULL)
+ {
+ fprintf(stderr, "ERROR: An ID for the object must be supplied. "
+ "Use --id <hex>\n");
+ return 1;
+ }
+
+ size_t objIDLen = 0;
+ char* objID = hexStrToBin(objectID, strlen(objectID), &objIDLen);
+ if (objID == NULL)
+ {
+ fprintf(stderr, "Please edit --id <hex> to correct error.\n");
+ return 1;
+ }
+
+ // Get the password
+ if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get user PIN\n");
+ return 1;
+ }
+
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_SLOT_ID_INVALID)
+ {
+ fprintf(stderr, "ERROR: The given slot does not exist.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
+ }
+ return 1;
+ }
+
+ rv = p11->C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_PIN_INCORRECT) {
+ fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ }
+ return 1;
+ }
+
+ crypto_init();
+ int result = crypto_import_aes_key(hSession, filePath, label, objID, objIDLen);
+ crypto_final();
+
+ return result;
+}
+
+// Convert a char array of hexadecimal characters into a binary representation
+char* hexStrToBin(char* objectID, int idLength, size_t* newLen)
+{
+ char* bytes = NULL;
+
+ if (idLength < 2 || idLength % 2 != 0)
+ {
+ fprintf(stderr, "ERROR: Invalid length on hex string.\n");
+ return NULL;
+ }
+
+ for (int i = 0; i < idLength; i++)
+ {
+ if (hexdigit_to_int(objectID[i]) == -1)
+ {
+ fprintf(stderr, "ERROR: Invalid character in hex string.\n");
+ return NULL;
+ }
+ }
+
+ *newLen = idLength / 2;
+ bytes = (char*) malloc(*newLen);
+ if (bytes == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return NULL;
+ }
+
+ for (size_t i = 0; i < *newLen; i++)
+ {
+ bytes[i] = hexdigit_to_int(objectID[2*i]) * 16 +
+ hexdigit_to_int(objectID[2*i+1]);
+ }
+
+ return bytes;
+}
+
+// Return the integer value of a hexadecimal character
+int hexdigit_to_int(char ch)
+{
+ switch (ch)
+ {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ case 'a':
+ case 'A':
+ return 10;
+ case 'b':
+ case 'B':
+ return 11;
+ case 'c':
+ case 'C':
+ return 12;
+ case 'd':
+ case 'D':
+ return 13;
+ case 'e':
+ case 'E':
+ return 14;
+ case 'f':
+ case 'F':
+ return 15;
+ default:
+ return -1;
+ }
+}
+
+// Search for an object
+CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, size_t objIDLen)
+{
+ if (objID == NULL)
+ {
+ return CK_INVALID_HANDLE;
+ }
+
+ CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+ CK_ULONG objectCount = 0;
+
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &oClass, sizeof(oClass) },
+ { CKA_ID, objID, objIDLen }
+ };
+
+ CK_RV rv = p11->C_FindObjectsInit(hSession, objTemplate, 2);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not prepare the object search.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ rv = p11->C_FindObjects(hSession, &hObject, 1, &objectCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the search results.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ rv = p11->C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not finalize the search.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ if (objectCount == 0)
+ {
+ return CK_INVALID_HANDLE;
+ }
+
+ return hObject;
+}
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util.h b/SoftHSMv2/src/bin/util/softhsm2-util.h
new file mode 100644
index 0000000..3c49314
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-util.h
+
+ This program can be used for interacting with HSMs using PKCS#11.
+ The default library is the libsofthsm2.so
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_UTIL_H
+#define _SOFTHSM_V2_SOFTHSM2_UTIL_H
+
+#include "cryptoki.h"
+#include <string>
+
+// Main functions
+
+void usage();
+bool checkSetup();
+int initToken(CK_SLOT_ID slotID, char* label, char* soPIN, char* userPIN);
+bool deleteToken(char* serial, char* token);
+bool findTokenDirectory(std::string basedir, std::string& tokendir, char* serial, char* label);
+bool rmdir(std::string path);
+bool rm(std::string path);
+int showSlots();
+int importKeyPair(char* filePath, char* filePIN, CK_SLOT_ID slotID, char* userPIN, char* objectLabel, char* objectID, int forceExec, int noPublicKey);
+int importSecretKey(char* filePath, CK_SLOT_ID slotID, char* userPIN, char* label, char* objectID);
+int crypto_import_key_pair(CK_SESSION_HANDLE hSession, char* filePath, char* filePIN, char* label, char* objID, size_t objIDLen, int noPublicKey);
+int crypto_import_aes_key(CK_SESSION_HANDLE hSession, char* filePath, char* label, char* objID, size_t objIDLen);
+
+// Support functions
+
+void crypto_init();
+void crypto_final();
+
+/// SoftHSM internal funtions
+bool initSoftHSM();
+void finalizeSoftHSM();
+
+/// Hex
+char* hexStrToBin(char* objectID, int idLength, size_t* newLen);
+int hexdigit_to_int(char ch);
+
+/// Library
+#if !defined(UTIL_BOTAN) && !defined(UTIL_OSSL)
+static void* moduleHandle;
+#endif
+extern CK_FUNCTION_LIST_PTR p11;
+
+/// PKCS#11 support
+CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, size_t objIDLen);
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_H
diff --git a/SoftHSMv2/src/bin/win32/getopt.cpp b/SoftHSMv2/src/bin/win32/getopt.cpp
new file mode 100644
index 0000000..dfeabe2
--- /dev/null
+++ b/SoftHSMv2/src/bin/win32/getopt.cpp
@@ -0,0 +1,520 @@
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+
+/* Windows needs warnx(). We change the definition though:
+ * 1. (another) global is defined, opterrmsg, which holds the error message
+ * 2. errors are always printed out on stderr w/o the program name
+ * Note that opterrmsg always gets set no matter what opterr is set to. The
+ * error message will not be printed if opterr is 0 as usual.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern char opterrmsg[128];
+char opterrmsg[128]; /* last error message is stored here */
+
+static void warnx(int print_error, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (fmt != NULL)
+ _vsnprintf(opterrmsg, 128, fmt, ap);
+ else
+ opterrmsg[0]='\0';
+ va_end(ap);
+ if (print_error) {
+ fprintf(stderr, opterrmsg);
+ fprintf(stderr, "\n");
+ }
+}
+
+#endif /*_WIN32*/
+
+/* not part of the original file */
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(X)
+#endif
+
+#if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND
+#define REPLACE_GETOPT
+#endif
+
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = '?'; /* character checked for validity */
+int optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+#if !HAVE_GETOPT_LONG
+#define IGNORE_FIRST (*options == '-' || *options == '+')
+#define PRINT_ERROR ((opterr) && ((*options != ':') \
+ || (IGNORE_FIRST && options[1] != ':')))
+#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
+#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
+/* XXX: GNU ignores PC if *options == '-' */
+#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
+
+/* return values */
+#define BADCH (int)'?'
+#define BADARG ((IGNORE_FIRST && options[1] == ':') \
+ || (*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#define EMSG ""
+
+static int getopt_internal(int, char * const *, const char *);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1; /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "unknown option -- %c";
+static const char illoptstring[] = "unknown option -- %s";
+
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return b;
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end,
+ int opt_end, char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ _DIAGASSERT(nargv != NULL);
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = panonopt_end - panonopt_start;
+ nopts = opt_end - panonopt_end;
+ ncycle = gcd(nnonopts, nopts);
+ cyclelen = (opt_end - panonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
+ cstart = panonopt_end+i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++) {
+ if (pos >= panonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **) nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **)nargv)[cstart] = swap;
+ }
+ }
+}
+
+/*
+ * getopt_internal --
+ * Parse argc/argv argument vector. Called by user level routines.
+ * Returns -2 if -- is found (can be long option or end of options marker).
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options)
+{
+ char *oli; /* option letter list index */
+ int optchar;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+
+ optarg = NULL;
+
+ /*
+ * XXX Some programs (like rsyncd) expect to be able to
+ * XXX re-initialize optind to 0 and have getopt_long(3)
+ * XXX properly function again. Work around this braindamage.
+ */
+ if (optind == 0)
+ optind = 1;
+
+ if (optreset)
+ nonopt_start = nonopt_end = -1;
+start:
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc) { /* end of argument vector */
+ place = EMSG;
+ if (nonopt_end != -1) {
+ /* do permutation, if we have to */
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ else if (nonopt_start != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ optind = nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return -1;
+ }
+ if ((*(place = nargv[optind]) != '-')
+ || (place[1] == '\0')) { /* found non-option */
+ place = EMSG;
+ if (IN_ORDER) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ optarg = nargv[optind++];
+ return INORDER;
+ }
+ if (!PERMUTE) {
+ /*
+ * if no permutation wanted, stop parsing
+ * at first non-option
+ */
+ return -1;
+ }
+ /* do permutation */
+ if (nonopt_start == -1)
+ nonopt_start = optind;
+ else if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ nonopt_start = optind -
+ (nonopt_end - nonopt_start);
+ nonopt_end = -1;
+ }
+ optind++;
+ /* process next argument */
+ goto start;
+ }
+ if (nonopt_start != -1 && nonopt_end == -1)
+ nonopt_end = optind;
+ if (place[1] && *++place == '-') { /* found "--" */
+ place++;
+ return -2;
+ }
+ }
+ if ((optchar = (int)*place++) == (int)':' ||
+ (oli = (char *) strchr(options + (IGNORE_FIRST ? 1 : 0),
+ optchar)) == NULL) {
+ /* option letter unknown or ':' */
+ if (!*place)
+ ++optind;
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(illoptchar, optchar);
+#else
+ warnx(PRINT_ERROR, illoptchar, optchar);
+#endif
+ optopt = optchar;
+ return BADCH;
+ }
+ if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
+ /* XXX: what if no long options provided (called by getopt)? */
+ if (*place)
+ return -2;
+
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+#else
+ warnx(PRINT_ERROR, recargchar, optchar);
+#endif
+ optopt = optchar;
+ return BADARG;
+ } else /* white space */
+ place = nargv[optind];
+ /*
+ * Handle -W arg the same as --arg (which causes getopt to
+ * stop parsing).
+ */
+ return -2;
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*place)
+ ++optind;
+ } else { /* takes (optional) argument */
+ optarg = NULL;
+ if (*place) /* no white space */
+ optarg = place;
+ /* XXX: disable test for :: if PC? (GNU doesn't) */
+ else if (oli[1] != ':') { /* arg not optional */
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+#else
+ warnx(PRINT_ERROR, recargchar, optchar);
+#endif
+ optopt = optchar;
+ return BADARG;
+ } else
+ optarg = nargv[optind];
+ }
+ place = EMSG;
+ ++optind;
+ }
+ /* dump back option letter */
+ return optchar;
+}
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the real getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+ int retval;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ ++optind;
+ /*
+ * We found an option (--), so if we skipped non-options,
+ * we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end, optind,
+ nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ retval = -1;
+ }
+ return retval;
+}
+
+/*
+ * getopt_long --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc,
+ char * const *nargv,
+ const char *options,
+ const struct option *long_options,
+ int *idx)
+{
+ int retval;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+ _DIAGASSERT(long_options != NULL);
+ /* idx may be NULL */
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ char *current_argv, *has_equal;
+ size_t current_argv_len;
+ int i, match;
+
+ current_argv = place;
+ match = -1;
+
+ optind++;
+ place = EMSG;
+
+ if (*current_argv == '\0') { /* found "--" */
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return -1;
+ }
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else
+ current_argv_len = strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) ==
+ (unsigned)current_argv_len) {
+ /* exact match */
+ match = i;
+ break;
+ }
+ if (match == -1) /* partial match */
+ match = i;
+ else {
+ /* ambiguous abbreviation */
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(ambig, (int)current_argv_len,
+ current_argv);
+#else
+ warnx(PRINT_ERROR, ambig, (int)current_argv_len,
+ current_argv);
+#endif
+ optopt = 0;
+ return BADCH;
+ }
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(noarg, (int)current_argv_len,
+ current_argv);
+#else
+ warnx(PRINT_ERROR, noarg, (int)current_argv_len,
+ current_argv);
+#endif
+ /*
+ * XXX: GNU sets optopt to val regardless of
+ * flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ return BADARG;
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else if (long_options[match].has_arg ==
+ required_argument) {
+ /*
+ * optional argument doesn't use
+ * next nargv
+ */
+ optarg = nargv[optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument; leading ':'
+ * indicates no error should be generated
+ */
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(recargstring, current_argv);
+#else
+ warnx(PRINT_ERROR, recargstring, current_argv);
+#endif
+ /*
+ * XXX: GNU sets optopt to val regardless
+ * of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ --optind;
+ return BADARG;
+ }
+ } else { /* unknown option */
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(illoptstring, current_argv);
+#else
+ warnx(PRINT_ERROR, illoptstring, current_argv);
+#endif
+ optopt = 0;
+ return BADCH;
+ }
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ retval = 0;
+ } else
+ retval = long_options[match].val;
+ if (idx)
+ *idx = match;
+ }
+ return retval;
+}
+#endif /* !GETOPT_LONG */
diff --git a/SoftHSMv2/src/bin/win32/getopt.h b/SoftHSMv2/src/bin/win32/getopt.h
new file mode 100644
index 0000000..f6b65a5
--- /dev/null
+++ b/SoftHSMv2/src/bin/win32/getopt.h
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GETOPT_H_
+#define _GETOPT_H_
+
+#ifdef _WIN32
+/* from <sys/cdefs.h> */
+# ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+# define __P(args) args
+#endif
+
+/*#ifndef _WIN32
+#include <sys/cdefs.h>
+#include <unistd.h>
+#endif*/
+
+/*
+ * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions
+ */
+#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+struct option {
+ /* name of long option */
+ const char *name;
+ /*
+ * one of no_argument, required_argument, and optional_argument:
+ * whether option takes an argument
+ */
+ int has_arg;
+ /* if not NULL, set *flag to val when option found */
+ int *flag;
+ /* if flag not NULL, value to set *flag to; else return value */
+ int val;
+};
+
+__BEGIN_DECLS
+int getopt_long __P((int, char * const *, const char *,
+ const struct option *, int *));
+__END_DECLS
+#endif
+
+#ifdef _WIN32
+/* These are global getopt variables */
+__BEGIN_DECLS
+
+extern int opterr, /* if error message should be printed */
+ optind, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+extern char* optarg; /* argument associated with option */
+
+/* Original getopt */
+int getopt __P((int, char * const *, const char *));
+
+__END_DECLS
+#endif
+
+#endif /* !_GETOPT_H_ */
diff --git a/SoftHSMv2/src/bin/win32/getpassphase.cpp b/SoftHSMv2/src/bin/win32/getpassphase.cpp
new file mode 100644
index 0000000..9d8aaca
--- /dev/null
+++ b/SoftHSMv2/src/bin/win32/getpassphase.cpp
@@ -0,0 +1,35 @@
+/* WIN32 getpassphrase */
+
+#include <config.h>
+#include <stdio.h>
+
+char *
+getpassphrase(const char *prompt) {
+ static char buf[128];
+ HANDLE h;
+ DWORD cc, mode;
+ int cnt;
+
+ h = GetStdHandle(STD_INPUT_HANDLE);
+ fputs(prompt, stderr);
+ fflush(stderr);
+ fflush(stdout);
+ FlushConsoleInputBuffer(h);
+ GetConsoleMode(h, &mode);
+ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
+
+ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
+ {
+ ReadFile(h, buf + cnt, 1, &cc, NULL);
+ if (buf[cnt] == '\r')
+ break;
+ fputc('*', stdout);
+ fflush(stderr);
+ fflush(stdout);
+ }
+
+ SetConsoleMode(h, mode);
+ buf[cnt] = '\0';
+ fputs("\n", stderr);
+ return (buf);
+}
diff --git a/SoftHSMv2/src/lib/Makefile.am b/SoftHSMv2/src/lib/Makefile.am
new file mode 100644
index 0000000..f3f5bb4
--- /dev/null
+++ b/SoftHSMv2/src/lib/Makefile.am
@@ -0,0 +1,52 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/common \
+ -I$(srcdir)/crypto \
+ -I$(srcdir)/data_mgr \
+ -I$(srcdir)/handle_mgr \
+ -I$(srcdir)/object_store \
+ -I$(srcdir)/pkcs11 \
+ -I$(srcdir)/session_mgr \
+ -I$(srcdir)/slot_mgr \
+ @CRYPTO_INCLUDES@
+
+lib_LTLIBRARIES = libsofthsm2.la
+
+libsofthsm2_la_SOURCES = access.cpp \
+ main.cpp \
+ P11Attributes.cpp \
+ P11Objects.cpp \
+ SoftHSM.cpp
+libsofthsm2_la_LIBADD = common/libsofthsm_common.la \
+ crypto/libsofthsm_crypto.la \
+ data_mgr/libsofthsm_datamgr.la \
+ handle_mgr/libsofthsm_handlemgr.la \
+ object_store/libsofthsm_objectstore.la \
+ session_mgr/libsofthsm_sessionmgr.la \
+ slot_mgr/libsofthsm_slotmgr.la
+libsofthsm2_la_LDFLAGS = -version-info @VERSION_INFO@ \
+ -avoid-version -module
+
+# Create a convenience library from all the other convenience library; this is
+# necessary to resolve circular dependencies when statically linking the test
+# executables
+noinst_LTLIBRARIES = libsofthsm_convarch.la
+
+libsofthsm_convarch_la_SOURCES =
+
+libsofthsm_convarch_la_LIBADD = $(libsofthsm2_la_LIBADD)
+
+SUBDIRS = common \
+ crypto \
+ data_mgr \
+ object_store \
+ session_mgr \
+ slot_mgr \
+ handle_mgr \
+ test
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/pkcs11/*.h \
+ $(srcdir)/win32/*.cc \
+ $(srcdir)/win32/*.cpp \
+ $(srcdir)/win32/*.h
diff --git a/SoftHSMv2/src/lib/P11Attributes.cpp b/SoftHSMv2/src/lib/P11Attributes.cpp
new file mode 100644
index 0000000..28d0f9b
--- /dev/null
+++ b/SoftHSMv2/src/lib/P11Attributes.cpp
@@ -0,0 +1,2514 @@
+/*
+ * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ P11Attributes.h
+
+ This file contains classes for controlling attributes
+ *****************************************************************************/
+
+#include "config.h"
+#include "P11Attributes.h"
+#include "ByteString.h"
+#include "CryptoFactory.h"
+#include "DESKey.h"
+#include "AESKey.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+// Constructor
+P11Attribute::P11Attribute(OSObject* inobject)
+{
+ osobject = inobject;
+ type = CKA_VENDOR_DEFINED;
+ size = (CK_ULONG)-1;
+ checks = 0;
+}
+
+// Destructor
+P11Attribute::~P11Attribute()
+{
+}
+
+CK_RV P11Attribute::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ ByteString value;
+ if (isPrivate)
+ {
+ if (!token->encrypt(ByteString((unsigned char*)pValue, ulValueLen),value))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ value = ByteString((unsigned char*)pValue, ulValueLen);
+ if (value.size() < ulValueLen)
+ return CKR_GENERAL_ERROR;
+ osobject->setAttribute(type, value);
+ return CKR_OK;
+}
+
+bool P11Attribute::isModifiable()
+{
+ // Get the CKA_MODIFIABLE attribute, when the attribute is
+ // not present return the default value which is CK_TRUE.
+ if (!osobject->attributeExists(CKA_MODIFIABLE)) return true;
+
+ return osobject->getBooleanValue(CKA_MODIFIABLE, true);
+}
+
+bool P11Attribute::isSensitive()
+{
+ // Get the CKA_SENSITIVE attribute, when the attribute is not present
+ // assume the object is not sensitive.
+ if (!osobject->attributeExists(CKA_SENSITIVE)) return false;
+
+ return osobject->getBooleanValue(CKA_SENSITIVE, false);
+}
+
+bool P11Attribute::isExtractable()
+{
+ // Get the CKA_EXTRACTABLE attribute, when the attribute is
+ // not present assume the object allows extraction.
+ if (!osobject->attributeExists(CKA_EXTRACTABLE)) return true;
+
+ return osobject->getBooleanValue(CKA_EXTRACTABLE, true);
+}
+
+bool P11Attribute::isTrusted()
+{
+ // Get the CKA_TRUSTED attribute, when the attribute is
+ // not present assume the object is not trusted.
+ if (!osobject->attributeExists(CKA_TRUSTED)) return false;
+
+ return osobject->getBooleanValue(CKA_TRUSTED, false);
+}
+
+// Initialize the attribute
+bool P11Attribute::init()
+{
+ if (osobject == NULL) return false;
+
+ // Create a default value if the attribute does not exist
+ if (osobject->attributeExists(type) == false)
+ {
+ return setDefault();
+ }
+
+ return true;
+}
+
+// Return the attribute type
+CK_ATTRIBUTE_TYPE P11Attribute::getType()
+{
+ return type;
+}
+
+// Return the attribute checks
+CK_ATTRIBUTE_TYPE P11Attribute::getChecks()
+{
+ return checks;
+}
+
+// Retrieve a template map
+static CK_RV retrieveAttributeMap(CK_ATTRIBUTE_PTR pTemplate, const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& map)
+{
+ size_t nullcnt = 0;
+
+ for (size_t i = 0; i < map.size(); ++i)
+ {
+ if (pTemplate[i].pValue == NULL_PTR)
+ ++nullcnt;
+ }
+
+ // Caller wants type & size
+ if (nullcnt == map.size())
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute>::const_iterator a = map.begin();
+ for (size_t i = 0; i < map.size(); ++i, ++a)
+ {
+ pTemplate[i].type = a->first;
+ const OSAttribute& attr = a->second;
+ if (attr.isBooleanAttribute())
+ {
+ pTemplate[i].ulValueLen = sizeof(CK_BBOOL);
+ }
+ else if (attr.isUnsignedLongAttribute())
+ {
+ pTemplate[i].ulValueLen = sizeof(CK_ULONG);
+ }
+ else if (attr.isByteStringAttribute())
+ {
+ pTemplate[i].ulValueLen = attr.getByteStringValue().size();
+ }
+ else
+ {
+ // Impossible
+ ERROR_MSG("Internal error: bad attribute in attribute map");
+
+ return CKR_GENERAL_ERROR;
+ }
+ }
+
+ return CKR_OK;
+ }
+
+ // Callers wants to get values
+ for (size_t i = 0; i < map.size(); ++i)
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute>::const_iterator a = map.find(pTemplate[i].type);
+ if (a == map.end())
+ {
+ pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION;
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+ const OSAttribute& attr = a->second;
+ if (attr.isBooleanAttribute())
+ {
+ if (pTemplate[i].ulValueLen < sizeof(CK_BBOOL))
+ {
+ pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ pTemplate[i].ulValueLen = sizeof(CK_BBOOL);
+ *(CK_BBOOL*)pTemplate[i].pValue = attr.getBooleanValue() ? CK_TRUE : CK_FALSE;
+ }
+ else if (attr.isUnsignedLongAttribute())
+ {
+ if (pTemplate[i].ulValueLen < sizeof(CK_ULONG))
+ {
+ pTemplate[i].ulValueLen= CK_UNAVAILABLE_INFORMATION;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ pTemplate[i].ulValueLen = sizeof(CK_ULONG);
+ *(CK_ULONG_PTR)pTemplate[i].pValue= attr.getUnsignedLongValue();
+ }
+ else if (attr.isByteStringAttribute())
+ {
+ ByteString value = attr.getByteStringValue();
+ if (pTemplate[i].ulValueLen < value.size())
+ {
+ pTemplate[i].ulValueLen= CK_UNAVAILABLE_INFORMATION;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ pTemplate[i].ulValueLen = value.size();
+ memcpy(pTemplate[i].pValue, value.const_byte_str(), value.size());
+ }
+ else
+ {
+ // Impossible
+ ERROR_MSG("Internal error: bad attribute in attribute map");
+
+ return CKR_GENERAL_ERROR;
+ }
+ }
+
+ return CKR_OK;
+}
+
+// Retrieve the value if allowed
+CK_RV P11Attribute::retrieve(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG_PTR pulValueLen)
+{
+
+ if (osobject == NULL) {
+ ERROR_MSG("Internal error: osobject field contains NULL_PTR");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (pulValueLen == NULL) {
+ ERROR_MSG("Internal error: pulValueLen contains NULL_PTR");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // [PKCS#11 v2.40, C_GetAttributeValue]
+ // 1. If the specified attribute (i.e., the attribute specified by the
+ // type field) for the object cannot be revealed because the object
+ // is sensitive or unextractable, then the ulValueLen field in that
+ // triple is modified to hold the value CK_UNAVAILABLE_INFORMATION.
+ //
+ // [PKCS#11 v2.40, 4.2 Common attributes, table 10]
+ // 7 Cannot be revealed if object has its CKA_SENSITIVE attribute
+ // set to CK_TRUE or its CKA_EXTRACTABLE attribute set to CK_FALSE.
+ if ((checks & ck7) == ck7 && (isSensitive() || !isExtractable())) {
+ *pulValueLen = CK_UNAVAILABLE_INFORMATION;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+
+ // Retrieve the lower level attribute.
+ if (!osobject->attributeExists(type)) {
+ // Should be impossible.
+ ERROR_MSG("Internal error: attribute not present");
+ return CKR_GENERAL_ERROR;
+ }
+ OSAttribute attr = osobject->getAttribute(type);
+
+ // Get the actual attribute size.
+ CK_ULONG attrSize = size;
+ if (size == (CK_ULONG)-1)
+ {
+ // We don't have a fixed size attribute so we need to consult
+ // the lower level attribute for the exact size.
+
+ // Lower level attribute has to be variable sized.
+ if (attr.isByteStringAttribute())
+ {
+ if (isPrivate && attr.getByteStringValue().size() != 0)
+ {
+ ByteString value;
+ if (!token->decrypt(attr.getByteStringValue(),value))
+ {
+ ERROR_MSG("Internal error: failed to decrypt private attribute value");
+ return CKR_GENERAL_ERROR;
+ }
+ attrSize = value.size();
+ }
+ else
+ attrSize = attr.getByteStringValue().size();
+ }
+ else if (attr.isMechanismTypeSetAttribute())
+ {
+ attrSize = attr.getMechanismTypeSetValue().size() * sizeof(CK_MECHANISM_TYPE);
+ }
+ else if (attr.isAttributeMapAttribute())
+ {
+ attrSize = attr.getAttributeMapValue().size() * sizeof(CK_ATTRIBUTE);
+ }
+ else
+ {
+ // Should be impossible.
+ ERROR_MSG("Internal error: attribute has fixed size");
+ return CKR_GENERAL_ERROR;
+ }
+ }
+
+ // [PKCS#11 v2.40, C_GetAttributeValue]
+ // 3. Otherwise, if the pValue field has the value NULL_PTR, then the
+ // ulValueLen field is modified to hold the exact length of the
+ // specified attribute for the object.
+ if (pValue == NULL_PTR) {
+ // Return the size of the attribute.
+ *pulValueLen = attrSize;
+ return CKR_OK;
+ }
+
+ // [PKCS#11 v2.40, C_GetAttributeValue]
+ // 4. Otherwise, if the length specified in ulValueLen is large enough
+ // to hold the value of the specified attribute for the object, then
+ // that attribute is copied into the buffer located at pValue, and
+ // the ulValueLen field is modified to hold the exact length of the
+ // attribute.
+ if (*pulValueLen >= attrSize)
+ {
+ // Only copy when there is actually something to copy
+ CK_RV rv = CKR_OK;
+
+ if (attr.isUnsignedLongAttribute()) {
+ *(CK_ULONG_PTR)pValue = attr.getUnsignedLongValue();
+ }
+ else if (attr.isBooleanAttribute())
+ {
+ *(CK_BBOOL*)pValue = attr.getBooleanValue() ? CK_TRUE : CK_FALSE;
+ }
+ else if (attr.isByteStringAttribute())
+ {
+ if (isPrivate && attr.getByteStringValue().size() != 0)
+ {
+ ByteString value;
+ if (!token->decrypt(attr.getByteStringValue(),value))
+ {
+ ERROR_MSG("Internal error: failed to decrypt private attribute value");
+ return CKR_GENERAL_ERROR;
+ }
+ const unsigned char* attrPtr = value.const_byte_str();
+ memcpy(pValue,attrPtr,attrSize);
+ }
+ else if (attr.getByteStringValue().size() != 0)
+ {
+ const unsigned char* attrPtr = attr.getByteStringValue().const_byte_str();
+ memcpy(pValue,attrPtr,attrSize);
+ }
+ }
+ else if (attr.isMechanismTypeSetAttribute())
+ {
+ CK_MECHANISM_TYPE_PTR pTemplate = (CK_MECHANISM_TYPE_PTR) pValue;
+ size_t i = 0;
+
+ std::set<CK_MECHANISM_TYPE> set = attr.getMechanismTypeSetValue();
+ for (std::set<CK_MECHANISM_TYPE>::const_iterator it = set.begin(); it != set.end(); ++it)
+ pTemplate[++i] = *it;
+ }
+ else
+ {
+ // attr is already retrieved and verified to be an Attribute Map
+ rv = retrieveAttributeMap((CK_ATTRIBUTE_PTR)pValue, attr.getAttributeMapValue());
+ }
+ *pulValueLen = attrSize;
+ return rv;
+ }
+
+ // [PKCS#11 v2.40, C_GetAttributeValue]
+ // 5. Otherwise, the ulValueLen field is modified to hold the value CK_UNAVAILABLE_INFORMATION.
+ *pulValueLen = CK_UNAVAILABLE_INFORMATION;
+ return CKR_BUFFER_TOO_SMALL;
+}
+
+// Update the value if allowed
+CK_RV P11Attribute::update(Token* token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ if (osobject == NULL) {
+ ERROR_MSG("Internal error: osobject field contains NULL_PTR");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // [PKCS#11 v2.40, 4.1.1 Creating objects]
+ // 2. If the supplied template specifies an invalid value for a valid attribute, then the
+ // attempt should fail with the error code CKR_ATTRIBUTE_VALUE_INVALID.
+ // The valid values for Cryptoki attributes are described in the Cryptoki specification.
+
+ // Check for null pointers in values.
+ if (pValue == NULL_PTR && ulValueLen != 0) {
+ ERROR_MSG("The attribute is a NULL_PTR but has a non-zero length")
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // For fixed sized attributes check that the size matches.
+ if (size != ((CK_ULONG)-1) && size != ulValueLen) {
+ ERROR_MSG("The attribute size is different from the expected size")
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // [PKCS#11 v2.40, 4.1.1 Creating objects] OBJECT_OP_CREATE | OBJECT_OP_SET | OBJECT_OP_COPY
+ // 3. If the supplied template specifies a value for a read-only attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_READ_ONLY.
+ // Whether or not a given Cryptoki attribute is read-only is explicitly stated in the Cryptoki
+ // specification; however, a particular library and token may be even more restrictive than
+ // Cryptoki specifies. In other words, an attribute which Cryptoki says is not read-only may
+ // nonetheless be read-only under certain circumstances (i.e., in conjunction with some
+ // combinations of other attributes) for a particular library and token. Whether or not a
+ // given non-Cryptoki attribute is read-only is obviously outside the scope of Cryptoki.
+
+ // Attributes cannot be changed if CKA_MODIFIABLE is set to false
+ if (!isModifiable() && op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE) {
+ ERROR_MSG("An object is with CKA_MODIFIABLE set to false is not modifiable");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ // Attributes cannot be modified if CKA_TRUSTED is true on a certificate object.
+ if (isTrusted() && op != OBJECT_OP_GENERATE && op != OBJECT_OP_CREATE) {
+ if (osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_CERTIFICATE)
+ {
+ ERROR_MSG("A trusted certificate cannot be modified");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ // ck2 MUST not be specified when object is created with C_CreateObject.
+ if ((checks & ck2) == ck2)
+ {
+ if (OBJECT_OP_CREATE==op)
+ {
+ ERROR_MSG("Prohibited attribute was passed to object creation function");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ // ck4 MUST not be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
+ if ((checks & ck4) == ck4)
+ {
+ if (OBJECT_OP_GENERATE==op)
+ {
+ ERROR_MSG("Prohibited attribute was passed to key generation function");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ // ck6 MUST not be specified when object is unwrapped with C_UnwrapKey.
+ if ((checks & ck6) == ck6)
+ {
+ if (OBJECT_OP_UNWRAP==op)
+ {
+ ERROR_MSG("Prohibited attribute was passed to key unwrapping function");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ // ck8 May be modified after object is created with a C_SetAttributeValue call
+ // or in the process of copying an object with a C_CopyObject call.
+ // However, it is possible that a particular token may not permit modification of
+ // the attribute during the course of a C_CopyObject call.
+ if ((checks & ck8) == ck8)
+ {
+ if (OBJECT_OP_SET==op || OBJECT_OP_COPY==op)
+ {
+ return updateAttr(token, isPrivate, pValue, ulValueLen, op);
+ }
+ }
+
+ // ck17 Can be changed in the process of copying the object using C_CopyObject.
+ if ((checks & ck17) == ck17)
+ {
+ if (OBJECT_OP_COPY==op)
+ {
+ return updateAttr(token, isPrivate, pValue, ulValueLen, op);
+ }
+ }
+
+ // For attributes that have not been explicitly excluded from modification
+ // during create/derive/generate/unwrap, we allow them to be modified.
+ if (OBJECT_OP_CREATE==op || OBJECT_OP_DERIVE==op || OBJECT_OP_GENERATE==op || OBJECT_OP_UNWRAP==op)
+ {
+ return updateAttr(token, isPrivate, pValue, ulValueLen, op);
+ }
+
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_CLASS
+ *****************************************/
+
+// Set default value
+bool P11AttrClass::setDefault()
+{
+ OSAttribute attrClass((unsigned long)CKO_VENDOR_DEFINED);
+ return osobject->setAttribute(type, attrClass);
+}
+
+// Update the value if allowed
+CK_RV P11AttrClass::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if (osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != *(CK_ULONG*)pValue)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_KEY_TYPE
+ *****************************************/
+
+// Set default value
+bool P11AttrKeyType::setDefault()
+{
+ OSAttribute attr((unsigned long)CKK_VENDOR_DEFINED);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrKeyType::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if (osobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != *(CK_ULONG*)pValue)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_CERTIFICATE_TYPE
+ * footnote 1
+ * 1 MUST be specified when object is created with C_CreateObject.
+ *****************************************/
+
+// Set default value
+bool P11AttrCertificateType::setDefault()
+{
+ OSAttribute attr((unsigned long)CKC_VENDOR_DEFINED);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrCertificateType::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if (osobject->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_VENDOR_DEFINED) != *(CK_ULONG*)pValue)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_TOKEN
+ *****************************************/
+
+// Set default value
+bool P11AttrToken::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrToken::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_PRIVATE
+ *****************************************/
+
+// Set default value
+bool P11AttrPrivate::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrPrivate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_MODIFIABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrModifiable::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrModifiable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_LABEL
+ *****************************************/
+
+// Set default value
+bool P11AttrLabel::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_COPYABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrCopyable::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrCopyable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ if (osobject->getBooleanValue(CKA_COPYABLE, true) == false)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_DESTROYABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrDestroyable::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrDestroyable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_APPLICATION
+ *****************************************/
+
+// Set default value
+bool P11AttrApplication::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_OBJECT_ID
+ *****************************************/
+
+// Set default value
+bool P11AttrObjectID::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_CHECK_VALUE
+ *****************************************/
+
+// Set default value
+bool P11AttrCheckValue::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrCheckValue::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ ByteString plaintext((unsigned char*)pValue, ulValueLen);
+ ByteString value;
+
+ // Encrypt
+
+ if (isPrivate)
+ {
+ if (!token->encrypt(plaintext, value))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ value = plaintext;
+
+ // Attribute specific checks
+
+ if (value.size() < ulValueLen)
+ return CKR_GENERAL_ERROR;
+
+ // Store data
+ if (ulValueLen == 0)
+ {
+ osobject->setAttribute(type, value);
+ }
+ else
+ {
+ ByteString checkValue;
+ ByteString keybits;
+ if (isPrivate)
+ {
+ if (!token->decrypt(osobject->getByteStringValue(CKA_VALUE), keybits))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ keybits = osobject->getByteStringValue(CKA_VALUE);
+ }
+
+ SymmetricKey key;
+ AESKey aes;
+ DESKey des;
+ switch (osobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED))
+ {
+ case CKK_GENERIC_SECRET:
+ case CKK_MD5_HMAC:
+ case CKK_SHA_1_HMAC:
+ case CKK_SHA224_HMAC:
+ case CKK_SHA256_HMAC:
+ case CKK_SHA384_HMAC:
+ case CKK_SHA512_HMAC:
+ key.setKeyBits(keybits);
+ key.setBitLen(keybits.size() * 8);
+ checkValue = key.getKeyCheckValue();
+ break;
+ case CKK_AES:
+ aes.setKeyBits(keybits);
+ aes.setBitLen(keybits.size() * 8);
+ checkValue = aes.getKeyCheckValue();
+ break;
+ case CKK_DES:
+ case CKK_DES2:
+ case CKK_DES3:
+ des.setKeyBits(keybits);
+ des.setBitLen(keybits.size() * 7);
+ checkValue = des.getKeyCheckValue();
+ break;
+ case CKK_GOST28147:
+ // TODO: Encryption support for CKK_GOST28147
+ // We do not calculate the KCV
+ checkValue = plaintext;
+ break;
+ default:
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (plaintext != checkValue)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ osobject->setAttribute(type, value);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_PUBLIC_KEY_INFO
+ *****************************************/
+
+// Set default value
+bool P11AttrPublicKeyInfo::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_ID
+ *****************************************/
+
+// Set default value
+bool P11AttrID::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_VALUE
+ *****************************************/
+
+// Set default value
+bool P11AttrValue::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrValue::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ ByteString plaintext((unsigned char*)pValue, ulValueLen);
+ ByteString value;
+
+ // Encrypt
+
+ if (isPrivate)
+ {
+ if (!token->encrypt(plaintext, value))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ value = plaintext;
+
+ // Attribute specific checks
+
+ if (value.size() < ulValueLen)
+ return CKR_GENERAL_ERROR;
+
+ // Store data
+
+ osobject->setAttribute(type, value);
+
+ // Set the size during C_CreateObject and C_UnwrapKey.
+
+ if (op == OBJECT_OP_CREATE || op == OBJECT_OP_UNWRAP)
+ {
+ // Set the CKA_VALUE_LEN
+ if (osobject->attributeExists(CKA_VALUE_LEN))
+ {
+ OSAttribute bytes((unsigned long)plaintext.size());
+ osobject->setAttribute(CKA_VALUE_LEN, bytes);
+ }
+
+ // Set the CKA_VALUE_BITS
+ if (osobject->attributeExists(CKA_VALUE_BITS))
+ {
+ OSAttribute bits((unsigned long)plaintext.bits());
+ osobject->setAttribute(CKA_VALUE_BITS, bits);
+ }
+ }
+
+ // Calculate the CKA_CHECK_VALUE for certificates
+ if (osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_CERTIFICATE)
+ {
+ HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA1);
+ if (hash == NULL) return CKR_GENERAL_ERROR;
+
+ ByteString digest;
+ if (hash->hashInit() == false ||
+ hash->hashUpdate(plaintext) == false ||
+ hash->hashFinal(digest) == false)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ return CKR_GENERAL_ERROR;
+ }
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ // First three bytes of the SHA-1 hash
+ digest.resize(3);
+
+ if (isPrivate)
+ {
+ ByteString encrypted;
+ if (!token->encrypt(digest, encrypted))
+ return CKR_GENERAL_ERROR;
+ osobject->setAttribute(CKA_CHECK_VALUE, encrypted);
+ }
+ else
+ osobject->setAttribute(CKA_CHECK_VALUE, digest);
+ }
+
+ // Calculate the CKA_CHECK_VALUE for secret keys
+ if (op == OBJECT_OP_CREATE &&
+ osobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
+ {
+ SymmetricKey key;
+ AESKey aes;
+ DESKey des;
+ ByteString checkValue;
+ switch (osobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED))
+ {
+ case CKK_GENERIC_SECRET:
+ case CKK_MD5_HMAC:
+ case CKK_SHA_1_HMAC:
+ case CKK_SHA224_HMAC:
+ case CKK_SHA256_HMAC:
+ case CKK_SHA384_HMAC:
+ case CKK_SHA512_HMAC:
+ key.setKeyBits(plaintext);
+ key.setBitLen(plaintext.size() * 8);
+ checkValue = key.getKeyCheckValue();
+ break;
+ case CKK_AES:
+ aes.setKeyBits(plaintext);
+ aes.setBitLen(plaintext.size() * 8);
+ checkValue = aes.getKeyCheckValue();
+ break;
+ case CKK_DES:
+ case CKK_DES2:
+ case CKK_DES3:
+ des.setKeyBits(plaintext);
+ des.setBitLen(plaintext.size() * 7);
+ checkValue = des.getKeyCheckValue();
+ break;
+ case CKK_GOST28147:
+ // TODO: Encryption support for CKK_GOST28147
+ // We do not calculate the KCV
+ break;
+ default:
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (isPrivate)
+ {
+ ByteString encrypted;
+ if (!token->encrypt(checkValue, encrypted))
+ return CKR_GENERAL_ERROR;
+ osobject->setAttribute(CKA_CHECK_VALUE, encrypted);
+ }
+ else
+ osobject->setAttribute(CKA_CHECK_VALUE, checkValue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_SUBJECT
+ *****************************************/
+
+// Set default value
+bool P11AttrSubject::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_ISSUER
+ *****************************************/
+
+// Set default value
+bool P11AttrIssuer::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_TRUSTED
+ *****************************************/
+
+// Set default value
+bool P11AttrTrusted::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrTrusted::updateAttr(Token *token, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ if (!token->isSOLoggedIn())
+ {
+ ERROR_MSG("CKA_TRUSTED can only be set to true by the SO");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_CERTIFICATE_CATEGORY
+ *****************************************/
+
+// Set default value
+bool P11AttrCertificateCategory::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrCertificateCategory::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_START_DATE
+ *****************************************/
+
+// Set default value
+bool P11AttrStartDate::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrStartDate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_DATE) && ulValueLen !=0)
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, ByteString((unsigned char*)pValue, ulValueLen));
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_END_DATE
+ *****************************************/
+
+// Set default value
+bool P11AttrEndDate::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrEndDate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_DATE) && ulValueLen !=0)
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, ByteString((unsigned char*)pValue, ulValueLen));
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_SERIAL_NUMBER
+ *****************************************/
+
+// Set default value
+bool P11AttrSerialNumber::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_URL
+ *****************************************/
+
+// Set default value
+bool P11AttrURL::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_HASH_OF_SUBJECT_PUBLIC_KEY
+ *****************************************/
+
+// Set default value
+bool P11AttrHashOfSubjectPublicKey::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_HASH_OF_ISSUER_PUBLIC_KEY
+ *****************************************/
+
+// Set default value
+bool P11AttrHashOfIssuerPublicKey::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_JAVA_MIDP_SECURITY_DOMAIN
+ *****************************************/
+
+// Set default value
+bool P11AttrJavaMidpSecurityDomain::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrJavaMidpSecurityDomain::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_NAME_HASH_ALGORITHM
+ *****************************************/
+
+// Set default value
+bool P11AttrNameHashAlgorithm::setDefault()
+{
+ OSAttribute attr((unsigned long)CKM_SHA_1);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrNameHashAlgorithm::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_DERIVE
+ *****************************************/
+
+// Set default value
+bool P11AttrDerive::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrDerive::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_ENCRYPT
+ *****************************************/
+
+// Set default value
+bool P11AttrEncrypt::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrEncrypt::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_VERIFY
+ *****************************************/
+
+// Set default value
+bool P11AttrVerify::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrVerify::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_VERIFY_RECOVER
+ *****************************************/
+
+// Set default value
+bool P11AttrVerifyRecover::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrVerifyRecover::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_WRAP
+ *****************************************/
+
+// Set default value
+bool P11AttrWrap::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrWrap::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_DECRYPT
+ *****************************************/
+
+// Set default value
+bool P11AttrDecrypt::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrDecrypt::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_SIGN
+ *****************************************/
+
+// Set default value
+bool P11AttrSign::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrSign::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_SIGN_RECOVER
+ *****************************************/
+
+// Set default value
+bool P11AttrSignRecover::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrSignRecover::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_UNWRAP
+ *****************************************/
+
+// Set default value
+bool P11AttrUnwrap::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrUnwrap::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_LOCAL
+ *****************************************/
+
+// Set default value
+bool P11AttrLocal::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrLocal::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR /*pValue*/, CK_ULONG /*ulValueLen*/, int /*op*/)
+{
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_KEY_GEN_MECHANISM
+ *****************************************/
+
+// Set default value
+bool P11AttrKeyGenMechanism::setDefault()
+{
+ OSAttribute attr((unsigned long)CK_UNAVAILABLE_INFORMATION);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrKeyGenMechanism::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR /*pValue*/, CK_ULONG /*ulValueLen*/, int /*op*/)
+{
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_ALWAYS_SENSITIVE
+ *****************************************/
+
+// Set default value
+bool P11AttrAlwaysSensitive::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrAlwaysSensitive::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR /*pValue*/, CK_ULONG /*ulValueLen*/, int /*op*/)
+{
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_NEVER_EXTRACTABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrNeverExtractable::setDefault()
+{
+ OSAttribute attr(true);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrNeverExtractable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR /*pValue*/, CK_ULONG /*ulValueLen*/, int /*op*/)
+{
+ return CKR_ATTRIBUTE_READ_ONLY;
+}
+
+/*****************************************
+ * CKA_SENSITIVE
+ *****************************************/
+
+// Set default value
+bool P11AttrSensitive::setDefault()
+{
+ // We default to false because we want to handle the secret keys in a correct way
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrSensitive::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
+ {
+ if (osobject->getBooleanValue(CKA_SENSITIVE, false))
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ osobject->setAttribute(CKA_ALWAYS_SENSITIVE, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+
+ // This is so that generated keys get the correct value
+ if (op == OBJECT_OP_GENERATE || op == OBJECT_OP_DERIVE)
+ {
+ osobject->setAttribute(CKA_ALWAYS_SENSITIVE, attrTrue);
+ }
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_EXTRACTABLE
+ *****************************************/
+
+// Set default value
+bool P11AttrExtractable::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrExtractable::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
+ {
+ if (osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ osobject->setAttribute(CKA_NEVER_EXTRACTABLE, attrFalse);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_WRAP_WITH_TRUSTED
+ *****************************************/
+
+// Set default value
+bool P11AttrWrapWithTrusted::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrWrapWithTrusted::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (op == OBJECT_OP_SET || op == OBJECT_OP_COPY)
+ {
+ if (osobject->getBooleanValue(CKA_WRAP_WITH_TRUSTED, false))
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_ALWAYS_AUTHENTICATE
+ *****************************************/
+
+// Set default value
+bool P11AttrAlwaysAuthenticate::setDefault()
+{
+ OSAttribute attr(false);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrAlwaysAuthenticate::updateAttr(Token* /*token*/, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ OSAttribute attrTrue(true);
+ OSAttribute attrFalse(false);
+
+ // Attribute specific checks
+
+ if (ulValueLen !=sizeof(CK_BBOOL))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ if (*(CK_BBOOL*)pValue == CK_FALSE)
+ {
+ osobject->setAttribute(type, attrFalse);
+ }
+ else
+ {
+ if (!isPrivate)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ osobject->setAttribute(type, attrTrue);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_MODULUS
+ *****************************************/
+
+// Set default value
+bool P11AttrModulus::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrModulus::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ ByteString plaintext((unsigned char*)pValue, ulValueLen);
+ ByteString value;
+
+ // Encrypt
+
+ if (isPrivate)
+ {
+ if (!token->encrypt(plaintext, value))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ value = plaintext;
+
+ // Attribute specific checks
+
+ if (value.size() < ulValueLen)
+ return CKR_GENERAL_ERROR;
+
+ // Store data
+
+ osobject->setAttribute(type, value);
+
+ // Set the CKA_MODULUS_BITS during C_CreateObject
+
+ if (op == OBJECT_OP_CREATE && osobject->attributeExists(CKA_MODULUS_BITS))
+ {
+ OSAttribute bits((unsigned long)plaintext.bits());
+ osobject->setAttribute(CKA_MODULUS_BITS, bits);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_PUBLIC_EXPONENT
+ *****************************************/
+
+// Set default value
+bool P11AttrPublicExponent::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_PRIVATE_EXPONENT
+ *****************************************/
+
+// Set default value
+bool P11AttrPrivateExponent::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_PRIME_1
+ *****************************************/
+
+// Set default value
+bool P11AttrPrime1::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_PRIME_2
+ *****************************************/
+
+// Set default value
+bool P11AttrPrime2::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_EXPONENT_1
+ *****************************************/
+
+// Set default value
+bool P11AttrExponent1::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_EXPONENT_2
+ *****************************************/
+
+// Set default value
+bool P11AttrExponent2::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_COEFFICIENT
+ *****************************************/
+
+// Set default value
+bool P11AttrCoefficient::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_MODULUS_BITS
+ *****************************************/
+
+// Set default value
+bool P11AttrModulusBits::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrModulusBits::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen !=sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_PRIME
+ *****************************************/
+
+// Set default value
+bool P11AttrPrime::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrPrime::updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ ByteString plaintext((unsigned char*)pValue, ulValueLen);
+ ByteString value;
+
+ // Encrypt
+
+ if (isPrivate)
+ {
+ if (!token->encrypt(plaintext, value))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ value = plaintext;
+
+ // Attribute specific checks
+
+ if (value.size() < ulValueLen)
+ return CKR_GENERAL_ERROR;
+
+ // Store data
+
+ osobject->setAttribute(type, value);
+
+ // Set the CKA_PRIME_BITS during C_CreateObject
+
+ if (op == OBJECT_OP_CREATE && osobject->attributeExists(CKA_PRIME_BITS))
+ {
+ OSAttribute bits((unsigned long)plaintext.bits());
+ osobject->setAttribute(CKA_PRIME_BITS, bits);
+ }
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_SUBPRIME
+ *****************************************/
+
+// Set default value
+bool P11AttrSubPrime::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_BASE
+ *****************************************/
+
+// Set default value
+bool P11AttrBase::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_PRIME_BITS
+ *****************************************/
+
+// Set default value
+bool P11AttrPrimeBits::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrPrimeBits::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen != sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_VALUE_BITS
+ *****************************************/
+
+// Set default value
+bool P11AttrValueBits::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrValueBits::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen != sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_EC_PARAMS
+ *****************************************/
+
+// Set default value
+bool P11AttrEcParams::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_EC_POINT
+ *****************************************/
+
+// Set default value
+bool P11AttrEcPoint::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_GOSTR3410_PARAMS
+ *****************************************/
+
+// Set default value
+bool P11AttrGostR3410Params::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_GOSTR3411_PARAMS
+ *****************************************/
+
+// Set default value
+bool P11AttrGostR3411Params::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_GOST28147_PARAMS
+ *****************************************/
+
+// Set default value
+bool P11AttrGost28147Params::setDefault()
+{
+ OSAttribute attr(ByteString(""));
+ return osobject->setAttribute(type, attr);
+}
+
+/*****************************************
+ * CKA_VALUE_LEN
+ *****************************************/
+
+// Set default value
+bool P11AttrValueLen::setDefault()
+{
+ OSAttribute attr((unsigned long)0);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value if allowed
+CK_RV P11AttrValueLen::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op)
+{
+ // Attribute specific checks
+
+ if (op != OBJECT_OP_GENERATE && op != OBJECT_OP_DERIVE)
+ {
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ if (ulValueLen != sizeof(CK_ULONG))
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Store data
+
+ osobject->setAttribute(type, *(CK_ULONG*)pValue);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_WRAP_TEMPLATE
+ *****************************************/
+
+// Set default value
+bool P11AttrWrapTemplate::setDefault()
+{
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> empty;
+ OSAttribute attr(empty);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value
+CK_RV P11AttrWrapTemplate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+ if ((ulValueLen % sizeof(CK_ATTRIBUTE)) != 0)
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Fill the template vector with elements
+ CK_ATTRIBUTE_PTR attr = (CK_ATTRIBUTE_PTR) pValue;
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> data;
+ for (size_t i = 0; i < ulValueLen / sizeof(CK_ATTRIBUTE); ++i, ++attr)
+ // Specialization for known attributes
+ switch (attr->type)
+ {
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_MODIFIABLE:
+ case CKA_COPYABLE:
+ case CKA_TRUSTED:
+ case CKA_ENCRYPT:
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ case CKA_UNWRAP:
+ case CKA_DERIVE:
+ case CKA_LOCAL:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_SENSITIVE:
+ case CKA_NEVER_EXTRACTABLE:
+ case CKA_EXTRACTABLE:
+ case CKA_WRAP_WITH_TRUSTED:
+ case CKA_SECONDARY_AUTH:
+ case CKA_ALWAYS_AUTHENTICATE:
+ {
+ // CK_BBOOL
+ if (attr->ulValueLen != sizeof(CK_BBOOL))
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ bool elem = (*(CK_BBOOL*)attr->pValue != CK_FALSE);
+ data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
+ }
+ break;
+
+ case CKA_CLASS:
+ case CKA_KEY_TYPE:
+ case CKA_CERTIFICATE_TYPE:
+ case CKA_CERTIFICATE_CATEGORY:
+ case CKA_JAVA_MIDP_SECURITY_DOMAIN:
+ case CKA_NAME_HASH_ALGORITHM:
+ case CKA_KEY_GEN_MECHANISM:
+ case CKA_MODULUS_BITS:
+ case CKA_PRIME_BITS:
+ case CKA_SUBPRIME_BITS:
+ case CKA_VALUE_BITS:
+ case CKA_VALUE_LEN:
+ case CKA_AUTH_PIN_FLAGS:
+ {
+ // CK_ULONG
+ if (attr->ulValueLen != sizeof(CK_ULONG))
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ unsigned long elem = *(CK_ULONG*)attr->pValue;
+ data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
+ }
+ break;
+
+ case CKA_WRAP_TEMPLATE:
+ case CKA_UNWRAP_TEMPLATE:
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ default:
+ {
+ // CK_BYTE
+ ByteString elem = ByteString((unsigned char*)attr->pValue, attr->ulValueLen);
+ data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
+ }
+ }
+
+ // Store data
+ osobject->setAttribute(type, data);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_UNWRAP_TEMPLATE
+ *****************************************/
+
+// Set default value
+bool P11AttrUnwrapTemplate::setDefault()
+{
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> empty;
+ OSAttribute attr(empty);
+ return osobject->setAttribute(type, attr);
+}
+
+// Update the value
+CK_RV P11AttrUnwrapTemplate::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ // Attribute specific checks
+ if ((ulValueLen % sizeof(CK_ATTRIBUTE)) != 0)
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Fill the template vector with elements
+ CK_ATTRIBUTE_PTR attr = (CK_ATTRIBUTE_PTR) pValue;
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> data;
+ for (size_t i = 0; i < ulValueLen / sizeof(CK_ATTRIBUTE); ++i, ++attr)
+ // Specialization for known attributes
+ switch (attr->type)
+ {
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_MODIFIABLE:
+ case CKA_COPYABLE:
+ case CKA_TRUSTED:
+ case CKA_ENCRYPT:
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ case CKA_UNWRAP:
+ case CKA_DERIVE:
+ case CKA_LOCAL:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_SENSITIVE:
+ case CKA_NEVER_EXTRACTABLE:
+ case CKA_EXTRACTABLE:
+ case CKA_WRAP_WITH_TRUSTED:
+ case CKA_SECONDARY_AUTH:
+ case CKA_ALWAYS_AUTHENTICATE:
+ {
+ // CK_BBOOL
+ if (attr->ulValueLen != sizeof(CK_BBOOL))
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ bool elem = (*(CK_BBOOL*)attr->pValue != CK_FALSE);
+ data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
+ }
+ break;
+
+ case CKA_CLASS:
+ case CKA_KEY_TYPE:
+ case CKA_CERTIFICATE_TYPE:
+ case CKA_CERTIFICATE_CATEGORY:
+ case CKA_JAVA_MIDP_SECURITY_DOMAIN:
+ case CKA_NAME_HASH_ALGORITHM:
+ case CKA_KEY_GEN_MECHANISM:
+ case CKA_MODULUS_BITS:
+ case CKA_PRIME_BITS:
+ case CKA_SUBPRIME_BITS:
+ case CKA_VALUE_BITS:
+ case CKA_VALUE_LEN:
+ case CKA_AUTH_PIN_FLAGS:
+ {
+ // CK_ULONG
+ if (attr->ulValueLen != sizeof(CK_ULONG))
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ unsigned long elem = *(CK_ULONG*)attr->pValue;
+ data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
+ }
+ break;
+
+ case CKA_WRAP_TEMPLATE:
+ case CKA_UNWRAP_TEMPLATE:
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+
+ default:
+ {
+ // CK_BYTE
+ ByteString elem = ByteString((unsigned char*)attr->pValue, attr->ulValueLen);
+ data.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attr->type, elem));
+ }
+ }
+
+ // Store data
+ osobject->setAttribute(type, data);
+
+ return CKR_OK;
+}
+
+/*****************************************
+ * CKA_ALLOWED_MECHANISMS
+ *****************************************/
+
+// Set default value
+bool P11AttrAllowedMechanisms::setDefault()
+{
+ std::set<CK_MECHANISM_TYPE> emptyMap;
+ return osobject->setAttribute(type, OSAttribute(emptyMap));
+}
+
+// Update the value if allowed
+CK_RV P11AttrAllowedMechanisms::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int /*op*/)
+{
+ if (ulValueLen == 0 || (ulValueLen % sizeof(CK_MECHANISM_TYPE)) != 0)
+ {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ CK_MECHANISM_TYPE_PTR mechType = (CK_MECHANISM_TYPE_PTR) pValue;
+
+ // Fill the set with values
+ std::set<CK_MECHANISM_TYPE> data;
+ for (size_t i = 0; i < ulValueLen / sizeof(CK_MECHANISM_TYPE); ++i, ++mechType)
+ {
+ data.insert(*mechType);
+ }
+
+ // Store data
+ osobject->setAttribute(type, OSAttribute(data));
+ return CKR_OK;
+}
diff --git a/SoftHSMv2/src/lib/P11Attributes.h b/SoftHSMv2/src/lib/P11Attributes.h
new file mode 100644
index 0000000..3cddf30
--- /dev/null
+++ b/SoftHSMv2/src/lib/P11Attributes.h
@@ -0,0 +1,1264 @@
+/*
+ * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ P11Attributes.h
+
+ This file contains classes for controlling attributes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_P11ATTRIBUTES_H
+#define _SOFTHSM_V2_P11ATTRIBUTES_H
+
+#include "cryptoki.h"
+#include "OSObject.h"
+#include "Token.h"
+
+// The operation types
+#define OBJECT_OP_NONE 0x0
+#define OBJECT_OP_COPY 0x1
+#define OBJECT_OP_CREATE 0x2
+#define OBJECT_OP_DERIVE 0x3
+#define OBJECT_OP_GENERATE 0x4
+#define OBJECT_OP_SET 0x5
+#define OBJECT_OP_UNWRAP 0x6
+
+class P11Attribute
+{
+public:
+ // Destructor
+ virtual ~P11Attribute();
+
+ // Initialize the attribute
+ bool init();
+
+ // Return the attribute type
+ CK_ATTRIBUTE_TYPE getType();
+
+ // Return the attribute checks
+ CK_ULONG getChecks();
+
+ // Retrieve the value if allowed
+ CK_RV retrieve(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG_PTR pulValueLen);
+
+ // Update the value if allowed
+ CK_RV update(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+
+ // Checks are determined by footnotes from table 10 under section 4.2 in the PKCS#11 v2.40 spec.
+ // Table 10 contains common footnotes for object attribute tables that determine the checks to perform on attributes.
+ // There are also checks not in table 10 that have been added here to allow enforcing additional contraints.
+ enum {
+ ck1=1, // 1 MUST be specified when object is created with C_CreateObject.
+ ck2=2, // 2 MUST not be specified when object is created with C_CreateObject.
+ ck3=4, // 3 MUST be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
+ ck4=8, // 4 MUST not be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
+ ck5=0x10, // 5 MUST be specified when object is unwrapped with C_UnwrapKey.
+ ck6=0x20, // 6 MUST not be specified when object is unwrapped with C_UnwrapKey.
+ ck7=0x40, // 7 Cannot be revealed if object has its CKA_SENSITIVE attribute set to CK_TRUE or
+ // its CKA_EXTRACTABLE attribute set to CK_FALSE.
+ ck8=0x80, // 8 May be modified after object is created with a C_SetAttributeValue call,
+ // or in the process of copying object with a C_CopyObject call.
+ // However, it is possible that a particular token may not permit modification of
+ // the attribute during the course of a C_CopyObject call.
+ ck9=0x100, // 9 Default value is token-specific, and may depend on the values of other attributes.
+ ck10=0x200, // 10 Can only be set to CK_TRUE by the SO user.
+ ck11=0x400, // 11 Attribute cannot be changed once set to CK_TRUE. It becomes a read only attribute.
+ ck12=0x800, // 12 Attribute cannot be changed once set to CK_FALSE. It becomes a read only attribute.
+ ck13=0x1000, // Intentionally not defined
+ ck14=0x2000, // 14 MUST be non-empty if CKA_URL is empty. (CKA_VALUE)
+ ck15=0x4000, // 15 MUST be non-empty if CKA_VALUE is empty. (CKA_URL)
+ ck16=0x8000, // 16 Can only be empty if CKA_URL is empty.
+ ck17=0x10000, // 17 Can be changed in the process of copying the object using C_CopyObject.
+ ck18=0x20000,
+ ck19=0x40000,
+ ck20=0x80000,
+ ck21=0x100000,
+ ck22=0x200000,
+ ck23=0x400000,
+ ck24=0x800000
+ };
+protected:
+ // Constructor
+ P11Attribute(OSObject* inobject);
+
+ // The object
+ OSObject* osobject;
+
+ // The attribute type
+ CK_ATTRIBUTE_TYPE type;
+
+ // The checks to perform when the attribute is accessed.
+ CK_ULONG checks;
+
+ // The attribute fixed size contains (CK_ULONG)-1 when size is variable.
+ CK_ULONG size;
+
+ // Set the default value of the attribute
+ virtual bool setDefault() = 0;
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+
+ // Helper functions
+ bool isModifiable();
+ bool isSensitive();
+ bool isExtractable();
+ bool isTrusted();
+};
+
+/*****************************************
+ * CKA_CLASS
+ *****************************************/
+
+class P11AttrClass : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrClass(OSObject* inobject) : P11Attribute(inobject) { type = CKA_CLASS; size = sizeof(CK_OBJECT_CLASS); checks = ck1; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_KEY_TYPE
+ *****************************************/
+
+class P11AttrKeyType : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrKeyType(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_KEY_TYPE; size = sizeof(CK_KEY_TYPE); checks = ck1|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_CERTIFICATE_TYPE
+ *****************************************/
+
+class P11AttrCertificateType : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCertificateType(OSObject* inobject) : P11Attribute(inobject) { type = CKA_CERTIFICATE_TYPE; size = sizeof(CK_CERTIFICATE_TYPE); checks = ck1; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_TOKEN
+ *****************************************/
+
+class P11AttrToken : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrToken(OSObject* inobject) : P11Attribute(inobject) { type = CKA_TOKEN; size = sizeof(CK_BBOOL); checks = ck17; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_PRIVATE
+ *****************************************/
+
+class P11AttrPrivate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrivate(OSObject* inobject) : P11Attribute(inobject) { type = CKA_PRIVATE; size = sizeof(CK_BBOOL); checks = ck17; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_MODIFIABLE
+ *****************************************/
+
+class P11AttrModifiable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrModifiable(OSObject* inobject) : P11Attribute(inobject) { type = CKA_MODIFIABLE; size = sizeof(CK_BBOOL); checks = ck17; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_LABEL
+ *****************************************/
+
+class P11AttrLabel : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrLabel(OSObject* inobject) : P11Attribute(inobject) { type = CKA_LABEL; checks = ck8; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_COPYABLE
+ *****************************************/
+
+class P11AttrCopyable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCopyable(OSObject* inobject) : P11Attribute(inobject) { type = CKA_COPYABLE; size = sizeof(CK_BBOOL); checks = ck12; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_DESTROYABLE
+ *****************************************/
+
+class P11AttrDestroyable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrDestroyable(OSObject* inobject) : P11Attribute(inobject) { type = CKA_DESTROYABLE; size = sizeof(CK_BBOOL); checks = ck17; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_APPLICATION
+ *****************************************/
+
+class P11AttrApplication : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrApplication(OSObject* inobject) : P11Attribute(inobject) { type = CKA_APPLICATION; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_OBJECT_ID
+ *****************************************/
+
+class P11AttrObjectID : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrObjectID(OSObject* inobject) : P11Attribute(inobject) { type = CKA_OBJECT_ID; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_CHECK_VALUE
+ *****************************************/
+
+class P11AttrCheckValue : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCheckValue(OSObject* inobject, CK_ULONG inchecks) : P11Attribute(inobject) { type = CKA_CHECK_VALUE; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_PUBLIC_KEY_INFO
+ *****************************************/
+
+class P11AttrPublicKeyInfo : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPublicKeyInfo(OSObject* inobject, CK_ULONG inchecks) : P11Attribute(inobject) { type = CKA_OBJECT_ID; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_ID
+ *****************************************/
+
+class P11AttrID : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrID(OSObject* inobject) : P11Attribute(inobject) { type = CKA_ID; checks = ck8; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_VALUE
+ *****************************************/
+
+class P11AttrValue : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrValue(OSObject* inobject, CK_ULONG inchecks) : P11Attribute(inobject) { type = CKA_VALUE; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SUBJECT
+ *****************************************/
+
+class P11AttrSubject : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSubject(OSObject* inobject, CK_ULONG inchecks) : P11Attribute(inobject) { type = CKA_SUBJECT; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_ISSUER
+ *****************************************/
+
+class P11AttrIssuer : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrIssuer(OSObject* inobject) : P11Attribute(inobject) { type = CKA_ISSUER; checks = ck8; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_TRUSTED
+ *****************************************/
+
+class P11AttrTrusted : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrTrusted(OSObject* inobject) : P11Attribute(inobject) { type = CKA_TRUSTED; size = sizeof(CK_BBOOL); checks = ck10; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_CERTIFICATE_CATEGORY
+ *****************************************/
+
+class P11AttrCertificateCategory : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCertificateCategory(OSObject* inobject) : P11Attribute(inobject) { type = CKA_CERTIFICATE_CATEGORY; size = sizeof(CK_ULONG); checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_START_DATE
+ *****************************************/
+
+class P11AttrStartDate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrStartDate(OSObject* inobject, CK_ULONG inchecks) : P11Attribute(inobject) { type = CKA_START_DATE; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_END_DATE
+ *****************************************/
+
+class P11AttrEndDate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrEndDate(OSObject* inobject, CK_ULONG inchecks) : P11Attribute(inobject) { type = CKA_END_DATE; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SERIAL_NUMBER
+ *****************************************/
+
+class P11AttrSerialNumber : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSerialNumber(OSObject* inobject) : P11Attribute(inobject) { type = CKA_SERIAL_NUMBER; checks = ck8; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_URL
+ *****************************************/
+
+class P11AttrURL : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrURL(OSObject* inobject) : P11Attribute(inobject) { type = CKA_URL; checks = ck15; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_HASH_OF_SUBJECT_PUBLIC_KEY
+ *****************************************/
+
+class P11AttrHashOfSubjectPublicKey : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrHashOfSubjectPublicKey(OSObject* inobject) : P11Attribute(inobject) { type = CKA_HASH_OF_SUBJECT_PUBLIC_KEY; checks = ck16; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_HASH_OF_ISSUER_PUBLIC_KEY
+ *****************************************/
+
+class P11AttrHashOfIssuerPublicKey : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrHashOfIssuerPublicKey(OSObject* inobject) : P11Attribute(inobject) { type = CKA_HASH_OF_ISSUER_PUBLIC_KEY; checks = ck16; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_JAVA_MIDP_SECURITY_DOMAIN
+ *****************************************/
+
+class P11AttrJavaMidpSecurityDomain : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrJavaMidpSecurityDomain(OSObject* inobject) : P11Attribute(inobject) { type = CKA_JAVA_MIDP_SECURITY_DOMAIN; size = sizeof(CK_ULONG); checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_NAME_HASH_ALGORITHM
+ *****************************************/
+
+class P11AttrNameHashAlgorithm : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrNameHashAlgorithm(OSObject* inobject) : P11Attribute(inobject) { type = CKA_NAME_HASH_ALGORITHM; size = sizeof(CK_MECHANISM_TYPE); checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_DERIVE
+ *****************************************/
+
+class P11AttrDerive : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrDerive(OSObject* inobject) : P11Attribute(inobject) { type = CKA_DERIVE; size = sizeof(CK_BBOOL); checks = ck8;}
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_ENCRYPT
+ *****************************************/
+
+class P11AttrEncrypt : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrEncrypt(OSObject* inobject) : P11Attribute(inobject) { type = CKA_ENCRYPT; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_VERIFY
+ *****************************************/
+
+class P11AttrVerify : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrVerify(OSObject* inobject) : P11Attribute(inobject) { type = CKA_VERIFY; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_VERIFY_RECOVER
+ *****************************************/
+
+class P11AttrVerifyRecover : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrVerifyRecover(OSObject* inobject) : P11Attribute(inobject) { type = CKA_VERIFY_RECOVER; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_WRAP
+ *****************************************/
+
+class P11AttrWrap : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrWrap(OSObject* inobject) : P11Attribute(inobject) { type = CKA_WRAP; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_DECRYPT
+ *****************************************/
+
+class P11AttrDecrypt : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrDecrypt(OSObject* inobject) : P11Attribute(inobject) { type = CKA_DECRYPT; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SIGN
+ *****************************************/
+
+class P11AttrSign : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSign(OSObject* inobject) : P11Attribute(inobject) { type = CKA_SIGN; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SIGN_RECOVER
+ *****************************************/
+
+class P11AttrSignRecover : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSignRecover(OSObject* inobject) : P11Attribute(inobject) { type = CKA_SIGN_RECOVER; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_UNWRAP
+ *****************************************/
+
+class P11AttrUnwrap : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrUnwrap(OSObject* inobject) : P11Attribute(inobject) { type = CKA_UNWRAP; size = sizeof(CK_BBOOL); checks = ck8|ck9; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_LOCAL
+ *****************************************/
+
+class P11AttrLocal : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrLocal(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_LOCAL; size = sizeof(CK_BBOOL); checks = ck2|ck4|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_KEY_GEN_MECHANISM
+ *****************************************/
+
+class P11AttrKeyGenMechanism : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrKeyGenMechanism(OSObject* inobject) : P11Attribute(inobject) { type = CKA_KEY_GEN_MECHANISM; size = sizeof(CK_MECHANISM_TYPE); checks = ck2|ck4|ck6; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_ALWAYS_SENSITIVE
+ *****************************************/
+
+class P11AttrAlwaysSensitive : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrAlwaysSensitive(OSObject* inobject) : P11Attribute(inobject) { type = CKA_ALWAYS_SENSITIVE; size = sizeof(CK_BBOOL); checks = ck2|ck4|ck6; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_NEVER_EXTRACTABLE
+ *****************************************/
+
+class P11AttrNeverExtractable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrNeverExtractable(OSObject* inobject) : P11Attribute(inobject) { type = CKA_NEVER_EXTRACTABLE; size = sizeof(CK_BBOOL); checks = ck2|ck4|ck6; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SENSITIVE
+ *****************************************/
+
+class P11AttrSensitive : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSensitive(OSObject* inobject) : P11Attribute(inobject) { type = CKA_SENSITIVE; size = sizeof(CK_BBOOL); checks = ck8|ck9|ck11; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_EXTRACTABLE
+ *****************************************/
+
+class P11AttrExtractable : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrExtractable(OSObject* inobject) : P11Attribute(inobject) { type = CKA_EXTRACTABLE; size = sizeof(CK_BBOOL); checks = ck8|ck9|ck12; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_WRAP_WITH_TRUSTED
+ *****************************************/
+
+class P11AttrWrapWithTrusted : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrWrapWithTrusted(OSObject* inobject) : P11Attribute(inobject) { type = CKA_WRAP_WITH_TRUSTED; size = sizeof(CK_BBOOL); checks = ck11; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_ALWAYS_AUTHENTICATE
+ *****************************************/
+
+class P11AttrAlwaysAuthenticate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrAlwaysAuthenticate(OSObject* inobject) : P11Attribute(inobject) { type = CKA_ALWAYS_AUTHENTICATE; size = sizeof(CK_BBOOL); checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_MODULUS
+ *****************************************/
+
+class P11AttrModulus : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrModulus(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_MODULUS; checks = ck1|ck4|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_PUBLIC_EXPONENT
+ *****************************************/
+
+class P11AttrPublicExponent : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPublicExponent(OSObject* inobject, CK_ULONG inchecks) : P11Attribute(inobject) { type = CKA_PUBLIC_EXPONENT; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_PRIVATE_EXPONENT
+ *****************************************/
+
+class P11AttrPrivateExponent : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrivateExponent(OSObject* inobject) : P11Attribute(inobject) { type = CKA_PRIVATE_EXPONENT; checks = ck1|ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_PRIME_1
+ *****************************************/
+
+class P11AttrPrime1 : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrime1(OSObject* inobject) : P11Attribute(inobject) { type = CKA_PRIME_1; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_PRIME_2
+ *****************************************/
+
+class P11AttrPrime2 : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrime2(OSObject* inobject) : P11Attribute(inobject) { type = CKA_PRIME_2; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_EXPONENT_1
+ *****************************************/
+
+class P11AttrExponent1 : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrExponent1(OSObject* inobject) : P11Attribute(inobject) { type = CKA_EXPONENT_1; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_EXPONENT_2
+ *****************************************/
+
+class P11AttrExponent2 : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrExponent2(OSObject* inobject) : P11Attribute(inobject) { type = CKA_EXPONENT_2; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_COEFFICIENT
+ *****************************************/
+
+class P11AttrCoefficient : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrCoefficient(OSObject* inobject) : P11Attribute(inobject) { type = CKA_COEFFICIENT; checks = ck4|ck6|ck7; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_MODULUS_BITS
+ *****************************************/
+
+class P11AttrModulusBits : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrModulusBits(OSObject* inobject) : P11Attribute(inobject) { type = CKA_MODULUS_BITS; size = sizeof(CK_ULONG); checks = ck2|ck3;}
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_PRIME
+ *****************************************/
+
+class P11AttrPrime : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrime(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_PRIME; checks = ck1|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_SUBPRIME
+ *****************************************/
+
+class P11AttrSubPrime : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrSubPrime(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_SUBPRIME; checks = ck1|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_BASE
+ *****************************************/
+
+class P11AttrBase : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrBase(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_BASE; checks = ck1|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_PRIME_BITS
+ *****************************************/
+
+class P11AttrPrimeBits : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrPrimeBits(OSObject* inobject) : P11Attribute(inobject) { type = CKA_PRIME_BITS; size = sizeof(CK_ULONG); checks = ck2|ck3;}
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_VALUE_BITS
+ *****************************************/
+
+class P11AttrValueBits : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrValueBits(OSObject* inobject) : P11Attribute(inobject) { type = CKA_VALUE_BITS; size = sizeof(CK_ULONG); checks = ck2|ck6;}
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_EC_PARAMS
+ *****************************************/
+
+class P11AttrEcParams : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrEcParams(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_EC_PARAMS; checks = ck1|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_EC_POINT
+ *****************************************/
+
+class P11AttrEcPoint : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrEcPoint(OSObject* inobject) : P11Attribute(inobject) { type = CKA_EC_POINT; checks = ck1|ck4; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_GOSTR3410_PARAMS
+ *****************************************/
+
+class P11AttrGostR3410Params : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrGostR3410Params(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_GOSTR3410_PARAMS; checks = ck1|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_GOSTR3411_PARAMS
+ *****************************************/
+
+class P11AttrGostR3411Params : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrGostR3411Params(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_GOSTR3411_PARAMS; checks = ck1|ck8|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_GOST28147_PARAMS
+ *****************************************/
+
+class P11AttrGost28147Params : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrGost28147Params(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_GOST28147_PARAMS; checks = inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+};
+
+/*****************************************
+ * CKA_VALUE_LEN
+ *****************************************/
+
+class P11AttrValueLen : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrValueLen(OSObject* inobject, CK_ULONG inchecks = 0) : P11Attribute(inobject) { type = CKA_VALUE_LEN; size = sizeof(CK_ULONG); checks = ck2|ck3|inchecks; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_WRAP_TEMPLATE
+ *****************************************/
+
+class P11AttrWrapTemplate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrWrapTemplate(OSObject* inobject) : P11Attribute(inobject) { type = CKA_WRAP_TEMPLATE; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_UNWRAP_TEMPLATE
+ *****************************************/
+
+class P11AttrUnwrapTemplate : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrUnwrapTemplate(OSObject* inobject) : P11Attribute(inobject) { type = CKA_UNWRAP_TEMPLATE; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+/*****************************************
+ * CKA_ALLOWED_MECHANISMS
+ *****************************************/
+
+class P11AttrAllowedMechanisms : public P11Attribute
+{
+public:
+ // Constructor
+ P11AttrAllowedMechanisms(OSObject* inobject) : P11Attribute(inobject) { type = CKA_ALLOWED_MECHANISMS; checks = 0; }
+
+protected:
+ // Set the default value of the attribute
+ virtual bool setDefault();
+
+ // Update the value if allowed
+ virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op);
+};
+
+#endif // !_SOFTHSM_V2_P11ATTRIBUTES_H
diff --git a/SoftHSMv2/src/lib/P11Objects.cpp b/SoftHSMv2/src/lib/P11Objects.cpp
new file mode 100644
index 0000000..c58d4ec
--- /dev/null
+++ b/SoftHSMv2/src/lib/P11Objects.cpp
@@ -0,0 +1,1807 @@
+/*
+ * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ P11Objects.cpp
+
+ This class respresent a PKCS#11 object
+ *****************************************************************************/
+
+#include "config.h"
+#include "P11Objects.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+// Constructor
+P11Object::P11Object()
+{
+ initialized = false;
+ osobject = NULL;
+}
+
+// Destructor
+P11Object::~P11Object()
+{
+ std::map<CK_ATTRIBUTE_TYPE, P11Attribute*> cleanUp = attributes;
+ attributes.clear();
+
+ for (std::map<CK_ATTRIBUTE_TYPE, P11Attribute*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if (i->second == NULL)
+ {
+ continue;
+ }
+
+ delete i->second;
+ i->second = NULL;
+ }
+}
+
+// Add attributes
+bool P11Object::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ osobject = inobject;
+
+ // Create attributes
+ P11Attribute* attrClass = new P11AttrClass(osobject);
+ P11Attribute* attrToken = new P11AttrToken(osobject);
+ P11Attribute* attrPrivate = new P11AttrPrivate(osobject);
+ P11Attribute* attrModifiable = new P11AttrModifiable(osobject);
+ P11Attribute* attrLabel = new P11AttrLabel(osobject);
+ P11Attribute* attrCopyable = new P11AttrCopyable(osobject);
+ P11Attribute* attrDestroyable = new P11AttrDestroyable(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrClass->init() ||
+ !attrToken->init() ||
+ !attrPrivate->init() ||
+ !attrModifiable->init() ||
+ !attrLabel->init() ||
+ !attrCopyable->init() ||
+ !attrDestroyable->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrClass;
+ delete attrToken;
+ delete attrPrivate;
+ delete attrModifiable;
+ delete attrLabel;
+ delete attrCopyable;
+ delete attrDestroyable;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrClass->getType()] = attrClass;
+ attributes[attrToken->getType()] = attrToken;
+ attributes[attrPrivate->getType()] = attrPrivate;
+ attributes[attrModifiable->getType()] = attrModifiable;
+ attributes[attrLabel->getType()] = attrLabel;
+ attributes[attrCopyable->getType()] = attrCopyable;
+ attributes[attrDestroyable->getType()] = attrDestroyable;
+
+ initialized = true;
+ return true;
+}
+
+CK_RV P11Object::loadTemplate(Token *token, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
+{
+ bool isPrivate = this->isPrivate();
+
+ // [PKCS#11 v2.40, C_GetAttributeValue]
+ // 1. If the specified attribute (i.e., the attribute specified by the
+ // type field) for the object cannot be revealed because the object
+ // is sensitive or unextractable, then the ulValueLen field in that
+ // triple is modified to hold the value CK_UNAVAILABLE_INFORMATION.
+ //
+ // 2. Otherwise, if the specified value for the object is invalid (the
+ // object does not possess such an attribute), then the ulValueLen
+ // field in that triple is modified to hold the value
+ // CK_UNAVAILABLE_INFORMATION.
+ //
+ // 3. Otherwise, if the pValue field has the value NULL_PTR, then the
+ // ulValueLen field is modified to hold the exact length of the
+ // specified attribute for the object.
+ //
+ // 4. Otherwise, if the length specified in ulValueLen is large enough
+ // to hold the value of the specified attribute for the object,
+ // then that attribute is copied into the buffer located at pValue,
+ // and the ulValueLen field is modified to hold the exact length of
+ // the attribute.
+ //
+ // 5. Otherwise, the ulValueLen field is modified to hold the value
+ // CK_UNAVAILABLE_INFORMATION.
+
+ bool invalid = false, sensitive = false, buffer_too_small = false;
+
+ // If case 3 or 4 applies to all the requested attributes, then the call will return CKR_OK.
+ for (CK_ULONG i = 0; i < ulAttributeCount; ++i)
+ {
+ P11Attribute* attr = attributes[pTemplate[i].type];
+
+ // case 2 of the attribute checks
+ if (attr == NULL) {
+ pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION;
+ // If case 2 applies to any of the requested attributes, then the call should
+ // return the value CKR_ATTRIBUTE_TYPE_INVALID.
+ invalid = true;
+ continue;
+ }
+
+ // case 1,3,4 and 5 of the attribute checks are done while retrieving the attribute itself.
+ CK_RV retrieve_rv = attr->retrieve(token, isPrivate, pTemplate[i].pValue, &pTemplate[i].ulValueLen);
+ if (retrieve_rv == CKR_ATTRIBUTE_SENSITIVE) {
+ // If case 1 applies to any of the requested attributes, then the call should
+ // return the value CKR_ATTRIBUTE_SENSITIVE.
+ sensitive = true;
+ } else if (retrieve_rv == CKR_BUFFER_TOO_SMALL) {
+ // If case 5 applies to any of the requested attributes, then the call should
+ // return the value CKR_BUFFER_TOO_SMALL.
+ buffer_too_small = true;
+ } else if (retrieve_rv != CKR_OK) {
+ return CKR_GENERAL_ERROR;
+ }
+
+ }
+
+ // As usual if more than one of these error codes is applicable, Cryptoki may
+ // return any of them. Only if none of them applies to any of the requested
+ // attributes will CKR_OK be returned. We choose to return the errors in
+ // the following priority, which is probably the most useful order.
+ if (sensitive)
+ return CKR_ATTRIBUTE_SENSITIVE;
+ if (invalid)
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ if (buffer_too_small)
+ return CKR_BUFFER_TOO_SMALL;
+ return CKR_OK;
+}
+
+// Save template
+CK_RV P11Object::saveTemplate(Token *token, bool isPrivate, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, int op)
+{
+ if (osobject == NULL)
+ return CKR_GENERAL_ERROR;
+ if (osobject->startTransaction() == false)
+ return CKR_GENERAL_ERROR;
+
+ if (op == OBJECT_OP_SET)
+ {
+ if (!isModifiable())
+ {
+ osobject->abortTransaction();
+ return CKR_ACTION_PROHIBITED;
+ }
+ }
+
+ // [PKCS#11 v2.40, 4.1.3 Copying objects] OBJECT_OP_COPY
+ // If the CKA_COPYABLE attribute of the object to be copied is set
+ // to CK_FALSE, C_CopyObject returns CKR_ACTION_PROHIBITED.
+ if (op == OBJECT_OP_COPY)
+ {
+ if (!isCopyable())
+ {
+ osobject->abortTransaction();
+ return CKR_ACTION_PROHIBITED;
+ }
+ }
+
+ for (CK_ULONG i = 0; i < ulAttributeCount; i++)
+ {
+ // [PKCS#11 v2.40, 4.1.1 Creating objects] OBJECT_OP_CREATE | OBJECT_OP_SET | OBJECT_OP_COPY
+ // 1. If the supplied template specifies a value for an invalid attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_TYPE_INVALID. An attribute
+ // is valid if it is either one of the attributes described in the Cryptoki specification or an
+ // additional vendor-specific attribute supported by the library and token.
+ P11Attribute* attr = attributes[pTemplate[i].type];
+
+ if (attr == NULL)
+ {
+ osobject->abortTransaction();
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+
+ // Additonal checks are done while updating the attributes themselves.
+ CK_RV rv = attr->update(token,isPrivate, pTemplate[i].pValue, pTemplate[i].ulValueLen, op);
+ if (rv != CKR_OK)
+ {
+ osobject->abortTransaction();
+ return rv;
+ }
+ }
+
+ // [PKCS#11 v2.40, 4.1.1 Creating objects]
+ // 4. If the attribute values in the supplied template, together with any default attribute
+ // values and any attribute values contributed to the object by the object-creation
+ // function itself, are insufficient to fully specify the object to create, then the attempt
+ // should fail with the error code CKR_TEMPLATE_INCOMPLETE.
+
+ // All attributes that have to be specified are marked as such in the specification.
+ // The following checks are relevant here:
+ for (std::map<CK_ATTRIBUTE_TYPE, P11Attribute*>::iterator i = attributes.begin(); i != attributes.end(); i++)
+ {
+ CK_ULONG checks = i->second->getChecks();
+
+ // ck1 MUST be specified when object is created with C_CreateObject.
+ // ck3 MUST be specified when object is generated with C_GenerateKey or C_GenerateKeyPair.
+ // ck5 MUST be specified when object is unwrapped with C_UnwrapKey.
+ if (((checks & P11Attribute::ck1) == P11Attribute::ck1 && op == OBJECT_OP_CREATE) ||
+ ((checks & P11Attribute::ck3) == P11Attribute::ck3 && op == OBJECT_OP_GENERATE) ||
+ ((checks & P11Attribute::ck5) == P11Attribute::ck5 && op == OBJECT_OP_UNWRAP))
+ {
+ bool isSpecified = false;
+
+ for (CK_ULONG n = 0; n < ulAttributeCount; n++)
+ {
+ if (i->first == pTemplate[n].type)
+ {
+ isSpecified = true;
+ break;
+ }
+ }
+
+ if (!isSpecified)
+ {
+ ERROR_MSG("Mandatory attribute (0x%08X) was not specified in template", (unsigned int)i->first);
+
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ }
+ }
+
+ // [PKCS#11 v2.40, 4.1.1 Creating objects]
+ // 5. If the attribute values in the supplied template, together with any default attribute
+ // values and any attribute values contributed to the object by the object-creation
+ // function itself, are inconsistent, then the attempt should fail with the error code
+ // CKR_TEMPLATE_INCONSISTENT. A set of attribute values is inconsistent if not
+ // all of its members can be satisfied simultaneously by the token, although each value
+ // individually is valid in Cryptoki. One example of an inconsistent template would be
+ // using a template which specifies two different values for the same attribute. Another
+ // example would be trying to create a secret key object with an attribute which is
+ // appropriate for various types of public keys or private keys, but not for secret keys.
+ // A final example would be a template with an attribute that violates some token
+ // specific requirement. Note that this final example of an inconsistent template is
+ // token-dependent—on a different token, such a template might not be inconsistent.
+
+ if (osobject->commitTransaction() == false)
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+bool P11Object::isPrivate()
+{
+ // Get the CKA_PRIVATE attribute, when the attribute is
+ // not present return the default value which we have
+ // chosen to be CK_FALSE.
+ if (!osobject->attributeExists(CKA_PRIVATE)) return false;
+
+ return osobject->getBooleanValue(CKA_PRIVATE, false);
+}
+
+bool P11Object::isCopyable()
+{
+ // Get the CKA_COPYABLE attribute, when the attribute is not
+ // present return the default value which is CK_TRUE.
+ if (!osobject->attributeExists(CKA_COPYABLE)) return true;
+
+ return osobject->getBooleanValue(CKA_COPYABLE, true);
+}
+
+bool P11Object::isModifiable()
+{
+ // Get the CKA_MODIFIABLE attribute, when the attribute is
+ // not present return the default value which is CK_TRUE.
+ if (!osobject->attributeExists(CKA_MODIFIABLE)) return true;
+
+ return osobject->getBooleanValue(CKA_MODIFIABLE, true);
+}
+
+// Constructor
+P11DataObj::P11DataObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DataObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ // Set default values for attributes that will be introduced in the parent
+ if (!inobject->attributeExists(CKA_CLASS) || inobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_DATA) {
+ OSAttribute setClass((unsigned long)CKO_DATA);
+ inobject->setAttribute(CKA_CLASS, setClass);
+ }
+
+ // Create parent
+ if (!P11Object::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrApplication = new P11AttrApplication(osobject);
+ P11Attribute* attrObjectID = new P11AttrObjectID(osobject);
+ // NOTE: There is no mention in the PKCS#11 v2.40 spec that for a Data
+ // Object the CKA_VALUE attribute may be modified after creation!
+ // Therefore we assume it is not allowed to change the CKA_VALUE
+ // attribute of a Data Object.
+ P11Attribute* attrValue = new P11AttrValue(osobject,0);
+
+ // Initialize the attributes
+ if
+ (
+ !attrApplication->init() ||
+ !attrObjectID->init() ||
+ !attrValue->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrApplication;
+ delete attrObjectID;
+ delete attrValue;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrApplication->getType()] = attrApplication;
+ attributes[attrObjectID->getType()] = attrObjectID;
+ attributes[attrValue->getType()] = attrValue;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11CertificateObj::P11CertificateObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11CertificateObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ // Set default values for attributes that will be introduced in the parent
+ if (!inobject->attributeExists(CKA_CLASS) || inobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_CERTIFICATE) {
+ OSAttribute setClass((unsigned long)CKO_CERTIFICATE);
+ inobject->setAttribute(CKA_CLASS, setClass);
+ }
+ // Make certificates public
+ if (!inobject->attributeExists(CKA_PRIVATE)) {
+ OSAttribute setPrivate(false);
+ inobject->setAttribute(CKA_PRIVATE, setPrivate);
+ }
+
+ // Create parent
+ if (!P11Object::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrCertificateType = new P11AttrCertificateType(osobject);
+ P11Attribute* attrTrusted = new P11AttrTrusted(osobject);
+ P11Attribute* attrCertificateCategory = new P11AttrCertificateCategory(osobject);
+ // NOTE: Because these attributes are used in a certificate object
+ // where the CKA_VALUE containing the certificate data is not
+ // modifiable, we assume that this attribute is also not modifiable.
+ // There is also no explicit mention of these attributes being modifiable.
+ P11Attribute* attrCheckValue = new P11AttrCheckValue(osobject, 0);
+ P11Attribute* attrStartDate = new P11AttrStartDate(osobject,0);
+ P11Attribute* attrEndDate = new P11AttrEndDate(osobject,0);
+ // TODO: CKA_PUBLIC_KEY_INFO is accepted, but we do not calculate it.
+ P11Attribute* attrPublicKeyInfo = new P11AttrPublicKeyInfo(osobject,0);
+
+ // Initialize the attributes
+ if
+ (
+ !attrCertificateType->init() ||
+ !attrTrusted->init() ||
+ !attrCertificateCategory->init() ||
+ !attrCheckValue->init() ||
+ !attrStartDate->init() ||
+ !attrEndDate->init() ||
+ !attrPublicKeyInfo->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrCertificateType;
+ delete attrTrusted;
+ delete attrCertificateCategory;
+ delete attrCheckValue;
+ delete attrStartDate;
+ delete attrEndDate;
+ delete attrPublicKeyInfo;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrCertificateType->getType()] = attrCertificateType;
+ attributes[attrTrusted->getType()] = attrTrusted;
+ attributes[attrCertificateCategory->getType()] = attrCertificateCategory;
+ attributes[attrCheckValue->getType()] = attrCheckValue;
+ attributes[attrStartDate->getType()] = attrStartDate;
+ attributes[attrEndDate->getType()] = attrEndDate;
+ attributes[attrPublicKeyInfo->getType()] = attrPublicKeyInfo;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11X509CertificateObj::P11X509CertificateObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11X509CertificateObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ // Set default values for attributes that will be introduced in the parent
+ if (!inobject->attributeExists(CKA_CERTIFICATE_TYPE) || inobject->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_VENDOR_DEFINED) != CKC_X_509) {
+ OSAttribute setCertType((unsigned long)CKC_X_509);
+ inobject->setAttribute(CKA_CERTIFICATE_TYPE, setCertType);
+ }
+
+ // Create parent
+ if (!P11CertificateObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrSubject = new P11AttrSubject(osobject,P11Attribute::ck1);
+ P11Attribute* attrID = new P11AttrID(osobject);
+ P11Attribute* attrIssuer = new P11AttrIssuer(osobject);
+ P11Attribute* attrSerialNumber = new P11AttrSerialNumber(osobject);
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck14);
+ P11Attribute* attrURL = new P11AttrURL(osobject);
+ P11Attribute* attrHashOfSubjectPublicKey = new P11AttrHashOfSubjectPublicKey(osobject);
+ P11Attribute* attrHashOfIssuerPublicKey = new P11AttrHashOfIssuerPublicKey(osobject);
+ P11Attribute* attrJavaMidpSecurityDomain = new P11AttrJavaMidpSecurityDomain(osobject);
+ P11Attribute* attrNameHashAlgorithm = new P11AttrNameHashAlgorithm(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrSubject->init() ||
+ !attrID->init() ||
+ !attrIssuer->init() ||
+ !attrSerialNumber->init() ||
+ !attrValue->init() ||
+ !attrURL->init() ||
+ !attrHashOfSubjectPublicKey->init() ||
+ !attrHashOfIssuerPublicKey->init() ||
+ !attrJavaMidpSecurityDomain->init() ||
+ !attrNameHashAlgorithm->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrSubject;
+ delete attrID;
+ delete attrIssuer;
+ delete attrSerialNumber;
+ delete attrValue;
+ delete attrURL;
+ delete attrHashOfSubjectPublicKey;
+ delete attrHashOfIssuerPublicKey;
+ delete attrJavaMidpSecurityDomain;
+ delete attrNameHashAlgorithm;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSubject->getType()] = attrSubject;
+ attributes[attrID->getType()] = attrID;
+ attributes[attrIssuer->getType()] = attrIssuer;
+ attributes[attrSerialNumber->getType()] = attrSerialNumber;
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrURL->getType()] = attrURL;
+ attributes[attrHashOfSubjectPublicKey->getType()] = attrHashOfSubjectPublicKey;
+ attributes[attrHashOfIssuerPublicKey->getType()] = attrHashOfIssuerPublicKey;
+ attributes[attrJavaMidpSecurityDomain->getType()] = attrJavaMidpSecurityDomain;
+ attributes[attrNameHashAlgorithm->getType()] = attrNameHashAlgorithm;
+
+ return true;
+}
+
+// Constructor
+P11OpenPGPPublicKeyObj::P11OpenPGPPublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11OpenPGPPublicKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ // Set default values for attributes that will be introduced in the parent
+ if (!inobject->attributeExists(CKA_CERTIFICATE_TYPE) || inobject->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_VENDOR_DEFINED) != CKC_OPENPGP) {
+ OSAttribute setCertType((unsigned long)CKC_OPENPGP);
+ inobject->setAttribute(CKA_CERTIFICATE_TYPE, setCertType);
+ }
+
+ // Create parent
+ if (!P11CertificateObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrSubject = new P11AttrSubject(osobject,P11Attribute::ck1);
+ P11Attribute* attrID = new P11AttrID(osobject);
+ P11Attribute* attrIssuer = new P11AttrIssuer(osobject);
+ P11Attribute* attrSerialNumber = new P11AttrSerialNumber(osobject);
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck14);
+ P11Attribute* attrURL = new P11AttrURL(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrSubject->init() ||
+ !attrID->init() ||
+ !attrIssuer->init() ||
+ !attrSerialNumber->init() ||
+ !attrValue->init() ||
+ !attrURL->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrSubject;
+ delete attrID;
+ delete attrIssuer;
+ delete attrSerialNumber;
+ delete attrValue;
+ delete attrURL;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSubject->getType()] = attrSubject;
+ attributes[attrID->getType()] = attrID;
+ attributes[attrIssuer->getType()] = attrIssuer;
+ attributes[attrSerialNumber->getType()] = attrSerialNumber;
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrURL->getType()] = attrURL;
+
+ return true;
+}
+
+// Constructor
+P11KeyObj::P11KeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11KeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ // Create parent
+ if (!P11Object::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrKeyType = new P11AttrKeyType(osobject,P11Attribute::ck5);
+ P11Attribute* attrID = new P11AttrID(osobject);
+ P11Attribute* attrStartDate = new P11AttrStartDate(osobject,P11Attribute::ck8);
+ P11Attribute* attrEndDate = new P11AttrEndDate(osobject,P11Attribute::ck8);
+ P11Attribute* attrDerive = new P11AttrDerive(osobject);
+ P11Attribute* attrLocal = new P11AttrLocal(osobject,P11Attribute::ck6);
+ P11Attribute* attrKeyGenMechanism = new P11AttrKeyGenMechanism(osobject);
+ P11Attribute* attrAllowedMechanisms = new P11AttrAllowedMechanisms(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrKeyType->init() ||
+ !attrID->init() ||
+ !attrStartDate->init() ||
+ !attrEndDate->init() ||
+ !attrDerive->init() ||
+ !attrLocal->init() ||
+ !attrKeyGenMechanism->init() ||
+ !attrAllowedMechanisms->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrKeyType;
+ delete attrID;
+ delete attrStartDate;
+ delete attrEndDate;
+ delete attrDerive;
+ delete attrLocal;
+ delete attrKeyGenMechanism;
+ delete attrAllowedMechanisms;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrKeyType->getType()] = attrKeyType;
+ attributes[attrID->getType()] = attrID;
+ attributes[attrStartDate->getType()] = attrStartDate;
+ attributes[attrEndDate->getType()] = attrEndDate;
+ attributes[attrDerive->getType()] = attrDerive;
+ attributes[attrLocal->getType()] = attrLocal;
+ attributes[attrKeyGenMechanism->getType()] = attrKeyGenMechanism;
+ attributes[attrAllowedMechanisms->getType()] = attrAllowedMechanisms;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11PublicKeyObj::P11PublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11PublicKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ // Set default values for attributes that will be introduced in the parent
+ if (!inobject->attributeExists(CKA_CLASS) || inobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY) {
+ OSAttribute setClass((unsigned long)CKO_PUBLIC_KEY);
+ inobject->setAttribute(CKA_CLASS, setClass);
+ }
+ // Make public keys public
+ if (!inobject->attributeExists(CKA_PRIVATE)) {
+ OSAttribute setPrivate(false);
+ inobject->setAttribute(CKA_PRIVATE, setPrivate);
+ }
+
+ // Create parent
+ if (!P11KeyObj::init(inobject)) return false;
+
+ if (initialized) return true;
+
+ // Create attributes
+ P11Attribute* attrSubject = new P11AttrSubject(osobject,P11Attribute::ck8);
+ P11Attribute* attrEncrypt = new P11AttrEncrypt(osobject);
+ P11Attribute* attrVerify = new P11AttrVerify(osobject);
+ P11Attribute* attrVerifyRecover = new P11AttrVerifyRecover(osobject);
+ P11Attribute* attrWrap = new P11AttrWrap(osobject);
+ P11Attribute* attrTrusted = new P11AttrTrusted(osobject);
+ P11Attribute* attrWrapTemplate = new P11AttrWrapTemplate(osobject);
+ // TODO: CKA_PUBLIC_KEY_INFO is accepted, but we do not calculate it
+ P11Attribute* attrPublicKeyInfo = new P11AttrPublicKeyInfo(osobject,0);
+
+ // Initialize the attributes
+ if
+ (
+ !attrSubject->init() ||
+ !attrEncrypt->init() ||
+ !attrVerify->init() ||
+ !attrVerifyRecover->init() ||
+ !attrWrap->init() ||
+ !attrTrusted->init() ||
+ !attrWrapTemplate->init() ||
+ !attrPublicKeyInfo->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrSubject;
+ delete attrEncrypt;
+ delete attrVerify;
+ delete attrVerifyRecover;
+ delete attrWrap;
+ delete attrTrusted;
+ delete attrWrapTemplate;
+ delete attrPublicKeyInfo;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSubject->getType()] = attrSubject;
+ attributes[attrEncrypt->getType()] = attrEncrypt;
+ attributes[attrVerify->getType()] = attrVerify;
+ attributes[attrVerifyRecover->getType()] = attrVerifyRecover;
+ attributes[attrWrap->getType()] = attrWrap;
+ attributes[attrTrusted->getType()] = attrTrusted;
+ attributes[attrWrapTemplate->getType()] = attrWrapTemplate;
+ attributes[attrPublicKeyInfo->getType()] = attrPublicKeyInfo;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11RSAPublicKeyObj::P11RSAPublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11RSAPublicKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) {
+ OSAttribute setKeyType((unsigned long)CKK_RSA);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PublicKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrModulus = new P11AttrModulus(osobject);
+ P11Attribute* attrModulusBits = new P11AttrModulusBits(osobject);
+ P11Attribute* attrPublicExponent = new P11AttrPublicExponent(osobject,P11Attribute::ck1);
+
+ // Initialize the attributes
+ if
+ (
+ !attrModulus->init() ||
+ !attrModulusBits->init() ||
+ !attrPublicExponent->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrModulus;
+ delete attrModulusBits;
+ delete attrPublicExponent;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrModulus->getType()] = attrModulus;
+ attributes[attrModulusBits->getType()] = attrModulusBits;
+ attributes[attrPublicExponent->getType()] = attrPublicExponent;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DSAPublicKeyObj::P11DSAPublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DSAPublicKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DSA) {
+ OSAttribute setKeyType((unsigned long)CKK_DSA);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PublicKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrPrime = new P11AttrPrime(osobject,P11Attribute::ck3);
+ P11Attribute* attrSubPrime = new P11AttrSubPrime(osobject,P11Attribute::ck3);
+ P11Attribute* attrBase = new P11AttrBase(osobject,P11Attribute::ck3);
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4);
+
+ // Initialize the attributes
+ if
+ (
+ !attrPrime->init() ||
+ !attrSubPrime->init() ||
+ !attrBase->init() ||
+ !attrValue->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrPrime;
+ delete attrSubPrime;
+ delete attrBase;
+ delete attrValue;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrPrime->getType()] = attrPrime;
+ attributes[attrSubPrime->getType()] = attrSubPrime;
+ attributes[attrBase->getType()] = attrBase;
+ attributes[attrValue->getType()] = attrValue;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11ECPublicKeyObj::P11ECPublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11ECPublicKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC) {
+ OSAttribute setKeyType((unsigned long)CKK_EC);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PublicKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrEcParams = new P11AttrEcParams(osobject,P11Attribute::ck3);
+ P11Attribute* attrEcPoint = new P11AttrEcPoint(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrEcParams->init() ||
+ !attrEcPoint->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrEcParams;
+ delete attrEcPoint;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrEcParams->getType()] = attrEcParams;
+ attributes[attrEcPoint->getType()] = attrEcPoint;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DHPublicKeyObj::P11DHPublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DHPublicKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH) {
+ OSAttribute setKeyType((unsigned long)CKK_DH);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PublicKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrPrime = new P11AttrPrime(osobject,P11Attribute::ck3);
+ P11Attribute* attrBase = new P11AttrBase(osobject,P11Attribute::ck3);
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4);
+
+ // Initialize the attributes
+ if
+ (
+ !attrPrime->init() ||
+ !attrBase->init() ||
+ !attrValue->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrPrime;
+ delete attrBase;
+ delete attrValue;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrPrime->getType()] = attrPrime;
+ attributes[attrBase->getType()] = attrBase;
+ attributes[attrValue->getType()] = attrValue;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11GOSTPublicKeyObj::P11GOSTPublicKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11GOSTPublicKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_GOSTR3410) {
+ OSAttribute setKeyType((unsigned long)CKK_GOSTR3410);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PublicKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4);
+ P11Attribute* attrGostR3410Params = new P11AttrGostR3410Params(osobject,P11Attribute::ck3);
+ P11Attribute* attrGostR3411Params = new P11AttrGostR3411Params(osobject,P11Attribute::ck3);
+ P11Attribute* attrGost28147Params = new P11AttrGost28147Params(osobject,P11Attribute::ck8);
+
+ // Initialize the attributes
+ if
+ (
+ !attrValue->init() ||
+ !attrGostR3410Params->init() ||
+ !attrGostR3411Params->init() ||
+ !attrGost28147Params->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrValue;
+ delete attrGostR3410Params;
+ delete attrGostR3411Params;
+ delete attrGost28147Params;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrGostR3410Params->getType()] = attrGostR3410Params;
+ attributes[attrGostR3411Params->getType()] = attrGostR3411Params;
+ attributes[attrGost28147Params->getType()] = attrGost28147Params;
+
+ initialized = true;
+ return true;
+}
+
+//constructor
+P11PrivateKeyObj::P11PrivateKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11PrivateKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_CLASS) || inobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY) {
+ OSAttribute setClass((unsigned long)CKO_PRIVATE_KEY);
+ inobject->setAttribute(CKA_CLASS, setClass);
+ }
+
+ // Create parent
+ if (!P11KeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrSubject = new P11AttrSubject(osobject,P11Attribute::ck8);
+ P11Attribute* attrSensitive = new P11AttrSensitive(osobject);
+ P11Attribute* attrDecrypt = new P11AttrDecrypt(osobject);
+ P11Attribute* attrSign = new P11AttrSign(osobject);
+ P11Attribute* attrSignRecover = new P11AttrSignRecover(osobject);
+ P11Attribute* attrUnwrap = new P11AttrUnwrap(osobject);
+ P11Attribute* attrExtractable = new P11AttrExtractable(osobject);
+ P11Attribute* attrAlwaysSensitive = new P11AttrAlwaysSensitive(osobject);
+ P11Attribute* attrNeverExtractable = new P11AttrNeverExtractable(osobject);
+ P11Attribute* attrWrapWithTrusted = new P11AttrWrapWithTrusted(osobject);
+ P11Attribute* attrUnwrapTemplate = new P11AttrUnwrapTemplate(osobject);
+ // TODO: CKA_ALWAYS_AUTHENTICATE is accepted, but we do not use it
+ P11Attribute* attrAlwaysAuthenticate = new P11AttrAlwaysAuthenticate(osobject);
+ // TODO: CKA_PUBLIC_KEY_INFO is accepted, but we do not calculate it
+ P11Attribute* attrPublicKeyInfo = new P11AttrPublicKeyInfo(osobject,P11Attribute::ck8);
+
+ // Initialize the attributes
+ if
+ (
+ !attrSubject->init() ||
+ !attrSensitive->init() ||
+ !attrDecrypt->init() ||
+ !attrSign->init() ||
+ !attrSignRecover->init() ||
+ !attrUnwrap->init() ||
+ !attrExtractable->init() ||
+ !attrAlwaysSensitive->init() ||
+ !attrNeverExtractable->init() ||
+ !attrWrapWithTrusted->init() ||
+ !attrUnwrapTemplate->init() ||
+ !attrAlwaysAuthenticate->init() ||
+ !attrPublicKeyInfo->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrSubject;
+ delete attrSensitive;
+ delete attrDecrypt;
+ delete attrSign;
+ delete attrSignRecover;
+ delete attrUnwrap;
+ delete attrExtractable;
+ delete attrAlwaysSensitive;
+ delete attrNeverExtractable;
+ delete attrWrapWithTrusted;
+ delete attrUnwrapTemplate;
+ delete attrAlwaysAuthenticate;
+ delete attrPublicKeyInfo;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSubject->getType()] = attrSubject;
+ attributes[attrSensitive->getType()] = attrSensitive;
+ attributes[attrDecrypt->getType()] = attrDecrypt;
+ attributes[attrSign->getType()] = attrSign;
+ attributes[attrSignRecover->getType()] = attrSignRecover;
+ attributes[attrUnwrap->getType()] = attrUnwrap;
+ attributes[attrExtractable->getType()] = attrExtractable;
+ attributes[attrAlwaysSensitive->getType()] = attrAlwaysSensitive;
+ attributes[attrNeverExtractable->getType()] = attrNeverExtractable;
+ attributes[attrWrapWithTrusted->getType()] = attrWrapWithTrusted;
+ attributes[attrUnwrapTemplate->getType()] = attrUnwrapTemplate;
+ attributes[attrAlwaysAuthenticate->getType()] = attrAlwaysAuthenticate;
+ attributes[attrPublicKeyInfo->getType()] = attrPublicKeyInfo;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11RSAPrivateKeyObj::P11RSAPrivateKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11RSAPrivateKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA) {
+ OSAttribute setKeyType((unsigned long)CKK_RSA);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PrivateKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrModulus = new P11AttrModulus(osobject,P11Attribute::ck6);
+ P11Attribute* attrPublicExponent = new P11AttrPublicExponent(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrPrivateExponent = new P11AttrPrivateExponent(osobject);
+ P11Attribute* attrPrime1 = new P11AttrPrime1(osobject);
+ P11Attribute* attrPrime2 = new P11AttrPrime2(osobject);
+ P11Attribute* attrExponent1 = new P11AttrExponent1(osobject);
+ P11Attribute* attrExponent2 = new P11AttrExponent2(osobject);
+ P11Attribute* attrCoefficient = new P11AttrCoefficient(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrModulus->init() ||
+ !attrPublicExponent->init() ||
+ !attrPrivateExponent->init() ||
+ !attrPrime1->init() ||
+ !attrPrime2->init() ||
+ !attrExponent1->init() ||
+ !attrExponent2->init() ||
+ !attrCoefficient->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrModulus;
+ delete attrPublicExponent;
+ delete attrPrivateExponent;
+ delete attrPrime1;
+ delete attrPrime2;
+ delete attrExponent1;
+ delete attrExponent2;
+ delete attrCoefficient;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrModulus->getType()] = attrModulus;
+ attributes[attrPublicExponent->getType()] = attrPublicExponent;
+ attributes[attrPrivateExponent->getType()] = attrPrivateExponent;
+ attributes[attrPrime1->getType()] = attrPrime1;
+ attributes[attrPrime2->getType()] = attrPrime2;
+ attributes[attrExponent1->getType()] = attrExponent1;
+ attributes[attrExponent2->getType()] = attrExponent2;
+ attributes[attrCoefficient->getType()] = attrCoefficient;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DSAPrivateKeyObj::P11DSAPrivateKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DSAPrivateKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DSA) {
+ OSAttribute setKeyType((unsigned long)CKK_DSA);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PrivateKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrPrime = new P11AttrPrime(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrSubPrime = new P11AttrSubPrime(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrBase = new P11AttrBase(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7);
+
+ // Initialize the attributes
+ if
+ (
+ !attrPrime->init() ||
+ !attrSubPrime->init() ||
+ !attrBase->init() ||
+ !attrValue->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrPrime;
+ delete attrSubPrime;
+ delete attrBase;
+ delete attrValue;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrPrime->getType()] = attrPrime;
+ attributes[attrSubPrime->getType()] = attrSubPrime;
+ attributes[attrBase->getType()] = attrBase;
+ attributes[attrValue->getType()] = attrValue;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11ECPrivateKeyObj::P11ECPrivateKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11ECPrivateKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC) {
+ OSAttribute setKeyType((unsigned long)CKK_EC);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PrivateKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrEcParams = new P11AttrEcParams(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7);
+
+ // Initialize the attributes
+ if
+ (
+ !attrEcParams->init() ||
+ !attrValue->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrEcParams;
+ delete attrValue;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrEcParams->getType()] = attrEcParams;
+ attributes[attrValue->getType()] = attrValue;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DHPrivateKeyObj::P11DHPrivateKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DHPrivateKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH) {
+ OSAttribute setKeyType((unsigned long)CKK_DH);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PrivateKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrPrime = new P11AttrPrime(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrBase = new P11AttrBase(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7);
+ P11Attribute* attrValueBits = new P11AttrValueBits(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrPrime->init() ||
+ !attrBase->init() ||
+ !attrValue->init() ||
+ !attrValueBits->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrPrime;
+ delete attrBase;
+ delete attrValue;
+ delete attrValueBits;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrPrime->getType()] = attrPrime;
+ attributes[attrBase->getType()] = attrBase;
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrValueBits->getType()] = attrValueBits;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11GOSTPrivateKeyObj::P11GOSTPrivateKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11GOSTPrivateKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_GOSTR3410) {
+ OSAttribute setKeyType((unsigned long)CKK_GOSTR3410);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11PrivateKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7);
+ P11Attribute* attrGostR3410Params = new P11AttrGostR3410Params(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrGostR3411Params = new P11AttrGostR3411Params(osobject,P11Attribute::ck4|P11Attribute::ck6);
+ P11Attribute* attrGost28147Params = new P11AttrGost28147Params(osobject,P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck8);
+
+ // Initialize the attributes
+ if
+ (
+ !attrValue->init() ||
+ !attrGostR3410Params->init() ||
+ !attrGostR3411Params->init() ||
+ !attrGost28147Params->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrValue;
+ delete attrGostR3410Params;
+ delete attrGostR3411Params;
+ delete attrGost28147Params;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrGostR3410Params->getType()] = attrGostR3410Params;
+ attributes[attrGostR3411Params->getType()] = attrGostR3411Params;
+ attributes[attrGost28147Params->getType()] = attrGost28147Params;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11SecretKeyObj::P11SecretKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11SecretKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_CLASS) || inobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY) {
+ OSAttribute setClass((unsigned long)CKO_SECRET_KEY);
+ inobject->setAttribute(CKA_CLASS, setClass);
+ }
+
+ // Create parent
+ if (!P11KeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrSensitive = new P11AttrSensitive(osobject);
+ P11Attribute* attrEncrypt = new P11AttrEncrypt(osobject);
+ P11Attribute* attrDecrypt = new P11AttrDecrypt(osobject);
+ P11Attribute* attrSign = new P11AttrSign(osobject);
+ P11Attribute* attrVerify = new P11AttrVerify(osobject);
+ P11Attribute* attrWrap = new P11AttrWrap(osobject);
+ P11Attribute* attrUnwrap = new P11AttrUnwrap(osobject);
+ P11Attribute* attrExtractable = new P11AttrExtractable(osobject);
+ P11Attribute* attrAlwaysSensitive = new P11AttrAlwaysSensitive(osobject);
+ P11Attribute* attrNeverExtractable = new P11AttrNeverExtractable(osobject);
+ P11Attribute* attrCheckValue = new P11AttrCheckValue(osobject, P11Attribute::ck8);
+ P11Attribute* attrWrapWithTrusted = new P11AttrWrapWithTrusted(osobject);
+ P11Attribute* attrTrusted = new P11AttrTrusted(osobject);
+ P11Attribute* attrWrapTemplate = new P11AttrWrapTemplate(osobject);
+ P11Attribute* attrUnwrapTemplate = new P11AttrUnwrapTemplate(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrSensitive->init() ||
+ !attrEncrypt->init() ||
+ !attrDecrypt->init() ||
+ !attrSign->init() ||
+ !attrVerify->init() ||
+ !attrWrap->init() ||
+ !attrUnwrap->init() ||
+ !attrExtractable->init() ||
+ !attrAlwaysSensitive->init() ||
+ !attrNeverExtractable->init() ||
+ !attrCheckValue->init() ||
+ !attrWrapWithTrusted->init() ||
+ !attrTrusted->init() ||
+ !attrWrapTemplate->init() ||
+ !attrUnwrapTemplate->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrSensitive;
+ delete attrEncrypt;
+ delete attrDecrypt;
+ delete attrSign;
+ delete attrVerify;
+ delete attrWrap;
+ delete attrUnwrap;
+ delete attrExtractable;
+ delete attrAlwaysSensitive;
+ delete attrNeverExtractable;
+ delete attrCheckValue;
+ delete attrWrapWithTrusted;
+ delete attrTrusted;
+ delete attrWrapTemplate;
+ delete attrUnwrapTemplate;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrSensitive->getType()] = attrSensitive;
+ attributes[attrEncrypt->getType()] = attrEncrypt;
+ attributes[attrDecrypt->getType()] = attrDecrypt;
+ attributes[attrSign->getType()] = attrSign;
+ attributes[attrVerify->getType()] = attrVerify;
+ attributes[attrWrap->getType()] = attrWrap;
+ attributes[attrUnwrap->getType()] = attrUnwrap;
+ attributes[attrExtractable->getType()] = attrExtractable;
+ attributes[attrAlwaysSensitive->getType()] = attrAlwaysSensitive;
+ attributes[attrNeverExtractable->getType()] = attrNeverExtractable;
+ attributes[attrCheckValue->getType()] = attrCheckValue;
+ attributes[attrWrapWithTrusted->getType()] = attrWrapWithTrusted;
+ attributes[attrTrusted->getType()] = attrTrusted;
+ attributes[attrWrapTemplate->getType()] = attrWrapTemplate;
+ attributes[attrUnwrapTemplate->getType()] = attrUnwrapTemplate;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11GenericSecretKeyObj::P11GenericSecretKeyObj()
+{
+ initialized = false;
+ keytype = CKK_VENDOR_DEFINED;
+}
+
+// Add attributes
+bool P11GenericSecretKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != keytype) {
+ OSAttribute setKeyType(keytype);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11SecretKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7);
+ P11Attribute* attrValueLen = new P11AttrValueLen(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrValue->init() ||
+ !attrValueLen->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrValue;
+ delete attrValueLen;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrValueLen->getType()] = attrValueLen;
+
+ initialized = true;
+ return true;
+}
+
+// Set Key Type
+bool P11GenericSecretKeyObj::setKeyType(CK_KEY_TYPE inKeytype)
+{
+ if (!initialized)
+ {
+ keytype = inKeytype;
+ return true;
+ }
+ else
+ return false;
+}
+
+// Get Key Type
+CK_KEY_TYPE P11GenericSecretKeyObj::getKeyType()
+{
+ return keytype;
+}
+
+// Constructor
+P11AESSecretKeyObj::P11AESSecretKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11AESSecretKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES) {
+ OSAttribute setKeyType((unsigned long)CKK_AES);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11SecretKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7);
+ P11Attribute* attrValueLen = new P11AttrValueLen(osobject,P11Attribute::ck6);
+
+ // Initialize the attributes
+ if
+ (
+ !attrValue->init() ||
+ !attrValueLen->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrValue;
+ delete attrValueLen;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrValueLen->getType()] = attrValueLen;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DESSecretKeyObj::P11DESSecretKeyObj()
+{
+ initialized = false;
+ keytype = CKK_VENDOR_DEFINED;
+}
+
+// Add attributes
+bool P11DESSecretKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != keytype) {
+ OSAttribute setKeyType(keytype);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11SecretKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7);
+
+ // Initialize the attributes
+ if (!attrValue->init())
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrValue;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrValue->getType()] = attrValue;
+
+ initialized = true;
+ return true;
+}
+
+// Set Key Type
+bool P11DESSecretKeyObj::setKeyType(CK_KEY_TYPE inKeytype)
+{
+ if (!initialized)
+ {
+ keytype = inKeytype;
+ return true;
+ }
+ else
+ return false;
+}
+
+// Get Key Type
+CK_KEY_TYPE P11DESSecretKeyObj::getKeyType()
+{
+ return keytype;
+}
+
+// Constructor
+P11GOSTSecretKeyObj::P11GOSTSecretKeyObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11GOSTSecretKeyObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_GOST28147) {
+ OSAttribute setKeyType((unsigned long)CKK_GOST28147);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11SecretKeyObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7);
+ P11Attribute* attrGost28147Params = new P11AttrGost28147Params(osobject,P11Attribute::ck1|P11Attribute::ck3|P11Attribute::ck5);
+
+ // Initialize the attributes
+ if
+ (
+ !attrValue->init() ||
+ !attrGost28147Params->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrValue;
+ delete attrGost28147Params;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrValue->getType()] = attrValue;
+ attributes[attrGost28147Params->getType()] = attrGost28147Params;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DomainObj::P11DomainObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DomainObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_CLASS) || inobject->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_DOMAIN_PARAMETERS) {
+ OSAttribute setClass((unsigned long)CKO_DOMAIN_PARAMETERS);
+ inobject->setAttribute(CKA_CLASS, setClass);
+ }
+
+ // Create parent
+ if (!P11Object::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrKeyType = new P11AttrKeyType(osobject);
+ P11Attribute* attrLocal = new P11AttrLocal(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrKeyType->init() ||
+ !attrLocal->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrKeyType;
+ delete attrLocal;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrKeyType->getType()] = attrKeyType;
+ attributes[attrLocal->getType()] = attrLocal;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DSADomainObj::P11DSADomainObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DSADomainObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DSA) {
+ OSAttribute setKeyType((unsigned long)CKK_DSA);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11DomainObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrPrime = new P11AttrPrime(osobject,P11Attribute::ck4);
+ P11Attribute* attrSubPrime = new P11AttrSubPrime(osobject,P11Attribute::ck4);
+ P11Attribute* attrBase = new P11AttrBase(osobject,P11Attribute::ck4);
+ P11Attribute* attrPrimeBits = new P11AttrPrimeBits(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrPrime->init() ||
+ !attrSubPrime->init() ||
+ !attrBase->init() ||
+ !attrPrimeBits->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrPrime;
+ delete attrSubPrime;
+ delete attrBase;
+ delete attrPrimeBits;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrPrime->getType()] = attrPrime;
+ attributes[attrSubPrime->getType()] = attrSubPrime;
+ attributes[attrBase->getType()] = attrBase;
+ attributes[attrPrimeBits->getType()] = attrPrimeBits;
+
+ initialized = true;
+ return true;
+}
+
+// Constructor
+P11DHDomainObj::P11DHDomainObj()
+{
+ initialized = false;
+}
+
+// Add attributes
+bool P11DHDomainObj::init(OSObject *inobject)
+{
+ if (initialized) return true;
+ if (inobject == NULL) return false;
+
+ if (!inobject->attributeExists(CKA_KEY_TYPE) || inobject->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH) {
+ OSAttribute setKeyType((unsigned long)CKK_DH);
+ inobject->setAttribute(CKA_KEY_TYPE, setKeyType);
+ }
+
+ // Create parent
+ if (!P11DomainObj::init(inobject)) return false;
+
+ // Create attributes
+ P11Attribute* attrPrime = new P11AttrPrime(osobject,P11Attribute::ck4);
+ P11Attribute* attrBase = new P11AttrBase(osobject,P11Attribute::ck4);
+ P11Attribute* attrPrimeBits = new P11AttrPrimeBits(osobject);
+
+ // Initialize the attributes
+ if
+ (
+ !attrPrime->init() ||
+ !attrBase->init() ||
+ !attrPrimeBits->init()
+ )
+ {
+ ERROR_MSG("Could not initialize the attribute");
+ delete attrPrime;
+ delete attrBase;
+ delete attrPrimeBits;
+ return false;
+ }
+
+ // Add them to the map
+ attributes[attrPrime->getType()] = attrPrime;
+ attributes[attrBase->getType()] = attrBase;
+ attributes[attrPrimeBits->getType()] = attrPrimeBits;
+
+ initialized = true;
+ return true;
+}
diff --git a/SoftHSMv2/src/lib/P11Objects.h b/SoftHSMv2/src/lib/P11Objects.h
new file mode 100644
index 0000000..942a8c4
--- /dev/null
+++ b/SoftHSMv2/src/lib/P11Objects.h
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ P11Objects.h
+
+ This class respresent a PKCS#11 object
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_P11OBJECTS_H
+#define _SOFTHSM_V2_P11OBJECTS_H
+
+#include "OSObject.h"
+#include "P11Attributes.h"
+#include "Token.h"
+#include "cryptoki.h"
+#include <map>
+
+class P11Object
+{
+public:
+ // Destructor
+ virtual ~P11Object();
+
+protected:
+ // Constructor
+ P11Object();
+
+ // The object
+ OSObject* osobject;
+
+ // The attributes
+ std::map<CK_ATTRIBUTE_TYPE, P11Attribute*> attributes;
+
+public:
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+
+public:
+ CK_RV loadTemplate(Token *token, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount);
+
+ // Save template
+ CK_RV saveTemplate(Token *token, bool isPrivate, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, int op);
+
+protected:
+ bool isPrivate();
+ bool isCopyable();
+ bool isModifiable();
+};
+
+class P11DataObj : public P11Object
+{
+public:
+ // Constructor
+ P11DataObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11CertificateObj : public P11Object
+{
+protected:
+ // Constructor
+ P11CertificateObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+ bool initialized;
+};
+
+class P11X509CertificateObj : public P11CertificateObj
+{
+public:
+ // Constructor
+ P11X509CertificateObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11OpenPGPPublicKeyObj : public P11CertificateObj
+{
+public:
+ // Constructor
+ P11OpenPGPPublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11KeyObj : public P11Object
+{
+protected:
+ // Constructor
+ P11KeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+ bool initialized;
+};
+
+class P11PublicKeyObj : public P11KeyObj
+{
+protected:
+ // Constructor
+ P11PublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+ bool initialized;
+};
+
+class P11RSAPublicKeyObj : public P11PublicKeyObj
+{
+public:
+ // Constructor
+ P11RSAPublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11DSAPublicKeyObj : public P11PublicKeyObj
+{
+public:
+ // Constructor
+ P11DSAPublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11ECPublicKeyObj : public P11PublicKeyObj
+{
+public:
+ // Constructor
+ P11ECPublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11DHPublicKeyObj : public P11PublicKeyObj
+{
+public:
+ // Constructor
+ P11DHPublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11GOSTPublicKeyObj : public P11PublicKeyObj
+{
+public:
+ // Constructor
+ P11GOSTPublicKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11PrivateKeyObj : public P11KeyObj
+{
+protected:
+ // Constructor
+ P11PrivateKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+ bool initialized;
+};
+
+class P11RSAPrivateKeyObj : public P11PrivateKeyObj
+{
+public:
+ // Constructor
+ P11RSAPrivateKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11DSAPrivateKeyObj : public P11PrivateKeyObj
+{
+public:
+ // Constructor
+ P11DSAPrivateKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11ECPrivateKeyObj : public P11PrivateKeyObj
+{
+public:
+ // Constructor
+ P11ECPrivateKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11DHPrivateKeyObj : public P11PrivateKeyObj
+{
+public:
+ // Constructor
+ P11DHPrivateKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11GOSTPrivateKeyObj : public P11PrivateKeyObj
+{
+public:
+ // Constructor
+ P11GOSTPrivateKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11SecretKeyObj : public P11KeyObj
+{
+protected:
+ // Constructor
+ P11SecretKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+ bool initialized;
+};
+
+class P11GenericSecretKeyObj : public P11SecretKeyObj
+{
+public:
+ // Constructor
+ P11GenericSecretKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+ // Better than multiply subclasses
+ virtual bool setKeyType(CK_KEY_TYPE inKeytype);
+ virtual CK_KEY_TYPE getKeyType();
+
+protected:
+ bool initialized;
+ CK_KEY_TYPE keytype;
+};
+
+class P11AESSecretKeyObj : public P11SecretKeyObj
+{
+public:
+ // Constructor
+ P11AESSecretKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11DESSecretKeyObj : public P11SecretKeyObj
+{
+public:
+ // Constructor
+ P11DESSecretKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+ // Better than multiply subclasses
+ virtual bool setKeyType(CK_KEY_TYPE inKeytype);
+ virtual CK_KEY_TYPE getKeyType();
+
+protected:
+ bool initialized;
+ CK_KEY_TYPE keytype;
+};
+
+class P11GOSTSecretKeyObj : public P11SecretKeyObj
+{
+public:
+ // Constructor
+ P11GOSTSecretKeyObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+
+protected:
+ bool initialized;
+};
+
+class P11DomainObj : public P11Object
+{
+protected:
+ // Constructor
+ P11DomainObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+ bool initialized;
+};
+
+class P11DSADomainObj : public P11DomainObj
+{
+public:
+ // Constructor
+ P11DSADomainObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+protected:
+ bool initialized;
+};
+
+class P11DHDomainObj : public P11DomainObj
+{
+public:
+ // Constructor
+ P11DHDomainObj();
+
+ // Add attributes
+ virtual bool init(OSObject *inobject);
+protected:
+ bool initialized;
+};
+
+#endif // !_SOFTHSM_V2_P11OBJECTS_H
diff --git a/SoftHSMv2/src/lib/SoftHSM.cpp b/SoftHSMv2/src/lib/SoftHSM.cpp
new file mode 100644
index 0000000..b06efc2
--- /dev/null
+++ b/SoftHSMv2/src/lib/SoftHSM.cpp
@@ -0,0 +1,11178 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SoftHSM.cpp
+
+ The implementation of the SoftHSM's main class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "access.h"
+#include "Configuration.h"
+#include "SimpleConfigLoader.h"
+#include "MutexFactory.h"
+#include "SecureMemoryRegistry.h"
+#include "CryptoFactory.h"
+#include "AsymmetricAlgorithm.h"
+#include "SymmetricAlgorithm.h"
+#include "AESKey.h"
+#include "DESKey.h"
+#include "RNG.h"
+#include "RSAParameters.h"
+#include "RSAPublicKey.h"
+#include "RSAPrivateKey.h"
+#include "DSAParameters.h"
+#include "DSAPublicKey.h"
+#include "DSAPrivateKey.h"
+#include "ECPublicKey.h"
+#include "ECPrivateKey.h"
+#include "ECParameters.h"
+#include "DHParameters.h"
+#include "DHPublicKey.h"
+#include "DHPrivateKey.h"
+#include "GOSTPublicKey.h"
+#include "GOSTPrivateKey.h"
+#include "cryptoki.h"
+#include "SoftHSM.h"
+#include "osmutex.h"
+#include "SessionManager.h"
+#include "SessionObjectStore.h"
+#include "HandleManager.h"
+#include "P11Objects.h"
+#include "odd.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+#include <stdlib.h>
+
+// Initialise the one-and-only instance
+
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+std::unique_ptr<SoftHSM> SoftHSM::instance(nullptr);
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+std::auto_ptr<SoftHSM> SoftHSM::instance(NULL);
+
+#endif
+
+static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERTIFICATE_TYPE certType, P11Object **p11object)
+{
+ switch(objClass) {
+ case CKO_DATA:
+ *p11object = new P11DataObj();
+ break;
+ case CKO_CERTIFICATE:
+ if (certType == CKC_X_509)
+ *p11object = new P11X509CertificateObj();
+ else if (certType == CKC_OPENPGP)
+ *p11object = new P11OpenPGPPublicKeyObj();
+ else
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ case CKO_PUBLIC_KEY:
+ if (keyType == CKK_RSA)
+ *p11object = new P11RSAPublicKeyObj();
+ else if (keyType == CKK_DSA)
+ *p11object = new P11DSAPublicKeyObj();
+ else if (keyType == CKK_EC)
+ *p11object = new P11ECPublicKeyObj();
+ else if (keyType == CKK_DH)
+ *p11object = new P11DHPublicKeyObj();
+ else if (keyType == CKK_GOSTR3410)
+ *p11object = new P11GOSTPublicKeyObj();
+ else
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ case CKO_PRIVATE_KEY:
+ // we need to know the type too
+ if (keyType == CKK_RSA)
+ *p11object = new P11RSAPrivateKeyObj();
+ else if (keyType == CKK_DSA)
+ *p11object = new P11DSAPrivateKeyObj();
+ else if (keyType == CKK_EC)
+ *p11object = new P11ECPrivateKeyObj();
+ else if (keyType == CKK_DH)
+ *p11object = new P11DHPrivateKeyObj();
+ else if (keyType == CKK_GOSTR3410)
+ *p11object = new P11GOSTPrivateKeyObj();
+ else
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ case CKO_SECRET_KEY:
+ if ((keyType == CKK_GENERIC_SECRET) ||
+ (keyType == CKK_MD5_HMAC) ||
+ (keyType == CKK_SHA_1_HMAC) ||
+ (keyType == CKK_SHA224_HMAC) ||
+ (keyType == CKK_SHA256_HMAC) ||
+ (keyType == CKK_SHA384_HMAC) ||
+ (keyType == CKK_SHA512_HMAC))
+ {
+ P11GenericSecretKeyObj* key = new P11GenericSecretKeyObj();
+ *p11object = key;
+ key->setKeyType(keyType);
+ }
+ else if (keyType == CKK_AES)
+ {
+ *p11object = new P11AESSecretKeyObj();
+ }
+ else if ((keyType == CKK_DES) ||
+ (keyType == CKK_DES2) ||
+ (keyType == CKK_DES3))
+ {
+ P11DESSecretKeyObj* key = new P11DESSecretKeyObj();
+ *p11object = key;
+ key->setKeyType(keyType);
+ }
+ else if (keyType == CKK_GOST28147)
+ {
+ *p11object = new P11GOSTSecretKeyObj();
+ }
+ else
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ case CKO_DOMAIN_PARAMETERS:
+ if (keyType == CKK_DSA)
+ *p11object = new P11DSADomainObj();
+ else if (keyType == CKK_DH)
+ *p11object = new P11DHDomainObj();
+ else
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ break;
+ default:
+ return CKR_ATTRIBUTE_VALUE_INVALID; // invalid value for a valid argument
+ }
+ return CKR_OK;
+}
+
+static CK_RV extractObjectInformation(CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_CLASS &objClass,
+ CK_KEY_TYPE &keyType,
+ CK_CERTIFICATE_TYPE &certType,
+ CK_BBOOL &isOnToken,
+ CK_BBOOL &isPrivate,
+ bool bImplicit)
+{
+ bool bHasClass = false;
+ bool bHasKeyType = false;
+ bool bHasCertType = false;
+ bool bHasPrivate = false;
+
+ // Extract object information
+ for (CK_ULONG i = 0; i < ulCount; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ if (pTemplate[i].ulValueLen == sizeof(CK_OBJECT_CLASS))
+ {
+ objClass = *(CK_OBJECT_CLASS_PTR)pTemplate[i].pValue;
+ bHasClass = true;
+ }
+ break;
+ case CKA_KEY_TYPE:
+ if (pTemplate[i].ulValueLen == sizeof(CK_KEY_TYPE))
+ {
+ keyType = *(CK_KEY_TYPE*)pTemplate[i].pValue;
+ bHasKeyType = true;
+ }
+ break;
+ case CKA_CERTIFICATE_TYPE:
+ if (pTemplate[i].ulValueLen == sizeof(CK_CERTIFICATE_TYPE))
+ {
+ certType = *(CK_CERTIFICATE_TYPE*)pTemplate[i].pValue;
+ bHasCertType = true;
+ }
+ break;
+ case CKA_TOKEN:
+ if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
+ {
+ isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
+ }
+ break;
+ case CKA_PRIVATE:
+ if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
+ {
+ isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
+ bHasPrivate = true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (bImplicit)
+ {
+ return CKR_OK;
+ }
+
+ if (!bHasClass)
+ {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ bool bKeyTypeRequired = (objClass == CKO_PUBLIC_KEY || objClass == CKO_PRIVATE_KEY || objClass == CKO_SECRET_KEY);
+ if (bKeyTypeRequired && !bHasKeyType)
+ {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ if (objClass == CKO_CERTIFICATE)
+ {
+ if (!bHasCertType)
+ {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if (!bHasPrivate)
+ {
+ // Change default value for certificates
+ isPrivate = CK_FALSE;
+ }
+ }
+
+ if (objClass == CKO_PUBLIC_KEY && !bHasPrivate)
+ {
+ // Change default value for public keys
+ isPrivate = CK_FALSE;
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV newP11Object(OSObject *object, P11Object **p11object)
+{
+ CK_OBJECT_CLASS objClass = object->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_CERTIFICATE_TYPE certType = CKC_X_509;
+ if (object->attributeExists(CKA_KEY_TYPE))
+ keyType = object->getUnsignedLongValue(CKA_KEY_TYPE, CKK_RSA);
+ if (object->attributeExists(CKA_CERTIFICATE_TYPE))
+ certType = object->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_X_509);
+ CK_RV rv = newP11Object(objClass,keyType,certType,p11object);
+ if (rv != CKR_OK)
+ return rv;
+ if (!(*p11object)->init(object))
+ return CKR_GENERAL_ERROR; // something went wrong that shouldn't have.
+ return CKR_OK;
+}
+
+#ifdef notyet
+static CK_ATTRIBUTE bsAttribute(CK_ATTRIBUTE_TYPE type, const ByteString &value)
+{
+ CK_ATTRIBUTE attr = {type, (CK_VOID_PTR)value.const_byte_str(), value.size() };
+ return attr;
+}
+#endif
+
+/*****************************************************************************
+ Implementation of SoftHSM class specific functions
+ *****************************************************************************/
+
+// Return the one-and-only instance
+SoftHSM* SoftHSM::i()
+{
+ if (!instance.get())
+ {
+ instance.reset(new SoftHSM());
+ }
+
+ return instance.get();
+}
+
+void SoftHSM::reset()
+{
+ if (instance.get())
+ instance.reset();
+}
+
+// Constructor
+SoftHSM::SoftHSM()
+{
+ isInitialised = false;
+ isRemovable = false;
+ sessionObjectStore = NULL;
+ objectStore = NULL;
+ slotManager = NULL;
+ sessionManager = NULL;
+ handleManager = NULL;
+}
+
+// Destructor
+SoftHSM::~SoftHSM()
+{
+ if (handleManager != NULL) delete handleManager;
+ if (sessionManager != NULL) delete sessionManager;
+ if (slotManager != NULL) delete slotManager;
+ if (objectStore != NULL) delete objectStore;
+ if (sessionObjectStore != NULL) delete sessionObjectStore;
+}
+
+/*****************************************************************************
+ Implementation of PKCS #11 functions
+ *****************************************************************************/
+
+// PKCS #11 initialisation function
+CK_RV SoftHSM::C_Initialize(CK_VOID_PTR pInitArgs)
+{
+ CK_C_INITIALIZE_ARGS_PTR args;
+
+ // Check if PKCS#11 is already initialized
+ if (isInitialised)
+ {
+ ERROR_MSG("SoftHSM is already initialized");
+ return CKR_CRYPTOKI_ALREADY_INITIALIZED;
+ }
+
+ // Do we have any arguments?
+ if (pInitArgs != NULL_PTR)
+ {
+ args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
+
+ // Must be set to NULL_PTR in this version of PKCS#11
+ if (args->pReserved != NULL_PTR)
+ {
+ ERROR_MSG("pReserved must be set to NULL_PTR");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ // Can we spawn our own threads?
+ // if (args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS)
+ // {
+ // DEBUG_MSG("Cannot create threads if CKF_LIBRARY_CANT_CREATE_OS_THREADS is set");
+ // return CKR_NEED_TO_CREATE_THREADS;
+ // }
+
+ // Are we not supplied with mutex functions?
+ if
+ (
+ args->CreateMutex == NULL_PTR &&
+ args->DestroyMutex == NULL_PTR &&
+ args->LockMutex == NULL_PTR &&
+ args->UnlockMutex == NULL_PTR
+ )
+ {
+ // Can we use our own mutex functions?
+ if (args->flags & CKF_OS_LOCKING_OK)
+ {
+ // Use our own mutex functions.
+ MutexFactory::i()->setCreateMutex(OSCreateMutex);
+ MutexFactory::i()->setDestroyMutex(OSDestroyMutex);
+ MutexFactory::i()->setLockMutex(OSLockMutex);
+ MutexFactory::i()->setUnlockMutex(OSUnlockMutex);
+ MutexFactory::i()->enable();
+ }
+ else
+ {
+ // The external application is not using threading
+ MutexFactory::i()->disable();
+ }
+ }
+ else
+ {
+ // We must have all mutex functions
+ if
+ (
+ args->CreateMutex == NULL_PTR ||
+ args->DestroyMutex == NULL_PTR ||
+ args->LockMutex == NULL_PTR ||
+ args->UnlockMutex == NULL_PTR
+ )
+ {
+ ERROR_MSG("Not all mutex functions are supplied");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ // We could use our own mutex functions if the flag is set,
+ // but we use the external functions in both cases.
+
+ // Load the external mutex functions
+ MutexFactory::i()->setCreateMutex(args->CreateMutex);
+ MutexFactory::i()->setDestroyMutex(args->DestroyMutex);
+ MutexFactory::i()->setLockMutex(args->LockMutex);
+ MutexFactory::i()->setUnlockMutex(args->UnlockMutex);
+ MutexFactory::i()->enable();
+ }
+ }
+ else
+ {
+ // No concurrent access by multiple threads
+ MutexFactory::i()->disable();
+ }
+
+ // Initiate SecureMemoryRegistry
+ if (SecureMemoryRegistry::i() == NULL)
+ {
+ ERROR_MSG("Could not load the SecureMemoryRegistry");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Build the CryptoFactory
+ if (CryptoFactory::i() == NULL)
+ {
+ ERROR_MSG("Could not load the CryptoFactory");
+ return CKR_GENERAL_ERROR;
+ }
+
+#ifdef WITH_FIPS
+ // Check the FIPS status
+ if (!CryptoFactory::i()->getFipsSelfTestStatus())
+ {
+ ERROR_MSG("The FIPS self test failed");
+ return CKR_FIPS_SELF_TEST_FAILED;
+ }
+#endif
+
+ // (Re)load the configuration
+ if (!Configuration::i()->reload(SimpleConfigLoader::i()))
+ {
+ ERROR_MSG("Could not load the configuration");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Configure the log level
+ if (!setLogLevel(Configuration::i()->getString("log.level", DEFAULT_LOG_LEVEL)))
+ {
+ ERROR_MSG("Could not set the log level");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Configure object store storage backend used by all tokens.
+ if (!ObjectStoreToken::selectBackend(Configuration::i()->getString("objectstore.backend", DEFAULT_OBJECTSTORE_BACKEND)))
+ {
+ ERROR_MSG("Could not set the storage backend");
+ return CKR_GENERAL_ERROR;
+ }
+
+ sessionObjectStore = new SessionObjectStore();
+
+ // Load the object store
+ objectStore = new ObjectStore(Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR));
+ if (!objectStore->isValid())
+ {
+ WARNING_MSG("Could not load the object store");
+ delete objectStore;
+ objectStore = NULL;
+ delete sessionObjectStore;
+ sessionObjectStore = NULL;
+ return CKR_GENERAL_ERROR;
+ }
+
+ isRemovable = Configuration::i()->getBool("slots.removable", false);
+
+ // Load the slot manager
+ slotManager = new SlotManager(objectStore);
+
+ // Load the session manager
+ sessionManager = new SessionManager();
+
+ // Load the handle manager
+ handleManager = new HandleManager();
+
+ // Set the state to initialised
+ isInitialised = true;
+
+ return CKR_OK;
+}
+
+// PKCS #11 finalisation function
+CK_RV SoftHSM::C_Finalize(CK_VOID_PTR pReserved)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Must be set to NULL_PTR in this version of PKCS#11
+ if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ if (handleManager != NULL) delete handleManager;
+ handleManager = NULL;
+ if (sessionManager != NULL) delete sessionManager;
+ sessionManager = NULL;
+ if (slotManager != NULL) delete slotManager;
+ slotManager = NULL;
+ if (objectStore != NULL) delete objectStore;
+ objectStore = NULL;
+ if (sessionObjectStore != NULL) delete sessionObjectStore;
+ sessionObjectStore = NULL;
+ CryptoFactory::reset();
+ SecureMemoryRegistry::reset();
+
+ isInitialised = false;
+
+ SoftHSM::reset();
+ return CKR_OK;
+}
+
+// Return information about the PKCS #11 module
+CK_RV SoftHSM::C_GetInfo(CK_INFO_PTR pInfo)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
+ pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
+ memset(pInfo->manufacturerID, ' ', 32);
+ memcpy(pInfo->manufacturerID, "SoftHSM", 7);
+ pInfo->flags = 0;
+ memset(pInfo->libraryDescription, ' ', 32);
+#ifdef WITH_FIPS
+ memcpy(pInfo->libraryDescription, "Implementation of PKCS11+FIPS", 29);
+#else
+ memcpy(pInfo->libraryDescription, "Implementation of PKCS11", 24);
+#endif
+ pInfo->libraryVersion.major = VERSION_MAJOR;
+ pInfo->libraryVersion.minor = VERSION_MINOR;
+
+ return CKR_OK;
+}
+
+// Return a list of available slots
+CK_RV SoftHSM::C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ return slotManager->getSlotList(objectStore, tokenPresent, pSlotList, pulCount);
+}
+
+// Return information about a slot
+CK_RV SoftHSM::C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
+{
+ CK_RV rv;
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ rv = slot->getSlotInfo(pInfo);
+ if (rv != CKR_OK) {
+ return rv;
+ }
+
+ if (isRemovable) {
+ pInfo->flags |= CKF_REMOVABLE_DEVICE;
+ }
+
+ return CKR_OK;
+}
+
+// Return information about a token in a slot
+CK_RV SoftHSM::C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ Token* token = slot->getToken();
+ if (token == NULL)
+ {
+ return CKR_TOKEN_NOT_PRESENT;
+ }
+
+ return token->getTokenInfo(pInfo);
+}
+
+// Return the list of supported mechanisms for a given slot
+CK_RV SoftHSM::C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
+{
+ // A list with the supported mechanisms
+ CK_ULONG nrSupportedMechanisms = 61;
+#ifdef WITH_ECC
+ nrSupportedMechanisms += 3;
+#endif
+#ifdef WITH_FIPS
+ nrSupportedMechanisms -= 9;
+#endif
+#ifdef WITH_GOST
+ nrSupportedMechanisms += 5;
+#endif
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ nrSupportedMechanisms += 1;
+#endif
+#ifdef WITH_RAW_PSS
+ nrSupportedMechanisms += 1; // CKM_RSA_PKCS_PSS
+#endif
+#ifdef WITH_AES_GCM
+ nrSupportedMechanisms += 1;
+#endif
+
+ CK_MECHANISM_TYPE supportedMechanisms[] =
+ {
+#ifndef WITH_FIPS
+ CKM_MD5,
+#endif
+ CKM_SHA_1,
+ CKM_SHA224,
+ CKM_SHA256,
+ CKM_SHA384,
+ CKM_SHA512,
+#ifndef WITH_FIPS
+ CKM_MD5_HMAC,
+#endif
+ CKM_SHA_1_HMAC,
+ CKM_SHA224_HMAC,
+ CKM_SHA256_HMAC,
+ CKM_SHA384_HMAC,
+ CKM_SHA512_HMAC,
+ CKM_RSA_PKCS_KEY_PAIR_GEN,
+ CKM_RSA_PKCS,
+ CKM_RSA_X_509,
+#ifndef WITH_FIPS
+ CKM_MD5_RSA_PKCS,
+#endif
+ CKM_SHA1_RSA_PKCS,
+ CKM_RSA_PKCS_OAEP,
+ CKM_SHA224_RSA_PKCS,
+ CKM_SHA256_RSA_PKCS,
+ CKM_SHA384_RSA_PKCS,
+ CKM_SHA512_RSA_PKCS,
+#ifdef WITH_RAW_PSS
+ CKM_RSA_PKCS_PSS,
+#endif
+ CKM_SHA1_RSA_PKCS_PSS,
+ CKM_SHA224_RSA_PKCS_PSS,
+ CKM_SHA256_RSA_PKCS_PSS,
+ CKM_SHA384_RSA_PKCS_PSS,
+ CKM_SHA512_RSA_PKCS_PSS,
+#ifndef WITH_FIPS
+ CKM_DES_KEY_GEN,
+#endif
+ CKM_DES2_KEY_GEN,
+ CKM_DES3_KEY_GEN,
+#ifndef WITH_FIPS
+ CKM_DES_ECB,
+ CKM_DES_CBC,
+ CKM_DES_CBC_PAD,
+ CKM_DES_ECB_ENCRYPT_DATA,
+ CKM_DES_CBC_ENCRYPT_DATA,
+#endif
+ CKM_DES3_ECB,
+ CKM_DES3_CBC,
+ CKM_DES3_CBC_PAD,
+ CKM_DES3_ECB_ENCRYPT_DATA,
+ CKM_DES3_CBC_ENCRYPT_DATA,
+ CKM_DES3_CMAC,
+ CKM_AES_KEY_GEN,
+ CKM_AES_ECB,
+ CKM_AES_CBC,
+ CKM_AES_CBC_PAD,
+ CKM_AES_CTR,
+#ifdef WITH_AES_GCM
+ CKM_AES_GCM,
+#endif
+ CKM_AES_KEY_WRAP,
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ CKM_AES_KEY_WRAP_PAD,
+#endif
+ CKM_AES_ECB_ENCRYPT_DATA,
+ CKM_AES_CBC_ENCRYPT_DATA,
+ CKM_AES_CMAC,
+ CKM_DSA_PARAMETER_GEN,
+ CKM_DSA_KEY_PAIR_GEN,
+ CKM_DSA,
+ CKM_DSA_SHA1,
+ CKM_DSA_SHA224,
+ CKM_DSA_SHA256,
+ CKM_DSA_SHA384,
+ CKM_DSA_SHA512,
+ CKM_DH_PKCS_KEY_PAIR_GEN,
+ CKM_DH_PKCS_PARAMETER_GEN,
+ CKM_DH_PKCS_DERIVE,
+#ifdef WITH_ECC
+ CKM_EC_KEY_PAIR_GEN,
+ CKM_ECDSA,
+ CKM_ECDH1_DERIVE,
+#endif
+#ifdef WITH_GOST
+ CKM_GOSTR3411,
+ CKM_GOSTR3411_HMAC,
+ CKM_GOSTR3410_KEY_PAIR_GEN,
+ CKM_GOSTR3410,
+ CKM_GOSTR3410_WITH_GOSTR3411
+#endif
+ };
+
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (pulCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ if (pMechanismList == NULL_PTR)
+ {
+ *pulCount = nrSupportedMechanisms;
+
+ return CKR_OK;
+ }
+
+ if (*pulCount < nrSupportedMechanisms)
+ {
+ *pulCount = nrSupportedMechanisms;
+
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ *pulCount = nrSupportedMechanisms;
+
+ for (CK_ULONG i = 0; i < nrSupportedMechanisms; i ++)
+ {
+ pMechanismList[i] = supportedMechanisms[i];
+ }
+
+ return CKR_OK;
+}
+
+// Return more information about a mechanism for a given slot
+CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
+{
+ unsigned long rsaMinSize, rsaMaxSize;
+ unsigned long dsaMinSize, dsaMaxSize;
+ unsigned long dhMinSize, dhMaxSize;
+#ifdef WITH_ECC
+ unsigned long ecdsaMinSize, ecdsaMaxSize;
+ unsigned long ecdhMinSize, ecdhMaxSize;
+#endif
+
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
+ if (rsa != NULL)
+ {
+ rsaMinSize = rsa->getMinKeySize();
+ rsaMaxSize = rsa->getMaxKeySize();
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+
+ AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
+ if (dsa != NULL)
+ {
+ dsaMinSize = dsa->getMinKeySize();
+ // Limitation in PKCS#11
+ if (dsaMinSize < 512)
+ {
+ dsaMinSize = 512;
+ }
+
+ dsaMaxSize = dsa->getMaxKeySize();
+ // Limitation in PKCS#11
+ if (dsaMaxSize > 1024)
+ {
+ dsaMaxSize = 1024;
+ }
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+
+ AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
+ if (dh != NULL)
+ {
+ dhMinSize = dh->getMinKeySize();
+ dhMaxSize = dh->getMaxKeySize();
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+
+#ifdef WITH_ECC
+ AsymmetricAlgorithm* ecdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
+ if (ecdsa != NULL)
+ {
+ ecdsaMinSize = ecdsa->getMinKeySize();
+ ecdsaMaxSize = ecdsa->getMaxKeySize();
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdsa);
+
+ AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
+ if (ecdh != NULL)
+ {
+ ecdhMinSize = ecdh->getMinKeySize();
+ ecdhMaxSize = ecdh->getMaxKeySize();
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
+#endif
+
+ switch (type)
+ {
+#ifndef WITH_FIPS
+ case CKM_MD5:
+#endif
+ case CKM_SHA_1:
+ case CKM_SHA224:
+ case CKM_SHA256:
+ case CKM_SHA384:
+ case CKM_SHA512:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_DIGEST;
+ break;
+#ifndef WITH_FIPS
+ case CKM_MD5_HMAC:
+ pInfo->ulMinKeySize = 16;
+ pInfo->ulMaxKeySize = 512;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+#endif
+ case CKM_SHA_1_HMAC:
+ pInfo->ulMinKeySize = 20;
+ pInfo->ulMaxKeySize = 512;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_SHA224_HMAC:
+ pInfo->ulMinKeySize = 28;
+ pInfo->ulMaxKeySize = 512;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_SHA256_HMAC:
+ pInfo->ulMinKeySize = 32;
+ pInfo->ulMaxKeySize = 512;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_SHA384_HMAC:
+ pInfo->ulMinKeySize = 48;
+ pInfo->ulMaxKeySize = 512;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_SHA512_HMAC:
+ pInfo->ulMinKeySize = 64;
+ pInfo->ulMaxKeySize = 512;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_GENERATE_KEY_PAIR;
+ break;
+ case CKM_RSA_PKCS:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
+ break;
+ case CKM_RSA_X_509:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+#ifndef WITH_FIPS
+ case CKM_MD5_RSA_PKCS:
+#endif
+ case CKM_SHA1_RSA_PKCS:
+ case CKM_SHA224_RSA_PKCS:
+ case CKM_SHA256_RSA_PKCS:
+ case CKM_SHA384_RSA_PKCS:
+ case CKM_SHA512_RSA_PKCS:
+#ifdef WITH_RAW_PSS
+ case CKM_RSA_PKCS_PSS:
+#endif
+ case CKM_SHA1_RSA_PKCS_PSS:
+ case CKM_SHA224_RSA_PKCS_PSS:
+ case CKM_SHA256_RSA_PKCS_PSS:
+ case CKM_SHA384_RSA_PKCS_PSS:
+ case CKM_SHA512_RSA_PKCS_PSS:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_RSA_PKCS_OAEP:
+ pInfo->ulMinKeySize = rsaMinSize;
+ pInfo->ulMaxKeySize = rsaMaxSize;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
+ break;
+#ifndef WITH_FIPS
+ case CKM_DES_KEY_GEN:
+#endif
+ case CKM_DES2_KEY_GEN:
+ case CKM_DES3_KEY_GEN:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_GENERATE;
+ break;
+#ifndef WITH_FIPS
+ case CKM_DES_ECB:
+ case CKM_DES_CBC:
+ case CKM_DES_CBC_PAD:
+#endif
+ case CKM_DES3_ECB:
+ case CKM_DES3_CBC:
+ case CKM_DES3_CBC_PAD:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+ case CKM_DES3_CMAC:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_AES_KEY_GEN:
+ pInfo->ulMinKeySize = 16;
+ pInfo->ulMaxKeySize = 32;
+ pInfo->flags = CKF_GENERATE;
+ break;
+ case CKM_AES_ECB:
+ case CKM_AES_CBC:
+ case CKM_AES_CBC_PAD:
+ case CKM_AES_CTR:
+#ifdef WITH_AES_GCM
+ case CKM_AES_GCM:
+#endif
+ pInfo->ulMinKeySize = 16;
+ pInfo->ulMaxKeySize = 32;
+ pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
+ break;
+ case CKM_AES_KEY_WRAP:
+ pInfo->ulMinKeySize = 16;
+ pInfo->ulMaxKeySize = 0x80000000;
+ pInfo->flags = CKF_WRAP | CKF_UNWRAP;
+ break;
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ case CKM_AES_KEY_WRAP_PAD:
+ pInfo->ulMinKeySize = 1;
+ pInfo->ulMaxKeySize = 0x80000000;
+ pInfo->flags = CKF_WRAP | CKF_UNWRAP;
+ break;
+#endif
+#ifndef WITH_FIPS
+ case CKM_DES_ECB_ENCRYPT_DATA:
+ case CKM_DES_CBC_ENCRYPT_DATA:
+#endif
+ case CKM_DES3_ECB_ENCRYPT_DATA:
+ case CKM_DES3_CBC_ENCRYPT_DATA:
+ case CKM_AES_ECB_ENCRYPT_DATA:
+ case CKM_AES_CBC_ENCRYPT_DATA:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_DERIVE;
+ break;
+ case CKM_AES_CMAC:
+ pInfo->ulMinKeySize = 16;
+ pInfo->ulMaxKeySize = 32;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_DSA_PARAMETER_GEN:
+ pInfo->ulMinKeySize = dsaMinSize;
+ pInfo->ulMaxKeySize = dsaMaxSize;
+ pInfo->flags = CKF_GENERATE;
+ break;
+ case CKM_DSA_KEY_PAIR_GEN:
+ pInfo->ulMinKeySize = dsaMinSize;
+ pInfo->ulMaxKeySize = dsaMaxSize;
+ pInfo->flags = CKF_GENERATE_KEY_PAIR;
+ break;
+ case CKM_DSA:
+ case CKM_DSA_SHA1:
+ case CKM_DSA_SHA224:
+ case CKM_DSA_SHA256:
+ case CKM_DSA_SHA384:
+ case CKM_DSA_SHA512:
+ pInfo->ulMinKeySize = dsaMinSize;
+ pInfo->ulMaxKeySize = dsaMaxSize;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_DH_PKCS_KEY_PAIR_GEN:
+ pInfo->ulMinKeySize = dhMinSize;
+ pInfo->ulMaxKeySize = dhMaxSize;
+ pInfo->flags = CKF_GENERATE_KEY_PAIR;
+ break;
+ case CKM_DH_PKCS_PARAMETER_GEN:
+ pInfo->ulMinKeySize = dhMinSize;
+ pInfo->ulMaxKeySize = dhMaxSize;
+ pInfo->flags = CKF_GENERATE;
+ break;
+ case CKM_DH_PKCS_DERIVE:
+ pInfo->ulMinKeySize = dhMinSize;
+ pInfo->ulMaxKeySize = dhMaxSize;
+ pInfo->flags = CKF_DERIVE;
+ break;
+#ifdef WITH_ECC
+ case CKM_EC_KEY_PAIR_GEN:
+ pInfo->ulMinKeySize = ecdsaMinSize;
+ pInfo->ulMaxKeySize = ecdsaMaxSize;
+#define CKF_EC_COMMOM (CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS)
+ pInfo->flags = CKF_GENERATE_KEY_PAIR | CKF_EC_COMMOM;
+ break;
+ case CKM_ECDSA:
+ pInfo->ulMinKeySize = ecdsaMinSize;
+ pInfo->ulMaxKeySize = ecdsaMaxSize;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_EC_COMMOM;
+ break;
+ case CKM_ECDH1_DERIVE:
+ pInfo->ulMinKeySize = ecdhMinSize;
+ pInfo->ulMaxKeySize = ecdhMaxSize;
+ pInfo->flags = CKF_DERIVE;
+ break;
+#endif
+#ifdef WITH_GOST
+ case CKM_GOSTR3411:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_DIGEST;
+ break;
+ case CKM_GOSTR3411_HMAC:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 32;
+ pInfo->ulMaxKeySize = 512;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_GOSTR3410_KEY_PAIR_GEN:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_GENERATE_KEY_PAIR;
+ break;
+ case CKM_GOSTR3410:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+ case CKM_GOSTR3410_WITH_GOSTR3411:
+ // Key size is not in use
+ pInfo->ulMinKeySize = 0;
+ pInfo->ulMaxKeySize = 0;
+ pInfo->flags = CKF_SIGN | CKF_VERIFY;
+ break;
+#endif
+ default:
+ DEBUG_MSG("The selected mechanism is not supported");
+ return CKR_MECHANISM_INVALID;
+ break;
+ }
+
+ return CKR_OK;
+}
+
+// Initialise the token in the specified slot
+CK_RV SoftHSM::C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL)
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ // Check if any session is open with this token.
+ if (sessionManager->haveSession(slotID))
+ {
+ return CKR_SESSION_EXISTS;
+ }
+
+ // Check the PIN
+ if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_INCORRECT;
+
+ ByteString soPIN(pPin, ulPinLen);
+
+ return slot->initToken(soPIN, pLabel);
+}
+
+// Initialise the user PIN
+CK_RV SoftHSM::C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // The SO must be logged in
+ if (session->getState() != CKS_RW_SO_FUNCTIONS) return CKR_USER_NOT_LOGGED_IN;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the PIN
+ if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
+
+ ByteString userPIN(pPin, ulPinLen);
+
+ return token->initUserPIN(userPIN);
+}
+
+// Change the PIN
+CK_RV SoftHSM::C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
+{
+ CK_RV rv = CKR_OK;
+
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check the new PINs
+ if (pOldPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pNewPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (ulNewLen < MIN_PIN_LEN || ulNewLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
+
+ ByteString oldPIN(pOldPin, ulOldLen);
+ ByteString newPIN(pNewPin, ulNewLen);
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ switch (session->getState())
+ {
+ case CKS_RW_PUBLIC_SESSION:
+ case CKS_RW_USER_FUNCTIONS:
+ rv = token->setUserPIN(oldPIN, newPIN);
+ break;
+ case CKS_RW_SO_FUNCTIONS:
+ rv = token->setSOPIN(oldPIN, newPIN);
+ break;
+ default:
+ return CKR_SESSION_READ_ONLY;
+ }
+
+ return rv;
+}
+
+// Open a new session to the specified slot
+CK_RV SoftHSM::C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ Slot* slot = slotManager->getSlot(slotID);
+
+ CK_RV rv = sessionManager->openSession(slot, flags, pApplication, notify, phSession);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Get a pointer to the session object and store it in the handle manager.
+ Session* session = sessionManager->getSession(*phSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+ *phSession = handleManager->addSession(slotID,session);
+
+ return CKR_OK;
+}
+
+// Close the given session
+CK_RV SoftHSM::C_CloseSession(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Tell the handle manager the session has been closed.
+ handleManager->sessionClosed(hSession);
+
+
+ // Tell the session object store that the session has closed.
+ sessionObjectStore->sessionClosed(hSession);
+
+ // Tell the session manager the session has been closed.
+ return sessionManager->closeSession(session->getHandle());
+}
+
+// Close all open sessions
+CK_RV SoftHSM::C_CloseAllSessions(CK_SLOT_ID slotID)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the slot
+ Slot* slot = slotManager->getSlot(slotID);
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+
+ // Get the token
+ Token* token = slot->getToken();
+ if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
+
+ // Tell the handle manager all sessions were closed for the given slotID.
+ // The handle manager should then remove all session and object handles for this slot.
+ handleManager->allSessionsClosed(slotID);
+
+ // Tell the session object store that all sessions were closed for the given slotID.
+ // The session object store should then remove all session objects for this slot.
+ sessionObjectStore->allSessionsClosed(slotID);
+
+ // Finally tell the session manager tho close all sessions for the given slot.
+ // This will also trigger a logout on the associated token to occur.
+ return sessionManager->closeAllSessions(slot);
+}
+
+// Retrieve information about the specified session
+CK_RV SoftHSM::C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return session->getInfo(pInfo);
+}
+
+// Determine the state of a running operation in a session
+CK_RV SoftHSM::C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG_PTR /*pulOperationStateLen*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Set the operation sate in a session
+CK_RV SoftHSM::C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG /*ulOperationStateLen*/, CK_OBJECT_HANDLE /*hEncryptionKey*/, CK_OBJECT_HANDLE /*hAuthenticationKey*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Login on the token in the specified session
+CK_RV SoftHSM::C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ CK_RV rv = CKR_OK;
+
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the PIN
+ if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ ByteString pin(pPin, ulPinLen);
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ switch (userType)
+ {
+ case CKU_SO:
+ // There cannot exist a R/O session on this slot
+ if (sessionManager->haveROSession(session->getSlot()->getSlotID())) return CKR_SESSION_READ_ONLY_EXISTS;
+
+ // Login
+ rv = token->loginSO(pin);
+ break;
+ case CKU_USER:
+ // Login
+ rv = token->loginUser(pin);
+ break;
+ case CKU_CONTEXT_SPECIFIC:
+ // Check if re-authentication is required
+ if (!session->getReAuthentication()) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // Re-authenticate
+ rv = token->reAuthenticate(pin);
+ if (rv == CKR_OK) session->setReAuthentication(false);
+ break;
+ default:
+ return CKR_USER_TYPE_INVALID;
+ }
+
+ return rv;
+}
+
+// Log out of the token in the specified session
+CK_RV SoftHSM::C_Logout(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Logout
+ token->logout();
+
+ // [PKCS#11 v2.40, C_Logout] When logout is successful...
+ // a. Any of the application's handles to private objects become invalid.
+ // b. Even if a user is later logged back into the token those handles remain invalid.
+ // c. All private session objects from sessions belonging to the application are destroyed.
+
+ // Have the handle manager remove all handles pointing to private objects for this slot.
+ CK_SLOT_ID slotID = session->getSlot()->getSlotID();
+ handleManager->tokenLoggedOut(slotID);
+ sessionObjectStore->tokenLoggedOut(slotID);
+
+ return CKR_OK;
+}
+
+// Create a new object on the token in the specified session using the given attribute template
+CK_RV SoftHSM::C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
+{
+ return this->CreateObject(hSession,pTemplate,ulCount,phObject,OBJECT_OP_CREATE);
+}
+
+// Create a copy of the object with the specified handle
+CK_RV SoftHSM::C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phNewObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ *phNewObject = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the slot
+ Slot* slot = session->getSlot();
+ if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Check the object handle.
+ OSObject *object = (OSObject *)handleManager->getObject(hObject);
+ if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL wasOnToken = object->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL wasPrivate = object->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), wasOnToken, wasPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if the object is copyable
+ CK_BBOOL isCopyable = object->getBooleanValue(CKA_COPYABLE, true);
+ if (!isCopyable) return CKR_ACTION_PROHIBITED;
+
+ // Extract critical information from the template
+ CK_BBOOL isOnToken = wasOnToken;
+ CK_BBOOL isPrivate = wasPrivate;
+
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ if ((pTemplate[i].type == CKA_TOKEN) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
+ {
+ isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
+ continue;
+ }
+ if ((pTemplate[i].type == CKA_PRIVATE) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
+ {
+ isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
+ continue;
+ }
+ }
+
+ // Check privacy does not downgrade
+ if (wasPrivate && !isPrivate) return CKR_TEMPLATE_INCONSISTENT;
+
+ // Check write user credentials
+ rv = haveWrite(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Create the object in session or on the token
+ OSObject *newobject = NULL_PTR;
+ if (isOnToken)
+ {
+ newobject = (OSObject*) token->createObject();
+ }
+ else
+ {
+ newobject = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
+ }
+ if (newobject == NULL) return CKR_GENERAL_ERROR;
+
+ // Copy attributes from object class (CKA_CLASS=0 so the first)
+ if (!newobject->startTransaction())
+ {
+ newobject->destroyObject();
+ return CKR_FUNCTION_FAILED;
+ }
+
+ CK_ATTRIBUTE_TYPE attrType = CKA_CLASS;
+ do
+ {
+ if (!object->attributeExists(attrType))
+ {
+ rv = CKR_FUNCTION_FAILED;
+ break;
+ }
+
+ OSAttribute attr = object->getAttribute(attrType);
+
+ // Upgrade privacy has to encrypt byte strings
+ if (!wasPrivate && isPrivate &&
+ attr.isByteStringAttribute() &&
+ attr.getByteStringValue().size() != 0)
+ {
+ ByteString value;
+ if (!token->encrypt(attr.getByteStringValue(), value) ||
+ !newobject->setAttribute(attrType, value))
+ {
+ rv = CKR_FUNCTION_FAILED;
+ break;
+ }
+ }
+ else
+ {
+ if (!newobject->setAttribute(attrType, attr))
+ {
+ rv = CKR_FUNCTION_FAILED;
+ break;
+ }
+ }
+ attrType = object->nextAttributeType(attrType);
+ }
+ while (attrType != CKA_CLASS);
+
+ if (rv != CKR_OK)
+ {
+ newobject->abortTransaction();
+ }
+ else if (!newobject->commitTransaction())
+ {
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ if (rv != CKR_OK)
+ {
+ newobject->destroyObject();
+ return rv;
+ }
+
+ // Get the new P11 object
+ P11Object* newp11object = NULL;
+ rv = newP11Object(newobject,&newp11object);
+ if (rv != CKR_OK)
+ {
+ newobject->destroyObject();
+ return rv;
+ }
+
+ // Apply the template
+ rv = newp11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate, ulCount, OBJECT_OP_COPY);
+ delete newp11object;
+
+ if (rv != CKR_OK)
+ {
+ newobject->destroyObject();
+ return rv;
+ }
+
+ // Set handle
+ if (isOnToken)
+ {
+ *phNewObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, newobject);
+ }
+ else
+ {
+ *phNewObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, newobject);
+ }
+
+ return CKR_OK;
+}
+
+// Destroy the specified object
+CK_RV SoftHSM::C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Check the object handle.
+ OSObject *object = (OSObject *)handleManager->getObject(hObject);
+ if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check user credentials
+ CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Check if the object is destroyable
+ CK_BBOOL isDestroyable = object->getBooleanValue(CKA_DESTROYABLE, true);
+ if (!isDestroyable) return CKR_ACTION_PROHIBITED;
+
+ // Tell the handleManager to forget about the object.
+ handleManager->destroyObject(hObject);
+
+ // Destroy the object
+ if (!object->destroyObject())
+ return CKR_FUNCTION_FAILED;
+
+ return CKR_OK;
+}
+
+// Determine the size of the specified object
+CK_RV SoftHSM::C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pulSize == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Check the object handle.
+ OSObject *object = (OSObject *)handleManager->getObject(hObject);
+ if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ *pulSize = CK_UNAVAILABLE_INFORMATION;
+
+ return CKR_OK;
+}
+
+// Retrieve the specified attributes for the given object
+CK_RV SoftHSM::C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the object handle.
+ OSObject *object = (OSObject *)handleManager->getObject(hObject);
+ if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
+ // so we use CKR_GENERAL_ERROR.
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Wrap a P11Object around the OSObject so we can access the attributes in the
+ // context of the object in which it is defined.
+ P11Object* p11object = NULL;
+ rv = newP11Object(object,&p11object);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Ask the P11Object to fill the template with attribute values.
+ rv = p11object->loadTemplate(token, pTemplate,ulCount);
+ delete p11object;
+ return rv;
+}
+
+// Change or set the value of the specified attributes on the specified object
+CK_RV SoftHSM::C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the object handle.
+ OSObject *object = (OSObject *)handleManager->getObject(hObject);
+ if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check user credentials
+ CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Check if the object is modifiable
+ CK_BBOOL isModifiable = object->getBooleanValue(CKA_MODIFIABLE, true);
+ if (!isModifiable) return CKR_ACTION_PROHIBITED;
+
+ // Wrap a P11Object around the OSObject so we can access the attributes in the
+ // context of the object in which it is defined.
+ P11Object* p11object = NULL;
+ rv = newP11Object(object,&p11object);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Ask the P11Object to save the template with attribute values.
+ rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate,ulCount,OBJECT_OP_SET);
+ delete p11object;
+ return rv;
+}
+
+// Initialise object search in the specified session using the specified attribute template as search parameters
+CK_RV SoftHSM::C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the slot
+ Slot* slot = session->getSlot();
+ if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Determine whether we have a public session or not.
+ bool isPublicSession;
+ switch (session->getState()) {
+ case CKS_RO_USER_FUNCTIONS:
+ case CKS_RW_USER_FUNCTIONS:
+ isPublicSession = false;
+ break;
+ default:
+ isPublicSession = true;
+ }
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ session->setOpType(SESSION_OP_FIND);
+ FindOperation *findOp = FindOperation::create();
+
+ // Check if we are out of memory
+ if (findOp == NULL_PTR) return CKR_HOST_MEMORY;
+
+ std::set<OSObject*> allObjects;
+ token->getObjects(allObjects);
+ sessionObjectStore->getObjects(slot->getSlotID(),allObjects);
+
+ std::set<CK_OBJECT_HANDLE> handles;
+ std::set<OSObject*>::iterator it;
+ for (it=allObjects.begin(); it != allObjects.end(); ++it)
+ {
+ // Refresh object and check if it is valid
+ if (!(*it)->isValid()) {
+ DEBUG_MSG("Object is not valid, skipping");
+ continue;
+ }
+
+ // Determine if the object has CKA_PRIVATE set to CK_TRUE
+ bool isPrivateObject = (*it)->getBooleanValue(CKA_PRIVATE, true);
+
+ // If the object is private, and we are in a public session then skip it !
+ if (isPublicSession && isPrivateObject)
+ continue; // skip object
+
+ // Perform the actual attribute matching.
+ bool bAttrMatch = true; // We let an empty template match everything.
+ for (CK_ULONG i=0; i<ulCount; ++i)
+ {
+ bAttrMatch = false;
+
+ if (!(*it)->attributeExists(pTemplate[i].type))
+ break;
+
+ OSAttribute attr = (*it)->getAttribute(pTemplate[i].type);
+
+ if (attr.isBooleanAttribute())
+ {
+ if (sizeof(CK_BBOOL) != pTemplate[i].ulValueLen)
+ break;
+ bool bTemplateValue = (*(CK_BBOOL*)pTemplate[i].pValue == CK_TRUE);
+ if (attr.getBooleanValue() != bTemplateValue)
+ break;
+ }
+ else
+ {
+ if (attr.isUnsignedLongAttribute())
+ {
+ if (sizeof(CK_ULONG) != pTemplate[i].ulValueLen)
+ break;
+ CK_ULONG ulTemplateValue = *(CK_ULONG_PTR)pTemplate[i].pValue;
+ if (attr.getUnsignedLongValue() != ulTemplateValue)
+ break;
+ }
+ else
+ {
+ if (attr.isByteStringAttribute())
+ {
+ ByteString bsAttrValue;
+ if (isPrivateObject && attr.getByteStringValue().size() != 0)
+ {
+ if (!token->decrypt(attr.getByteStringValue(), bsAttrValue))
+ {
+ delete findOp;
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else
+ bsAttrValue = attr.getByteStringValue();
+
+ if (bsAttrValue.size() != pTemplate[i].ulValueLen)
+ break;
+ if (pTemplate[i].ulValueLen != 0)
+ {
+ ByteString bsTemplateValue((const unsigned char*)pTemplate[i].pValue, pTemplate[i].ulValueLen);
+ if (bsAttrValue != bsTemplateValue)
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+ // The attribute matched !
+ bAttrMatch = true;
+ }
+
+ if (bAttrMatch)
+ {
+ CK_SLOT_ID slotID = slot->getSlotID();
+ bool isOnToken = (*it)->getBooleanValue(CKA_TOKEN, false);
+ bool isPrivate = (*it)->getBooleanValue(CKA_PRIVATE, true);
+ // Create an object handle for every returned object.
+ CK_OBJECT_HANDLE hObject;
+ if (isOnToken)
+ hObject = handleManager->addTokenObject(slotID,isPrivate,*it);
+ else
+ hObject = handleManager->addSessionObject(slotID,hSession,isPrivate,*it);
+ if (hObject == CK_INVALID_HANDLE)
+ {
+ delete findOp;
+ return CKR_GENERAL_ERROR;
+ }
+ handles.insert(hObject);
+ }
+ }
+
+ // Storing the object handles for the find will protect the library
+ // whenever a stale object handle is used to access the library.
+ findOp->setHandles(handles);
+
+ session->setFindOp(findOp);
+
+ return CKR_OK;
+}
+
+// Continue the search for objects in the specified session
+CK_RV SoftHSM::C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+ if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulObjectCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // return the object handles that have been added to the find operation.
+ FindOperation *findOp = session->getFindOp();
+ if (findOp == NULL) return CKR_GENERAL_ERROR;
+
+ // Ask the find operation to retrieve the object handles
+ *pulObjectCount = findOp->retrieveHandles(phObject,ulMaxObjectCount);
+
+ // Erase the object handles from the find operation.
+ findOp->eraseHandles(0,*pulObjectCount);
+
+ return CKR_OK;
+}
+
+// Finish searching for objects
+CK_RV SoftHSM::C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Encrypt*/Decrypt*() is for Symmetrical ciphers too
+static bool isSymMechanism(CK_MECHANISM_PTR pMechanism)
+{
+ if (pMechanism == NULL_PTR) return false;
+
+ switch(pMechanism->mechanism) {
+ case CKM_DES_ECB:
+ case CKM_DES_CBC:
+ case CKM_DES_CBC_PAD:
+ case CKM_DES3_ECB:
+ case CKM_DES3_CBC:
+ case CKM_DES3_CBC_PAD:
+ case CKM_AES_ECB:
+ case CKM_AES_CBC:
+ case CKM_AES_CBC_PAD:
+ case CKM_AES_CTR:
+ case CKM_AES_GCM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// SymAlgorithm version of C_EncryptInit
+CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for encryption
+ if (!key->getBooleanValue(CKA_ENCRYPT, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the key
+ if (!isMechanismPermitted(key, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Get the symmetric algorithm matching the mechanism
+ SymAlgo::Type algo = SymAlgo::Unknown;
+ SymMode::Type mode = SymMode::Unknown;
+ bool padding = false;
+ ByteString iv;
+ size_t bb = 8;
+ size_t counterBits = 0;
+ ByteString aad;
+ size_t tagBytes = 0;
+ switch(pMechanism->mechanism) {
+#ifndef WITH_FIPS
+ case CKM_DES_ECB:
+ algo = SymAlgo::DES;
+ mode = SymMode::ECB;
+ bb = 7;
+ break;
+ case CKM_DES_CBC:
+ algo = SymAlgo::DES;
+ mode = SymMode::CBC;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ bb = 7;
+ break;
+ case CKM_DES_CBC_PAD:
+ algo = SymAlgo::DES;
+ mode = SymMode::CBC;
+ padding = true;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ bb = 7;
+ break;
+#endif
+ case CKM_DES3_ECB:
+ algo = SymAlgo::DES3;
+ mode = SymMode::ECB;
+ bb = 7;
+ break;
+ case CKM_DES3_CBC:
+ algo = SymAlgo::DES3;
+ mode = SymMode::CBC;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ bb = 7;
+ break;
+ case CKM_DES3_CBC_PAD:
+ algo = SymAlgo::DES3;
+ mode = SymMode::CBC;
+ padding = true;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ bb = 7;
+ break;
+ case CKM_AES_ECB:
+ algo = SymAlgo::AES;
+ mode = SymMode::ECB;
+ break;
+ case CKM_AES_CBC:
+ algo = SymAlgo::AES;
+ mode = SymMode::CBC;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ break;
+ case CKM_AES_CBC_PAD:
+ algo = SymAlgo::AES;
+ mode = SymMode::CBC;
+ padding = true;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ break;
+ case CKM_AES_CTR:
+ algo = SymAlgo::AES;
+ mode = SymMode::CTR;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
+ {
+ DEBUG_MSG("CTR mode requires a counter block");
+ return CKR_ARGUMENTS_BAD;
+ }
+ counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
+ if (counterBits == 0 || counterBits > 128)
+ {
+ DEBUG_MSG("Invalid ulCounterBits");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ iv.resize(16);
+ memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
+ break;
+#ifdef WITH_AES_GCM
+ case CKM_AES_GCM:
+ algo = SymAlgo::AES;
+ mode = SymMode::GCM;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
+ {
+ DEBUG_MSG("GCM mode requires parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
+ memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
+ aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
+ memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
+ tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
+ if (tagBytes > 128 || tagBytes % 8 != 0)
+ {
+ DEBUG_MSG("Invalid ulTagBits value");
+ return CKR_ARGUMENTS_BAD;
+ }
+ tagBytes = tagBytes / 8;
+ break;
+#endif
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
+ if (cipher == NULL) return CKR_MECHANISM_INVALID;
+
+ SymmetricKey* secretkey = new SymmetricKey();
+
+ if (getSymmetricKey(secretkey, token, key) != CKR_OK)
+ {
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // adjust key bit length
+ secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
+
+ // Initialize encryption
+ if (!cipher->encryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
+ {
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_ENCRYPT);
+ session->setSymmetricCryptoOp(cipher);
+ session->setAllowMultiPartOp(true);
+ session->setAllowSinglePartOp(true);
+ session->setSymmetricKey(secretkey);
+
+ return CKR_OK;
+}
+
+// AsymAlgorithm version of C_EncryptInit
+CK_RV SoftHSM::AsymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for encryption
+ if (!key->getBooleanValue(CKA_ENCRYPT, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Get the asymmetric algorithm matching the mechanism
+ AsymMech::Type mechanism;
+ bool isRSA = false;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism = AsymMech::RSA_PKCS;
+ isRSA = true;
+ break;
+ case CKM_RSA_X_509:
+ mechanism = AsymMech::RSA;
+ isRSA = true;
+ break;
+ case CKM_RSA_PKCS_OAEP:
+ rv = MechParamCheckRSAPKCSOAEP(pMechanism);
+ if (rv != CKR_OK)
+ return rv;
+
+ mechanism = AsymMech::RSA_PKCS_OAEP;
+ isRSA = true;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PublicKey* publicKey = NULL;
+ if (isRSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ publicKey = asymCrypto->newPublicKey();
+ if (publicKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_ENCRYPT);
+ session->setAsymmetricCryptoOp(asymCrypto);
+ session->setMechanism(mechanism);
+ session->setAllowMultiPartOp(false);
+ session->setAllowSinglePartOp(true);
+ session->setPublicKey(publicKey);
+
+ return CKR_OK;
+}
+
+// Initialise encryption using the specified object and mechanism
+CK_RV SoftHSM::C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (isSymMechanism(pMechanism))
+ return SymEncryptInit(hSession, pMechanism, hKey);
+ else
+ return AsymEncryptInit(hSession, pMechanism, hKey);
+}
+
+// SymAlgorithm version of C_Encrypt
+static CK_RV SymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
+ if (cipher == NULL || !session->getAllowSinglePartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check data size
+ CK_ULONG maxSize = ulDataLen + cipher->getTagBytes();
+ if (cipher->isBlockCipher())
+ {
+ CK_ULONG remainder = ulDataLen % cipher->getBlockSize();
+ if (cipher->getPaddingMode() == false && remainder != 0)
+ {
+ session->resetOp();
+ return CKR_DATA_LEN_RANGE;
+ }
+
+ // Round up to block size
+ if (remainder != 0)
+ {
+ maxSize = ulDataLen + cipher->getBlockSize() - remainder;
+ }
+ else if (cipher->getPaddingMode() == true)
+ {
+ maxSize = ulDataLen + cipher->getBlockSize();
+ }
+ }
+ if (!cipher->checkMaximumBytes(ulDataLen))
+ {
+ session->resetOp();
+ return CKR_DATA_LEN_RANGE;
+ }
+
+ if (pEncryptedData == NULL_PTR)
+ {
+ *pulEncryptedDataLen = maxSize;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulEncryptedDataLen < maxSize)
+ {
+ *pulEncryptedDataLen = maxSize;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data(pData, ulDataLen);
+ ByteString encryptedData;
+
+ // Encrypt the data
+ if (!cipher->encryptUpdate(data, encryptedData))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Finalize encryption
+ ByteString encryptedFinal;
+ if (!cipher->encryptFinal(encryptedFinal))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ encryptedData += encryptedFinal;
+ encryptedData.resize(maxSize);
+
+ memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
+ *pulEncryptedDataLen = encryptedData.size();
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// AsymAlgorithm version of C_Encrypt
+static CK_RV AsymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ AsymMech::Type mechanism = session->getMechanism();
+ PublicKey* publicKey = session->getPublicKey();
+ if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the encrypted data
+ CK_ULONG size = publicKey->getOutputLength();
+
+ if (pEncryptedData == NULL_PTR)
+ {
+ *pulEncryptedDataLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulEncryptedDataLen < size)
+ {
+ *pulEncryptedDataLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data;
+ ByteString encryptedData;
+
+ // We must allow input length <= k and therfore need to prepend the data with zeroes.
+ if (mechanism == AsymMech::RSA) {
+ data.wipe(size-ulDataLen);
+ }
+
+ data += ByteString(pData, ulDataLen);
+
+ // Encrypt the data
+ if (!asymCrypto->encrypt(publicKey,data,encryptedData,mechanism))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (encryptedData.size() != size)
+ {
+ ERROR_MSG("The size of the encrypted data differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pEncryptedData, encryptedData.byte_str(), size);
+ *pulEncryptedDataLen = size;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Perform a single operation encryption operation in the specified session
+CK_RV SoftHSM::C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_ENCRYPT)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getSymmetricCryptoOp() != NULL)
+ return SymEncrypt(session, pData, ulDataLen,
+ pEncryptedData, pulEncryptedDataLen);
+ else
+ return AsymEncrypt(session, pData, ulDataLen,
+ pEncryptedData, pulEncryptedDataLen);
+}
+
+// SymAlgorithm version of C_EncryptUpdate
+static CK_RV SymEncryptUpdate(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
+ if (cipher == NULL || !session->getAllowMultiPartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check data size
+ size_t blockSize = cipher->getBlockSize();
+ size_t remainingSize = cipher->getBufferSize();
+ CK_ULONG maxSize = ulDataLen + remainingSize;
+ if (cipher->isBlockCipher())
+ {
+ int nrOfBlocks = (ulDataLen + remainingSize) / blockSize;
+ maxSize = nrOfBlocks * blockSize;
+ }
+ if (!cipher->checkMaximumBytes(ulDataLen))
+ {
+ session->resetOp();
+ return CKR_DATA_LEN_RANGE;
+ }
+
+ // Check data size
+ if (pEncryptedData == NULL_PTR)
+ {
+ *pulEncryptedDataLen = maxSize;
+ return CKR_OK;
+ }
+
+ // Check output buffer size
+ if (*pulEncryptedDataLen < maxSize)
+ {
+ DEBUG_MSG("ulDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x",
+ ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize);
+ *pulEncryptedDataLen = maxSize;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data(pData, ulDataLen);
+ ByteString encryptedData;
+
+ // Encrypt the data
+ if (!cipher->encryptUpdate(data, encryptedData))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ DEBUG_MSG("ulDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x encryptedData.size(): %#5x",
+ ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize, encryptedData.size());
+
+ // Check output size from crypto. Unrecoverable error if to large.
+ if (*pulEncryptedDataLen < encryptedData.size())
+ {
+ session->resetOp();
+ ERROR_MSG("EncryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
+ *pulEncryptedDataLen, encryptedData.size());
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (encryptedData.size() > 0)
+ {
+ memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
+ }
+ *pulEncryptedDataLen = encryptedData.size();
+
+ return CKR_OK;
+}
+
+// Feed data to the running encryption operation in a session
+CK_RV SoftHSM::C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_ENCRYPT)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getSymmetricCryptoOp() != NULL)
+ return SymEncryptUpdate(session, pData, ulDataLen,
+ pEncryptedData, pulEncryptedDataLen);
+ else
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// SymAlgorithm version of C_EncryptFinal
+static CK_RV SymEncryptFinal(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
+ if (cipher == NULL || !session->getAllowMultiPartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check data size
+ size_t remainingSize = cipher->getBufferSize() + cipher->getTagBytes();
+ CK_ULONG size = remainingSize;
+ if (cipher->isBlockCipher())
+ {
+ size_t blockSize = cipher->getBlockSize();
+ bool isPadding = cipher->getPaddingMode();
+ if ((remainingSize % blockSize) != 0 && !isPadding)
+ {
+ session->resetOp();
+ DEBUG_MSG("Remaining buffer size is not an integral of the block size. Block size: %#2x Remaining size: %#2x",
+ blockSize, remainingSize);
+ return CKR_DATA_LEN_RANGE;
+ }
+ // when padding: an integral of the block size that is longer than the remaining data.
+ size = isPadding ? ((remainingSize + blockSize) / blockSize) * blockSize : remainingSize;
+ }
+
+ // Give required output buffer size.
+ if (pEncryptedData == NULL_PTR)
+ {
+ *pulEncryptedDataLen = size;
+ return CKR_OK;
+ }
+
+ // Check output buffer size
+ if (*pulEncryptedDataLen < size)
+ {
+ DEBUG_MSG("output buffer size: %#5x size: %#5x",
+ *pulEncryptedDataLen, size);
+ *pulEncryptedDataLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Finalize encryption
+ ByteString encryptedFinal;
+ if (!cipher->encryptFinal(encryptedFinal))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ DEBUG_MSG("output buffer size: %#2x size: %#2x encryptedFinal.size(): %#2x",
+ *pulEncryptedDataLen, size, encryptedFinal.size());
+
+ // Check output size from crypto. Unrecoverable error if to large.
+ if (*pulEncryptedDataLen < encryptedFinal.size())
+ {
+ session->resetOp();
+ ERROR_MSG("EncryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
+ *pulEncryptedDataLen, encryptedFinal.size());
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (encryptedFinal.size() > 0)
+ {
+ memcpy(pEncryptedData, encryptedFinal.byte_str(), encryptedFinal.size());
+ }
+ *pulEncryptedDataLen = encryptedFinal.size();
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Finalise the encryption operation
+CK_RV SoftHSM::C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_ENCRYPT) return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getSymmetricCryptoOp() != NULL)
+ return SymEncryptFinal(session, pEncryptedData, pulEncryptedDataLen);
+ else
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// SymAlgorithm version of C_DecryptInit
+CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for decryption
+ if (!key->getBooleanValue(CKA_DECRYPT, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+
+ // Check if the specified mechanism is allowed for the key
+ if (!isMechanismPermitted(key, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Get the symmetric algorithm matching the mechanism
+ SymAlgo::Type algo = SymAlgo::Unknown;
+ SymMode::Type mode = SymMode::Unknown;
+ bool padding = false;
+ ByteString iv;
+ size_t bb = 8;
+ size_t counterBits = 0;
+ ByteString aad;
+ size_t tagBytes = 0;
+ switch(pMechanism->mechanism) {
+#ifndef WITH_FIPS
+ case CKM_DES_ECB:
+ algo = SymAlgo::DES;
+ mode = SymMode::ECB;
+ bb = 7;
+ break;
+ case CKM_DES_CBC:
+ algo = SymAlgo::DES;
+ mode = SymMode::CBC;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ bb = 7;
+ break;
+ case CKM_DES_CBC_PAD:
+ algo = SymAlgo::DES;
+ mode = SymMode::CBC;
+ padding = true;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ bb = 7;
+ break;
+#endif
+ case CKM_DES3_ECB:
+ algo = SymAlgo::DES3;
+ mode = SymMode::ECB;
+ bb = 7;
+ break;
+ case CKM_DES3_CBC:
+ algo = SymAlgo::DES3;
+ mode = SymMode::CBC;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ bb = 7;
+ break;
+ case CKM_DES3_CBC_PAD:
+ algo = SymAlgo::DES3;
+ mode = SymMode::CBC;
+ padding = true;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ bb = 7;
+ break;
+ case CKM_AES_ECB:
+ algo = SymAlgo::AES;
+ mode = SymMode::ECB;
+ break;
+ case CKM_AES_CBC:
+ algo = SymAlgo::AES;
+ mode = SymMode::CBC;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ break;
+ case CKM_AES_CBC_PAD:
+ algo = SymAlgo::AES;
+ mode = SymMode::CBC;
+ padding = true;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen == 0)
+ {
+ DEBUG_MSG("CBC mode requires an init vector");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(pMechanism->ulParameterLen);
+ memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ break;
+ case CKM_AES_CTR:
+ algo = SymAlgo::AES;
+ mode = SymMode::CTR;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
+ {
+ DEBUG_MSG("CTR mode requires a counter block");
+ return CKR_ARGUMENTS_BAD;
+ }
+ counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
+ if (counterBits == 0 || counterBits > 128)
+ {
+ DEBUG_MSG("Invalid ulCounterBits");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ iv.resize(16);
+ memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
+ break;
+#ifdef WITH_AES_GCM
+ case CKM_AES_GCM:
+ algo = SymAlgo::AES;
+ mode = SymMode::GCM;
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
+ {
+ DEBUG_MSG("GCM mode requires parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
+ memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
+ aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
+ memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
+ tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
+ if (tagBytes > 128 || tagBytes % 8 != 0)
+ {
+ DEBUG_MSG("Invalid ulTagBits value");
+ return CKR_ARGUMENTS_BAD;
+ }
+ tagBytes = tagBytes / 8;
+ break;
+#endif
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
+ if (cipher == NULL) return CKR_MECHANISM_INVALID;
+
+ SymmetricKey* secretkey = new SymmetricKey();
+
+ if (getSymmetricKey(secretkey, token, key) != CKR_OK)
+ {
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // adjust key bit length
+ secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
+
+ // Initialize decryption
+ if (!cipher->decryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
+ {
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_DECRYPT);
+ session->setSymmetricCryptoOp(cipher);
+ session->setAllowMultiPartOp(true);
+ session->setAllowSinglePartOp(true);
+ session->setSymmetricKey(secretkey);
+
+ return CKR_OK;
+}
+
+// AsymAlgorithm version of C_DecryptInit
+CK_RV SoftHSM::AsymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for decryption
+ if (!key->getBooleanValue(CKA_DECRYPT, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the key
+ if (!isMechanismPermitted(key, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Get the asymmetric algorithm matching the mechanism
+ AsymMech::Type mechanism = AsymMech::Unknown;
+ bool isRSA = false;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism = AsymMech::RSA_PKCS;
+ isRSA = true;
+ break;
+ case CKM_RSA_X_509:
+ mechanism = AsymMech::RSA;
+ isRSA = true;
+ break;
+ case CKM_RSA_PKCS_OAEP:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
+ {
+ DEBUG_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1)
+ {
+ DEBUG_MSG("hashAlg must be CKM_SHA_1");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
+ {
+ DEBUG_MSG("mgf must be CKG_MGF1_SHA1");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ mechanism = AsymMech::RSA_PKCS_OAEP;
+ isRSA = true;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PrivateKey* privateKey = NULL;
+ if (isRSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ privateKey = asymCrypto->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Check if re-authentication is required
+ if (key->getBooleanValue(CKA_ALWAYS_AUTHENTICATE, false))
+ {
+ session->setReAuthentication(true);
+ }
+
+ session->setOpType(SESSION_OP_DECRYPT);
+ session->setAsymmetricCryptoOp(asymCrypto);
+ session->setMechanism(mechanism);
+ session->setAllowMultiPartOp(false);
+ session->setAllowSinglePartOp(true);
+ session->setPrivateKey(privateKey);
+
+ return CKR_OK;
+}
+
+// Initialise decryption using the specified object
+CK_RV SoftHSM::C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (isSymMechanism(pMechanism))
+ return SymDecryptInit(hSession, pMechanism, hKey);
+ else
+ return AsymDecryptInit(hSession, pMechanism, hKey);
+}
+
+// SymAlgorithm version of C_Decrypt
+static CK_RV SymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
+ if (cipher == NULL || !session->getAllowSinglePartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check encrypted data size
+ if (cipher->isBlockCipher() && ulEncryptedDataLen % cipher->getBlockSize() != 0)
+ {
+ session->resetOp();
+ return CKR_ENCRYPTED_DATA_LEN_RANGE;
+ }
+ if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
+ {
+ session->resetOp();
+ return CKR_ENCRYPTED_DATA_LEN_RANGE;
+ }
+
+ if (pData == NULL_PTR)
+ {
+ *pulDataLen = ulEncryptedDataLen;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulDataLen < ulEncryptedDataLen)
+ {
+ *pulDataLen = ulEncryptedDataLen;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
+ ByteString data;
+
+ // Decrypt the data
+ if (!cipher->decryptUpdate(encryptedData,data))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Finalize decryption
+ ByteString dataFinal;
+ if (!cipher->decryptFinal(dataFinal))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ data += dataFinal;
+ if (data.size() > ulEncryptedDataLen)
+ {
+ data.resize(ulEncryptedDataLen);
+ }
+
+ if (data.size() != 0)
+ {
+ memcpy(pData, data.byte_str(), data.size());
+ }
+ *pulDataLen = data.size();
+
+ session->resetOp();
+ return CKR_OK;
+
+}
+
+// AsymAlgorithm version of C_Decrypt
+static CK_RV AsymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ AsymMech::Type mechanism = session->getMechanism();
+ PrivateKey* privateKey = session->getPrivateKey();
+ if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check if re-authentication is required
+ if (session->getReAuthentication())
+ {
+ session->resetOp();
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // Size of the data
+ CK_ULONG size = privateKey->getOutputLength();
+ if (pData == NULL_PTR)
+ {
+ *pulDataLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulDataLen < size)
+ {
+ *pulDataLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
+ ByteString data;
+
+ // Decrypt the data
+ if (!asymCrypto->decrypt(privateKey,encryptedData,data,mechanism))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (data.size() > size)
+ {
+ ERROR_MSG("The size of the decrypted data exceeds the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ if (data.size() != 0)
+ {
+ memcpy(pData, data.byte_str(), data.size());
+ }
+ *pulDataLen = data.size();
+
+ session->resetOp();
+ return CKR_OK;
+
+}
+
+// Perform a single operation decryption in the given session
+CK_RV SoftHSM::C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DECRYPT)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getSymmetricCryptoOp() != NULL)
+ return SymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
+ pData, pulDataLen);
+ else
+ return AsymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
+ pData, pulDataLen);
+}
+
+// SymAlgorithm version of C_DecryptUpdate
+static CK_RV SymDecryptUpdate(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
+ if (cipher == NULL || !session->getAllowMultiPartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check encrypted data size
+ size_t blockSize = cipher->getBlockSize();
+ size_t remainingSize = cipher->getBufferSize();
+ CK_ULONG maxSize = ulEncryptedDataLen + remainingSize;
+ if (cipher->isBlockCipher())
+ {
+ // There must always be one block left in padding mode if next operation is DecryptFinal.
+ // To guarantee that one byte is removed in padding mode when the number of blocks is calculated.
+ size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
+ int nrOfBlocks = (ulEncryptedDataLen + remainingSize - paddingAdjustByte) / blockSize;
+ maxSize = nrOfBlocks * blockSize;
+ }
+ if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
+ {
+ session->resetOp();
+ return CKR_ENCRYPTED_DATA_LEN_RANGE;
+ }
+
+ // Give required output buffer size.
+ if (pData == NULL_PTR)
+ {
+ *pDataLen = maxSize;
+ return CKR_OK;
+ }
+
+ // Check output buffer size
+ if (*pDataLen < maxSize)
+ {
+ DEBUG_MSG("Output buffer too short ulEncryptedDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x",
+ ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize);
+ *pDataLen = maxSize;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data(pEncryptedData, ulEncryptedDataLen);
+ ByteString decryptedData;
+
+ // Encrypt the data
+ if (!cipher->decryptUpdate(data, decryptedData))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ DEBUG_MSG("ulEncryptedDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x decryptedData.size(): %#5x",
+ ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize, decryptedData.size());
+
+ // Check output size from crypto. Unrecoverable error if to large.
+ if (*pDataLen < decryptedData.size())
+ {
+ session->resetOp();
+ ERROR_MSG("DecryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the decrypt.",
+ *pDataLen, decryptedData.size());
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (decryptedData.size() > 0)
+ {
+ memcpy(pData, decryptedData.byte_str(), decryptedData.size());
+ }
+ *pDataLen = decryptedData.size();
+
+ return CKR_OK;
+}
+
+
+// Feed data to the running decryption operation in a session
+CK_RV SoftHSM::C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DECRYPT)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getSymmetricCryptoOp() != NULL)
+ return SymDecryptUpdate(session, pEncryptedData, ulEncryptedDataLen,
+ pData, pDataLen);
+ else
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+static CK_RV SymDecryptFinal(Session* session, CK_BYTE_PTR pDecryptedData, CK_ULONG_PTR pulDecryptedDataLen)
+{
+ SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
+ if (cipher == NULL || !session->getAllowMultiPartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check encrypted data size
+ size_t remainingSize = cipher->getBufferSize();
+ CK_ULONG size = remainingSize;
+ if (cipher->isBlockCipher())
+ {
+ size_t blockSize = cipher->getBlockSize();
+ if (remainingSize % blockSize != 0)
+ {
+ session->resetOp();
+ DEBUG_MSG("Remaining data length is not an integral of the block size. Block size: %#2x Remaining size: %#2x",
+ blockSize, remainingSize);
+ return CKR_ENCRYPTED_DATA_LEN_RANGE;
+ }
+ // It is at least one padding byte. If no padding the all remains will be returned.
+ size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
+ size = remainingSize - paddingAdjustByte;
+ }
+
+ // Give required output buffer size.
+ if (pDecryptedData == NULL_PTR)
+ {
+ *pulDecryptedDataLen = size;
+ return CKR_OK;
+ }
+
+ // Check output buffer size
+ if (*pulDecryptedDataLen < size)
+ {
+ DEBUG_MSG("output buffer size: %#5x size: %#5x",
+ *pulDecryptedDataLen, size);
+ *pulDecryptedDataLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Finalize decryption
+ ByteString decryptedFinal;
+ if (!cipher->decryptFinal(decryptedFinal))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ DEBUG_MSG("output buffer size: %#2x size: %#2x decryptedFinal.size(): %#2x",
+ *pulDecryptedDataLen, size, decryptedFinal.size());
+
+ // Check output size from crypto. Unrecoverable error if to large.
+ if (*pulDecryptedDataLen < decryptedFinal.size())
+ {
+ session->resetOp();
+ ERROR_MSG("DecryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
+ *pulDecryptedDataLen, decryptedFinal.size());
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (decryptedFinal.size() > 0)
+ {
+ memcpy(pDecryptedData, decryptedFinal.byte_str(), decryptedFinal.size());
+ }
+ *pulDecryptedDataLen = decryptedFinal.size();
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Finalise the decryption operation
+CK_RV SoftHSM::C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DECRYPT) return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getSymmetricCryptoOp() != NULL)
+ return SymDecryptFinal(session, pData, pDataLen);
+ else
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Initialise digesting using the specified mechanism in the specified session
+CK_RV SoftHSM::C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the mechanism
+ HashAlgo::Type algo = HashAlgo::Unknown;
+ switch(pMechanism->mechanism) {
+#ifndef WITH_FIPS
+ case CKM_MD5:
+ algo = HashAlgo::MD5;
+ break;
+#endif
+ case CKM_SHA_1:
+ algo = HashAlgo::SHA1;
+ break;
+ case CKM_SHA224:
+ algo = HashAlgo::SHA224;
+ break;
+ case CKM_SHA256:
+ algo = HashAlgo::SHA256;
+ break;
+ case CKM_SHA384:
+ algo = HashAlgo::SHA384;
+ break;
+ case CKM_SHA512:
+ algo = HashAlgo::SHA512;
+ break;
+#ifdef WITH_GOST
+ case CKM_GOSTR3411:
+ algo = HashAlgo::GOST;
+ break;
+#endif
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(algo);
+ if (hash == NULL) return CKR_MECHANISM_INVALID;
+
+ // Initialize hashing
+ if (hash->hashInit() == false)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ return CKR_GENERAL_ERROR;
+ }
+
+ session->setOpType(SESSION_OP_DIGEST);
+ session->setDigestOp(hash);
+ session->setHashAlgo(algo);
+
+ return CKR_OK;
+}
+
+// Digest the specified data in a one-pass operation and return the resulting digest
+CK_RV SoftHSM::C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // Return size
+ CK_ULONG size = session->getDigestOp()->getHashSize();
+ if (pDigest == NULL_PTR)
+ {
+ *pulDigestLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulDigestLen < size)
+ {
+ *pulDigestLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data(pData, ulDataLen);
+
+ // Digest the data
+ if (session->getDigestOp()->hashUpdate(data) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Get the digest
+ ByteString digest;
+ if (session->getDigestOp()->hashFinal(digest) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (digest.size() != size)
+ {
+ ERROR_MSG("The size of the digest differ from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pDigest, digest.byte_str(), size);
+ *pulDigestLen = size;
+
+ session->resetOp();
+
+ return CKR_OK;
+}
+
+// Update a running digest operation
+CK_RV SoftHSM::C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // Get the data
+ ByteString data(pPart, ulPartLen);
+
+ // Digest the data
+ if (session->getDigestOp()->hashUpdate(data) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+// Update a running digest operation by digesting a secret key with the specified handle
+CK_RV SoftHSM::C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hObject);
+ if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
+ // so we use CKR_GENERAL_ERROR.
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Whitelist
+ HashAlgo::Type algo = session->getHashAlgo();
+ if (algo != HashAlgo::SHA1 &&
+ algo != HashAlgo::SHA224 &&
+ algo != HashAlgo::SHA256 &&
+ algo != HashAlgo::SHA384 &&
+ algo != HashAlgo::SHA512)
+ {
+ // Parano...
+ if (!key->getBooleanValue(CKA_EXTRACTABLE, false))
+ return CKR_KEY_INDIGESTIBLE;
+ if (key->getBooleanValue(CKA_SENSITIVE, false))
+ return CKR_KEY_INDIGESTIBLE;
+ }
+
+ // Get value
+ if (!key->attributeExists(CKA_VALUE))
+ return CKR_KEY_INDIGESTIBLE;
+ ByteString keybits;
+ if (isPrivate)
+ {
+ if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ keybits = key->getByteStringValue(CKA_VALUE);
+ }
+
+ // Digest the value
+ if (session->getDigestOp()->hashUpdate(keybits) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+// Finalise the digest operation in the specified session and return the digest
+CK_RV SoftHSM::C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
+
+ // Return size
+ CK_ULONG size = session->getDigestOp()->getHashSize();
+ if (pDigest == NULL_PTR)
+ {
+ *pulDigestLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulDigestLen < size)
+ {
+ *pulDigestLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the digest
+ ByteString digest;
+ if (session->getDigestOp()->hashFinal(digest) == false)
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (digest.size() != size)
+ {
+ ERROR_MSG("The size of the digest differ from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pDigest, digest.byte_str(), size);
+ *pulDigestLen = size;
+
+ session->resetOp();
+
+ return CKR_OK;
+}
+
+// Sign*/Verify*() is for MACs too
+static bool isMacMechanism(CK_MECHANISM_PTR pMechanism)
+{
+ if (pMechanism == NULL_PTR) return false;
+
+ switch(pMechanism->mechanism) {
+ case CKM_MD5_HMAC:
+ case CKM_SHA_1_HMAC:
+ case CKM_SHA224_HMAC:
+ case CKM_SHA256_HMAC:
+ case CKM_SHA384_HMAC:
+ case CKM_SHA512_HMAC:
+#ifdef WITH_GOST
+ case CKM_GOSTR3411_HMAC:
+#endif
+ case CKM_DES3_CMAC:
+ case CKM_AES_CMAC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// MacAlgorithm version of C_SignInit
+CK_RV SoftHSM::MacSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for signing
+ if (!key->getBooleanValue(CKA_SIGN, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the key
+ if (!isMechanismPermitted(key, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Get key info
+ CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
+
+ // Get the MAC algorithm matching the mechanism
+ // Also check mechanism constraints
+ MacAlgo::Type algo = MacAlgo::Unknown;
+ size_t bb = 8;
+ size_t minSize = 0;
+ switch(pMechanism->mechanism) {
+#ifndef WITH_FIPS
+ case CKM_MD5_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 16;
+ algo = MacAlgo::HMAC_MD5;
+ break;
+#endif
+ case CKM_SHA_1_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 20;
+ algo = MacAlgo::HMAC_SHA1;
+ break;
+ case CKM_SHA224_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 28;
+ algo = MacAlgo::HMAC_SHA224;
+ break;
+ case CKM_SHA256_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 32;
+ algo = MacAlgo::HMAC_SHA256;
+ break;
+ case CKM_SHA384_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 48;
+ algo = MacAlgo::HMAC_SHA384;
+ break;
+ case CKM_SHA512_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 64;
+ algo = MacAlgo::HMAC_SHA512;
+ break;
+#ifdef WITH_GOST
+ case CKM_GOSTR3411_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 32;
+ algo = MacAlgo::HMAC_GOST;
+ break;
+#endif
+ case CKM_DES3_CMAC:
+ if (keyType != CKK_DES2 && keyType != CKK_DES3)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ algo = MacAlgo::CMAC_DES;
+ bb = 7;
+ break;
+ case CKM_AES_CMAC:
+ if (keyType != CKK_AES)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ algo = MacAlgo::CMAC_AES;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
+ if (mac == NULL) return CKR_MECHANISM_INVALID;
+
+ SymmetricKey* privkey = new SymmetricKey();
+
+ if (getSymmetricKey(privkey, token, key) != CKR_OK)
+ {
+ mac->recycleKey(privkey);
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Adjust key bit length
+ privkey->setBitLen(privkey->getKeyBits().size() * bb);
+
+ // Check key size
+ if (privkey->getBitLen() < (minSize*8))
+ {
+ mac->recycleKey(privkey);
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+ return CKR_KEY_SIZE_RANGE;
+ }
+
+ // Initialize signing
+ if (!mac->signInit(privkey))
+ {
+ mac->recycleKey(privkey);
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_SIGN);
+ session->setMacOp(mac);
+ session->setAllowMultiPartOp(true);
+ session->setAllowSinglePartOp(true);
+ session->setSymmetricKey(privkey);
+
+ return CKR_OK;
+}
+
+// AsymmetricAlgorithm version of C_SignInit
+CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for signing
+ if (!key->getBooleanValue(CKA_SIGN, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the key
+ if (!isMechanismPermitted(key, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Get the asymmetric algorithm matching the mechanism
+ AsymMech::Type mechanism = AsymMech::Unknown;
+ void* param = NULL;
+ size_t paramLen = 0;
+ RSA_PKCS_PSS_PARAMS pssParam;
+ bool bAllowMultiPartOp;
+ bool isRSA = false;
+ bool isDSA = false;
+ bool isECDSA = false;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism = AsymMech::RSA_PKCS;
+ bAllowMultiPartOp = false;
+ isRSA = true;
+ break;
+ case CKM_RSA_X_509:
+ mechanism = AsymMech::RSA;
+ bAllowMultiPartOp = false;
+ isRSA = true;
+ break;
+#ifndef WITH_FIPS
+ case CKM_MD5_RSA_PKCS:
+ mechanism = AsymMech::RSA_MD5_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+#endif
+ case CKM_SHA1_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA1_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA224_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA224_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA256_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA256_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA384_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA384_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA512_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA512_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+#ifdef WITH_RAW_PSS
+ case CKM_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
+ {
+ ERROR_MSG("Invalid RSA-PSS parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_PKCS_PSS;
+ unsigned long allowedMgf;
+
+ switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
+ case CKM_SHA_1:
+ pssParam.hashAlg = HashAlgo::SHA1;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
+ allowedMgf = CKG_MGF1_SHA1;
+ break;
+ case CKM_SHA224:
+ pssParam.hashAlg = HashAlgo::SHA224;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
+ allowedMgf = CKG_MGF1_SHA224;
+ break;
+ case CKM_SHA256:
+ pssParam.hashAlg = HashAlgo::SHA256;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
+ allowedMgf = CKG_MGF1_SHA256;
+ break;
+ case CKM_SHA384:
+ pssParam.hashAlg = HashAlgo::SHA384;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
+ allowedMgf = CKG_MGF1_SHA384;
+ break;
+ case CKM_SHA512:
+ pssParam.hashAlg = HashAlgo::SHA512;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
+ allowedMgf = CKG_MGF1_SHA512;
+ break;
+ default:
+ ERROR_MSG("Invalid RSA-PSS hash");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != allowedMgf) {
+ ERROR_MSG("Hash and MGF don't match");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = false;
+ isRSA = true;
+ break;
+#endif
+ case CKM_SHA1_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA1;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA224_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA224;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA256_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA256;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA384_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA384;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA512_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA512;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_DSA:
+ mechanism = AsymMech::DSA;
+ bAllowMultiPartOp = false;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA1:
+ mechanism = AsymMech::DSA_SHA1;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA224:
+ mechanism = AsymMech::DSA_SHA224;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA256:
+ mechanism = AsymMech::DSA_SHA256;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA384:
+ mechanism = AsymMech::DSA_SHA384;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA512:
+ mechanism = AsymMech::DSA_SHA512;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+#ifdef WITH_ECC
+ case CKM_ECDSA:
+ mechanism = AsymMech::ECDSA;
+ bAllowMultiPartOp = false;
+ isECDSA = true;
+ break;
+#endif
+#ifdef WITH_GOST
+ case CKM_GOSTR3410:
+ mechanism = AsymMech::GOST;
+ bAllowMultiPartOp = false;
+ break;
+ case CKM_GOSTR3410_WITH_GOSTR3411:
+ mechanism = AsymMech::GOST_GOST;
+ bAllowMultiPartOp = true;
+ break;
+#endif
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PrivateKey* privateKey = NULL;
+ if (isRSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ privateKey = asymCrypto->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else if (isDSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ privateKey = asymCrypto->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+#ifdef WITH_ECC
+ else if (isECDSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ privateKey = asymCrypto->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getECPrivateKey((ECPrivateKey*)privateKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+#endif
+ else
+ {
+#ifdef WITH_GOST
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ privateKey = asymCrypto->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+#else
+ return CKR_MECHANISM_INVALID;
+#endif
+ }
+
+ // Initialize signing
+ if (bAllowMultiPartOp && !asymCrypto->signInit(privateKey,mechanism,param,paramLen))
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Check if re-authentication is required
+ if (key->getBooleanValue(CKA_ALWAYS_AUTHENTICATE, false))
+ {
+ session->setReAuthentication(true);
+ }
+
+ session->setOpType(SESSION_OP_SIGN);
+ session->setAsymmetricCryptoOp(asymCrypto);
+ session->setMechanism(mechanism);
+ session->setParameters(param, paramLen);
+ session->setAllowMultiPartOp(bAllowMultiPartOp);
+ session->setAllowSinglePartOp(true);
+ session->setPrivateKey(privateKey);
+
+ return CKR_OK;
+}
+
+// Initialise a signing operation using the specified key and mechanism
+CK_RV SoftHSM::C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (isMacMechanism(pMechanism))
+ return MacSignInit(hSession, pMechanism, hKey);
+ else
+ return AsymSignInit(hSession, pMechanism, hKey);
+}
+
+// MacAlgorithm version of C_Sign
+static CK_RV MacSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ MacAlgorithm* mac = session->getMacOp();
+ if (mac == NULL || !session->getAllowSinglePartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = mac->getMacSize();
+ if (pSignature == NULL_PTR)
+ {
+ *pulSignatureLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulSignatureLen < size)
+ {
+ *pulSignatureLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data(pData, ulDataLen);
+
+ // Sign the data
+ if (!mac->signUpdate(data))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Get the signature
+ ByteString signature;
+ if (!mac->signFinal(signature))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (signature.size() != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pSignature, signature.byte_str(), size);
+ *pulSignatureLen = size;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// AsymmetricAlgorithm version of C_Sign
+static CK_RV AsymSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ AsymMech::Type mechanism = session->getMechanism();
+ PrivateKey* privateKey = session->getPrivateKey();
+ size_t paramLen;
+ void* param = session->getParameters(paramLen);
+ if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check if re-authentication is required
+ if (session->getReAuthentication())
+ {
+ session->resetOp();
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // Size of the signature
+ CK_ULONG size = privateKey->getOutputLength();
+ if (pSignature == NULL_PTR)
+ {
+ *pulSignatureLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulSignatureLen < size)
+ {
+ *pulSignatureLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the data
+ ByteString data;
+
+ // We must allow input length <= k and therfore need to prepend the data with zeroes.
+ if (mechanism == AsymMech::RSA) {
+ data.wipe(size-ulDataLen);
+ }
+
+ data += ByteString(pData, ulDataLen);
+ ByteString signature;
+
+ // Sign the data
+ if (session->getAllowMultiPartOp())
+ {
+ if (!asymCrypto->signUpdate(data) ||
+ !asymCrypto->signFinal(signature))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else if (!asymCrypto->sign(privateKey,data,signature,mechanism,param,paramLen))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (signature.size() != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pSignature, signature.byte_str(), size);
+ *pulSignatureLen = size;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Sign the data in a single pass operation
+CK_RV SoftHSM::C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_SIGN)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getMacOp() != NULL)
+ return MacSign(session, pData, ulDataLen,
+ pSignature, pulSignatureLen);
+ else
+ return AsymSign(session, pData, ulDataLen,
+ pSignature, pulSignatureLen);
+}
+
+// MacAlgorithm version of C_SignUpdate
+static CK_RV MacSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ MacAlgorithm* mac = session->getMacOp();
+ if (mac == NULL || !session->getAllowMultiPartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Get the part
+ ByteString part(pPart, ulPartLen);
+
+ // Sign the data
+ if (!mac->signUpdate(part))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ session->setAllowSinglePartOp(false);
+ return CKR_OK;
+}
+
+// AsymmetricAlgorithm version of C_SignUpdate
+static CK_RV AsymSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ if (asymCrypto == NULL || !session->getAllowMultiPartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check if re-authentication is required
+ if (session->getReAuthentication())
+ {
+ session->resetOp();
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // Get the part
+ ByteString part(pPart, ulPartLen);
+
+ // Sign the data
+ if (!asymCrypto->signUpdate(part))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ session->setAllowSinglePartOp(false);
+ return CKR_OK;
+}
+
+// Update a running signing operation with additional data
+CK_RV SoftHSM::C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_SIGN)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getMacOp() != NULL)
+ return MacSignUpdate(session, pPart, ulPartLen);
+ else
+ return AsymSignUpdate(session, pPart, ulPartLen);
+}
+
+// MacAlgorithm version of C_SignFinal
+static CK_RV MacSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ MacAlgorithm* mac = session->getMacOp();
+ if (mac == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = mac->getMacSize();
+ if (pSignature == NULL_PTR)
+ {
+ *pulSignatureLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulSignatureLen < size)
+ {
+ *pulSignatureLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the signature
+ ByteString signature;
+ if (!mac->signFinal(signature))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (signature.size() != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pSignature, signature.byte_str(), size);
+ *pulSignatureLen = size;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// AsymmetricAlgorithm version of C_SignFinal
+static CK_RV AsymSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ PrivateKey* privateKey = session->getPrivateKey();
+ if (asymCrypto == NULL || privateKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Check if re-authentication is required
+ if (session->getReAuthentication())
+ {
+ session->resetOp();
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // Size of the signature
+ CK_ULONG size = privateKey->getOutputLength();
+ if (pSignature == NULL_PTR)
+ {
+ *pulSignatureLen = size;
+ return CKR_OK;
+ }
+
+ // Check buffer size
+ if (*pulSignatureLen < size)
+ {
+ *pulSignatureLen = size;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ // Get the signature
+ ByteString signature;
+ if (!asymCrypto->signFinal(signature))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Check size
+ if (signature.size() != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+ memcpy(pSignature, signature.byte_str(), size);
+ *pulSignatureLen = size;
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Finalise a running signing operation and return the signature
+CK_RV SoftHSM::C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_SIGN || !session->getAllowMultiPartOp())
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getMacOp() != NULL)
+ return MacSignFinal(session, pSignature, pulSignatureLen);
+ else
+ return AsymSignFinal(session, pSignature, pulSignatureLen);
+}
+
+// Initialise a signing operation that allows recovery of the signed data
+CK_RV SoftHSM::C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Perform a single part signing operation that allows recovery of the signed data
+CK_RV SoftHSM::C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pData*/, CK_ULONG /*ulDataLen*/, CK_BYTE_PTR /*pSignature*/, CK_ULONG_PTR /*pulSignatureLen*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// MacAlgorithm version of C_VerifyInit
+CK_RV SoftHSM::MacVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for verifying
+ if (!key->getBooleanValue(CKA_VERIFY, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the key
+ if (!isMechanismPermitted(key, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Get key info
+ CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
+
+ // Get the MAC algorithm matching the mechanism
+ // Also check mechanism constraints
+ MacAlgo::Type algo = MacAlgo::Unknown;
+ size_t bb = 8;
+ size_t minSize = 0;
+ switch(pMechanism->mechanism) {
+#ifndef WITH_FIPS
+ case CKM_MD5_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 16;
+ algo = MacAlgo::HMAC_MD5;
+ break;
+#endif
+ case CKM_SHA_1_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 20;
+ algo = MacAlgo::HMAC_SHA1;
+ break;
+ case CKM_SHA224_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 28;
+ algo = MacAlgo::HMAC_SHA224;
+ break;
+ case CKM_SHA256_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 32;
+ algo = MacAlgo::HMAC_SHA256;
+ break;
+ case CKM_SHA384_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 48;
+ algo = MacAlgo::HMAC_SHA384;
+ break;
+ case CKM_SHA512_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 64;
+ algo = MacAlgo::HMAC_SHA512;
+ break;
+#ifdef WITH_GOST
+ case CKM_GOSTR3411_HMAC:
+ if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ minSize = 32;
+ algo = MacAlgo::HMAC_GOST;
+ break;
+#endif
+ case CKM_DES3_CMAC:
+ if (keyType != CKK_DES2 && keyType != CKK_DES3)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ algo = MacAlgo::CMAC_DES;
+ bb = 7;
+ break;
+ case CKM_AES_CMAC:
+ if (keyType != CKK_AES)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ algo = MacAlgo::CMAC_AES;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
+ if (mac == NULL) return CKR_MECHANISM_INVALID;
+
+ SymmetricKey* pubkey = new SymmetricKey();
+
+ if (getSymmetricKey(pubkey, token, key) != CKR_OK)
+ {
+ mac->recycleKey(pubkey);
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Adjust key bit length
+ pubkey->setBitLen(pubkey->getKeyBits().size() * bb);
+
+ // Check key size
+ if (pubkey->getBitLen() < (minSize*8))
+ {
+ mac->recycleKey(pubkey);
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+ return CKR_KEY_SIZE_RANGE;
+ }
+
+ // Initialize verifying
+ if (!mac->verifyInit(pubkey))
+ {
+ mac->recycleKey(pubkey);
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_VERIFY);
+ session->setMacOp(mac);
+ session->setAllowMultiPartOp(true);
+ session->setAllowSinglePartOp(true);
+ session->setSymmetricKey(pubkey);
+
+ return CKR_OK;
+}
+
+// AsymmetricAlgorithm version of C_VerifyInit
+CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check read user credentials
+ CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for verifying
+ if (!key->getBooleanValue(CKA_VERIFY, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the key
+ if (!isMechanismPermitted(key, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Get the asymmetric algorithm matching the mechanism
+ AsymMech::Type mechanism = AsymMech::Unknown;
+ void* param = NULL;
+ size_t paramLen = 0;
+ RSA_PKCS_PSS_PARAMS pssParam;
+ bool bAllowMultiPartOp;
+ bool isRSA = false;
+ bool isDSA = false;
+ bool isECDSA = false;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mechanism = AsymMech::RSA_PKCS;
+ bAllowMultiPartOp = false;
+ isRSA = true;
+ break;
+ case CKM_RSA_X_509:
+ mechanism = AsymMech::RSA;
+ bAllowMultiPartOp = false;
+ isRSA = true;
+ break;
+#ifndef WITH_FIPS
+ case CKM_MD5_RSA_PKCS:
+ mechanism = AsymMech::RSA_MD5_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+#endif
+ case CKM_SHA1_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA1_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA224_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA224_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA256_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA256_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA384_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA384_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA512_RSA_PKCS:
+ mechanism = AsymMech::RSA_SHA512_PKCS;
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+#ifdef WITH_RAW_PSS
+ case CKM_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_PKCS_PSS;
+
+ unsigned long expectedMgf;
+ switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
+ case CKM_SHA_1:
+ pssParam.hashAlg = HashAlgo::SHA1;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
+ expectedMgf = CKG_MGF1_SHA1;
+ break;
+ case CKM_SHA224:
+ pssParam.hashAlg = HashAlgo::SHA224;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
+ expectedMgf = CKG_MGF1_SHA224;
+ break;
+ case CKM_SHA256:
+ pssParam.hashAlg = HashAlgo::SHA256;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
+ expectedMgf = CKG_MGF1_SHA256;
+ break;
+ case CKM_SHA384:
+ pssParam.hashAlg = HashAlgo::SHA384;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
+ expectedMgf = CKG_MGF1_SHA384;
+ break;
+ case CKM_SHA512:
+ pssParam.hashAlg = HashAlgo::SHA512;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
+ expectedMgf = CKG_MGF1_SHA512;
+ break;
+ default:
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != expectedMgf) {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = false;
+ isRSA = true;
+ break;
+#endif
+ case CKM_SHA1_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA1;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA224_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA224;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA256_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA256;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA384_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA384;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_SHA512_RSA_PKCS_PSS:
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
+ CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
+ {
+ ERROR_MSG("Invalid parameters");
+ return CKR_ARGUMENTS_BAD;
+ }
+ mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
+ pssParam.hashAlg = HashAlgo::SHA512;
+ pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
+ pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
+ param = &pssParam;
+ paramLen = sizeof(pssParam);
+ bAllowMultiPartOp = true;
+ isRSA = true;
+ break;
+ case CKM_DSA:
+ mechanism = AsymMech::DSA;
+ bAllowMultiPartOp = false;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA1:
+ mechanism = AsymMech::DSA_SHA1;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA224:
+ mechanism = AsymMech::DSA_SHA224;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA256:
+ mechanism = AsymMech::DSA_SHA256;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA384:
+ mechanism = AsymMech::DSA_SHA384;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+ case CKM_DSA_SHA512:
+ mechanism = AsymMech::DSA_SHA512;
+ bAllowMultiPartOp = true;
+ isDSA = true;
+ break;
+#ifdef WITH_ECC
+ case CKM_ECDSA:
+ mechanism = AsymMech::ECDSA;
+ bAllowMultiPartOp = false;
+ isECDSA = true;
+ break;
+#endif
+#ifdef WITH_GOST
+ case CKM_GOSTR3410:
+ mechanism = AsymMech::GOST;
+ bAllowMultiPartOp = false;
+ break;
+ case CKM_GOSTR3410_WITH_GOSTR3411:
+ mechanism = AsymMech::GOST_GOST;
+ bAllowMultiPartOp = true;
+ break;
+#endif
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PublicKey* publicKey = NULL;
+ if (isRSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ publicKey = asymCrypto->newPublicKey();
+ if (publicKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+ else if (isDSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ publicKey = asymCrypto->newPublicKey();
+ if (publicKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getDSAPublicKey((DSAPublicKey*)publicKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+#ifdef WITH_ECC
+ else if (isECDSA)
+ {
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ publicKey = asymCrypto->newPublicKey();
+ if (publicKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getECPublicKey((ECPublicKey*)publicKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ }
+#endif
+ else
+ {
+#ifdef WITH_GOST
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
+ if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
+
+ publicKey = asymCrypto->newPublicKey();
+ if (publicKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+
+ if (getGOSTPublicKey((GOSTPublicKey*)publicKey, token, key) != CKR_OK)
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+#else
+ return CKR_MECHANISM_INVALID;
+#endif
+ }
+
+ // Initialize verifying
+ if (bAllowMultiPartOp && !asymCrypto->verifyInit(publicKey,mechanism,param,paramLen))
+ {
+ asymCrypto->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ session->setOpType(SESSION_OP_VERIFY);
+ session->setAsymmetricCryptoOp(asymCrypto);
+ session->setMechanism(mechanism);
+ session->setParameters(param, paramLen);
+ session->setAllowMultiPartOp(bAllowMultiPartOp);
+ session->setAllowSinglePartOp(true);
+ session->setPublicKey(publicKey);
+
+ return CKR_OK;
+}
+
+// Initialise a verification operation using the specified key and mechanism
+CK_RV SoftHSM::C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ if (isMacMechanism(pMechanism))
+ return MacVerifyInit(hSession, pMechanism, hKey);
+ else
+ return AsymVerifyInit(hSession, pMechanism, hKey);
+}
+
+// MacAlgorithm version of C_Verify
+static CK_RV MacVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ MacAlgorithm* mac = session->getMacOp();
+ if (mac == NULL || !session->getAllowSinglePartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = mac->getMacSize();
+
+ // Check buffer size
+ if (ulSignatureLen != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_SIGNATURE_LEN_RANGE;
+ }
+
+ // Get the data
+ ByteString data(pData, ulDataLen);
+
+ // Verify the data
+ if (!mac->verifyUpdate(data))
+ {
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Get the signature
+ ByteString signature(pSignature, ulSignatureLen);
+
+ // Verify the signature
+ if (!mac->verifyFinal(signature))
+ {
+ session->resetOp();
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// AsymmetricAlgorithm version of C_Verify
+static CK_RV AsymVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ AsymMech::Type mechanism = session->getMechanism();
+ PublicKey* publicKey = session->getPublicKey();
+ size_t paramLen;
+ void* param = session->getParameters(paramLen);
+ if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = publicKey->getOutputLength();
+
+ // Check buffer size
+ if (ulSignatureLen != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_SIGNATURE_LEN_RANGE;
+ }
+
+ // Get the data
+ ByteString data;
+
+ // We must allow input length <= k and therfore need to prepend the data with zeroes.
+ if (mechanism == AsymMech::RSA) {
+ data.wipe(size-ulDataLen);
+ }
+
+ data += ByteString(pData, ulDataLen);
+ ByteString signature(pSignature, ulSignatureLen);
+
+ // Verify the data
+ if (session->getAllowMultiPartOp())
+ {
+ if (!asymCrypto->verifyUpdate(data) ||
+ !asymCrypto->verifyFinal(signature))
+ {
+ session->resetOp();
+ return CKR_SIGNATURE_INVALID;
+ }
+ }
+ else if (!asymCrypto->verify(publicKey,data,signature,mechanism,param,paramLen))
+ {
+ session->resetOp();
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Perform a single pass verification operation
+CK_RV SoftHSM::C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_VERIFY)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getMacOp() != NULL)
+ return MacVerify(session, pData, ulDataLen,
+ pSignature, ulSignatureLen);
+ else
+ return AsymVerify(session, pData, ulDataLen,
+ pSignature, ulSignatureLen);
+}
+
+// MacAlgorithm version of C_VerifyUpdate
+static CK_RV MacVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ MacAlgorithm* mac = session->getMacOp();
+ if (mac == NULL || !session->getAllowMultiPartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Get the part
+ ByteString part(pPart, ulPartLen);
+
+ // Verify the data
+ if (!mac->verifyUpdate(part))
+ {
+ // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ session->setAllowSinglePartOp(false);
+ return CKR_OK;
+}
+
+// AsymmetricAlgorithm version of C_VerifyUpdate
+static CK_RV AsymVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ if (asymCrypto == NULL || !session->getAllowMultiPartOp())
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Get the part
+ ByteString part(pPart, ulPartLen);
+
+ // Verify the data
+ if (!asymCrypto->verifyUpdate(part))
+ {
+ // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
+ session->resetOp();
+ return CKR_GENERAL_ERROR;
+ }
+
+ session->setAllowSinglePartOp(false);
+ return CKR_OK;
+}
+
+// Update a running verification operation with additional data
+CK_RV SoftHSM::C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_VERIFY)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getMacOp() != NULL)
+ return MacVerifyUpdate(session, pPart, ulPartLen);
+ else
+ return AsymVerifyUpdate(session, pPart, ulPartLen);
+}
+
+// MacAlgorithm version of C_SignFinal
+static CK_RV MacVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ MacAlgorithm* mac = session->getMacOp();
+ if (mac == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = mac->getMacSize();
+
+ // Check buffer size
+ if (ulSignatureLen != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_SIGNATURE_LEN_RANGE;
+ }
+
+ // Get the signature
+ ByteString signature(pSignature, ulSignatureLen);
+
+ // Verify the data
+ if (!mac->verifyFinal(signature))
+ {
+ session->resetOp();
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// AsymmetricAlgorithm version of C_VerifyFinal
+static CK_RV AsymVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+ PublicKey* publicKey = session->getPublicKey();
+ if (asymCrypto == NULL || publicKey == NULL)
+ {
+ session->resetOp();
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ // Size of the signature
+ CK_ULONG size = publicKey->getOutputLength();
+
+ // Check buffer size
+ if (ulSignatureLen != size)
+ {
+ ERROR_MSG("The size of the signature differs from the size of the mechanism");
+ session->resetOp();
+ return CKR_SIGNATURE_LEN_RANGE;
+ }
+
+ // Get the data
+ ByteString signature(pSignature, ulSignatureLen);
+
+ // Verify the data
+ if (!asymCrypto->verifyFinal(signature))
+ {
+ session->resetOp();
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ session->resetOp();
+ return CKR_OK;
+}
+
+// Finalise the verification operation and check the signature
+CK_RV SoftHSM::C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we are doing the correct operation
+ if (session->getOpType() != SESSION_OP_VERIFY || !session->getAllowMultiPartOp())
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if (session->getMacOp() != NULL)
+ return MacVerifyFinal(session, pSignature, ulSignatureLen);
+ else
+ return AsymVerifyFinal(session, pSignature, ulSignatureLen);
+}
+
+// Initialise a verification operation the allows recovery of the signed data from the signature
+CK_RV SoftHSM::C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if we have another operation
+ if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Perform a single part verification operation and recover the signed data
+CK_RV SoftHSM::C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pSignature*/, CK_ULONG /*ulSignatureLen*/, CK_BYTE_PTR /*pData*/, CK_ULONG_PTR /*pulDataLen*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Update a running multi-part encryption and digesting operation
+CK_RV SoftHSM::C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Update a running multi-part decryption and digesting operation
+CK_RV SoftHSM::C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pDecryptedPart*/, CK_ULONG_PTR /*pulDecryptedPartLen*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Update a running multi-part signing and encryption operation
+CK_RV SoftHSM::C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Update a running multi-part decryption and verification operation
+CK_RV SoftHSM::C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG /*ulEncryptedPartLen*/, CK_BYTE_PTR /*pPart*/, CK_ULONG_PTR /*pulPartLen*/)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Generate a secret key or a domain parameter set using the specified mechanism
+CK_RV SoftHSM::C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check the mechanism, only accept DSA and DH parameters
+ // and symmetric ciphers
+ CK_OBJECT_CLASS objClass;
+ CK_KEY_TYPE keyType;
+ switch (pMechanism->mechanism)
+ {
+ case CKM_DSA_PARAMETER_GEN:
+ objClass = CKO_DOMAIN_PARAMETERS;
+ keyType = CKK_DSA;
+ break;
+ case CKM_DH_PKCS_PARAMETER_GEN:
+ objClass = CKO_DOMAIN_PARAMETERS;
+ keyType = CKK_DH;
+ break;
+#ifndef WITH_FIPS
+ case CKM_DES_KEY_GEN:
+ objClass = CKO_SECRET_KEY;
+ keyType = CKK_DES;
+ break;
+#endif
+ case CKM_DES2_KEY_GEN:
+ objClass = CKO_SECRET_KEY;
+ keyType = CKK_DES2;
+ break;
+ case CKM_DES3_KEY_GEN:
+ objClass = CKO_SECRET_KEY;
+ keyType = CKK_DES3;
+ break;
+ case CKM_AES_KEY_GEN:
+ objClass = CKO_SECRET_KEY;
+ keyType = CKK_AES;
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Extract information from the template that is needed to create the object.
+ CK_BBOOL isOnToken = CK_FALSE;
+ CK_BBOOL isPrivate = CK_TRUE;
+ CK_CERTIFICATE_TYPE dummy;
+ bool isImplicit = true;
+ extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
+
+ // Report errors and/or unexpected usage.
+ if (objClass != CKO_SECRET_KEY && objClass != CKO_DOMAIN_PARAMETERS)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN &&
+ (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DSA))
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN &&
+ (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DH))
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DES_KEY_GEN &&
+ (objClass != CKO_SECRET_KEY || keyType != CKK_DES))
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DES2_KEY_GEN &&
+ (objClass != CKO_SECRET_KEY || keyType != CKK_DES2))
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DES3_KEY_GEN &&
+ (objClass != CKO_SECRET_KEY || keyType != CKK_DES3))
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_AES_KEY_GEN &&
+ (objClass != CKO_SECRET_KEY || keyType != CKK_AES))
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ // Check authorization
+ CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Generate DSA domain parameters
+ if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN)
+ {
+ return this->generateDSAParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
+ }
+
+ // Generate DH domain parameters
+ if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN)
+ {
+ return this->generateDHParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
+ }
+
+ // Generate DES secret key
+ if (pMechanism->mechanism == CKM_DES_KEY_GEN)
+ {
+ return this->generateDES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
+ }
+
+ // Generate DES2 secret key
+ if (pMechanism->mechanism == CKM_DES2_KEY_GEN)
+ {
+ return this->generateDES2(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
+ }
+
+ // Generate DES3 secret key
+ if (pMechanism->mechanism == CKM_DES3_KEY_GEN)
+ {
+ return this->generateDES3(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
+ }
+
+ // Generate AES secret key
+ if (pMechanism->mechanism == CKM_AES_KEY_GEN)
+ {
+ return this->generateAES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
+ }
+
+ return CKR_GENERAL_ERROR;
+}
+
+// Generate a key-pair using the specified mechanism
+CK_RV SoftHSM::C_GenerateKeyPair
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey
+)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phPublicKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phPrivateKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check the mechanism, only accept RSA, DSA, EC and DH key pair generation.
+ CK_KEY_TYPE keyType;
+ switch (pMechanism->mechanism)
+ {
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ keyType = CKK_RSA;
+ break;
+ case CKM_DSA_KEY_PAIR_GEN:
+ keyType = CKK_DSA;
+ break;
+ case CKM_DH_PKCS_KEY_PAIR_GEN:
+ keyType = CKK_DH;
+ break;
+#ifdef WITH_ECC
+ case CKM_EC_KEY_PAIR_GEN:
+ keyType = CKK_EC;
+ break;
+#endif
+#ifdef WITH_GOST
+ case CKM_GOSTR3410_KEY_PAIR_GEN:
+ keyType = CKK_GOSTR3410;
+ break;
+#endif
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ CK_CERTIFICATE_TYPE dummy;
+
+ // Extract information from the public key template that is needed to create the object.
+ CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
+ CK_BBOOL ispublicKeyToken = CK_FALSE;
+ CK_BBOOL ispublicKeyPrivate = CK_FALSE;
+ bool isPublicKeyImplicit = true;
+ extractObjectInformation(pPublicKeyTemplate, ulPublicKeyAttributeCount, publicKeyClass, keyType, dummy, ispublicKeyToken, ispublicKeyPrivate, isPublicKeyImplicit);
+
+ // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
+ if (publicKeyClass != CKO_PUBLIC_KEY)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ // Extract information from the private key template that is needed to create the object.
+ CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
+ CK_BBOOL isprivateKeyToken = CK_FALSE;
+ CK_BBOOL isprivateKeyPrivate = CK_TRUE;
+ bool isPrivateKeyImplicit = true;
+ extractObjectInformation(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, privateKeyClass, keyType, dummy, isprivateKeyToken, isprivateKeyPrivate, isPrivateKeyImplicit);
+
+ // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
+ if (privateKeyClass != CKO_PRIVATE_KEY)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
+ return CKR_TEMPLATE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ // Check user credentials
+ CK_RV rv = haveWrite(session->getState(), ispublicKeyToken || isprivateKeyToken, ispublicKeyPrivate || isprivateKeyPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Generate RSA keys
+ if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN)
+ {
+ return this->generateRSA(hSession,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
+ }
+
+ // Generate DSA keys
+ if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN)
+ {
+ return this->generateDSA(hSession,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
+ }
+
+ // Generate EC keys
+ if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN)
+ {
+ return this->generateEC(hSession,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
+ }
+
+ // Generate DH keys
+ if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN)
+ {
+ return this->generateDH(hSession,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
+ }
+
+ // Generate GOST keys
+ if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN)
+ {
+ return this->generateGOST(hSession,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ phPublicKey, phPrivateKey,
+ ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
+ }
+
+ return CKR_GENERAL_ERROR;
+}
+
+// Internal: Wrap blob using symmetric key
+CK_RV SoftHSM::WrapKeySym
+(
+ CK_MECHANISM_PTR pMechanism,
+ Token* token,
+ OSObject* wrapKey,
+ ByteString& keydata,
+ ByteString& wrapped
+)
+{
+ // Get the symmetric algorithm matching the mechanism
+ SymAlgo::Type algo = SymAlgo::Unknown;
+ SymWrap::Type mode = SymWrap::Unknown;
+ size_t bb = 8;
+#ifdef HAVE_AES_KEY_WRAP
+ CK_ULONG wrappedlen = keydata.size();
+
+ // [PKCS#11 v2.40, 2.14.3 AES Key Wrap]
+ // A key whose length is not a multiple of the AES Key Wrap block
+ // size (8 bytes) will be zero padded to fit.
+ CK_ULONG alignment = wrappedlen % 8;
+ if (alignment != 0)
+ {
+ keydata.resize(wrappedlen + 8 - alignment);
+ memset(&keydata[wrappedlen], 0, 8 - alignment);
+ wrappedlen = keydata.size();
+ }
+#endif
+ switch(pMechanism->mechanism) {
+#ifdef HAVE_AES_KEY_WRAP
+ case CKM_AES_KEY_WRAP:
+ if ((wrappedlen < 16) || ((wrappedlen % 8) != 0))
+ return CKR_KEY_SIZE_RANGE;
+ algo = SymAlgo::AES;
+ mode = SymWrap::AES_KEYWRAP;
+ break;
+#endif
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ case CKM_AES_KEY_WRAP_PAD:
+ algo = SymAlgo::AES;
+ mode = SymWrap::AES_KEYWRAP_PAD;
+ break;
+#endif
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
+ if (cipher == NULL) return CKR_MECHANISM_INVALID;
+
+ SymmetricKey* wrappingkey = new SymmetricKey();
+
+ if (getSymmetricKey(wrappingkey, token, wrapKey) != CKR_OK)
+ {
+ cipher->recycleKey(wrappingkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // adjust key bit length
+ wrappingkey->setBitLen(wrappingkey->getKeyBits().size() * bb);
+
+ // Wrap the key
+ if (!cipher->wrapKey(wrappingkey, mode, keydata, wrapped))
+ {
+ cipher->recycleKey(wrappingkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+
+ cipher->recycleKey(wrappingkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_OK;
+}
+
+// Internal: Wrap blob using asymmetric key
+CK_RV SoftHSM::WrapKeyAsym
+(
+ CK_MECHANISM_PTR pMechanism,
+ Token* token,
+ OSObject* wrapKey,
+ ByteString& keydata,
+ ByteString& wrapped
+)
+{
+ const size_t bb = 8;
+ AsymAlgo::Type algo = AsymAlgo::Unknown;
+ AsymMech::Type mech = AsymMech::Unknown;
+
+ CK_ULONG modulus_length;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ case CKM_RSA_PKCS_OAEP:
+ algo = AsymAlgo::RSA;
+ if (!wrapKey->attributeExists(CKA_MODULUS_BITS))
+ return CKR_GENERAL_ERROR;
+ modulus_length = wrapKey->getUnsignedLongValue(CKA_MODULUS_BITS, 0);
+ // adjust key bit length
+ modulus_length /= bb;
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ mech = AsymMech::RSA_PKCS;
+ // RFC 3447 section 7.2.1
+ if (keydata.size() > modulus_length - 11)
+ return CKR_KEY_SIZE_RANGE;
+ break;
+
+ case CKM_RSA_PKCS_OAEP:
+ mech = AsymMech::RSA_PKCS_OAEP;
+ // SHA-1 is the only supported option
+ // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen
+ if (keydata.size() > modulus_length - 2 - 2 * 160 / 8)
+ return CKR_KEY_SIZE_RANGE;
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
+ if (cipher == NULL) return CKR_MECHANISM_INVALID;
+
+ PublicKey* publicKey = cipher->newPublicKey();
+ if (publicKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
+ return CKR_HOST_MEMORY;
+ }
+
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ case CKM_RSA_PKCS_OAEP:
+ if (getRSAPublicKey((RSAPublicKey*)publicKey, token, wrapKey) != CKR_OK)
+ {
+ cipher->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ // Wrap the key
+ if (!cipher->wrapKey(publicKey, keydata, wrapped, mech))
+ {
+ cipher->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+
+ cipher->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
+
+ return CKR_OK;
+}
+
+
+// Wrap the specified key using the specified wrapping key and mechanism
+CK_RV SoftHSM::C_WrapKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey,
+ CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG_PTR pulWrappedKeyLen
+)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pulWrappedKeyLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ CK_RV rv;
+ // Check the mechanism, only accept advanced AES key wrapping and RSA
+ switch(pMechanism->mechanism)
+ {
+#ifdef HAVE_AES_KEY_WRAP
+ case CKM_AES_KEY_WRAP:
+#endif
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ case CKM_AES_KEY_WRAP_PAD:
+#endif
+ case CKM_RSA_PKCS:
+ // Does not handle optional init vector
+ if (pMechanism->pParameter != NULL_PTR ||
+ pMechanism->ulParameterLen != 0)
+ return CKR_ARGUMENTS_BAD;
+ break;
+ case CKM_RSA_PKCS_OAEP:
+ rv = MechParamCheckRSAPKCSOAEP(pMechanism);
+ if (rv != CKR_OK)
+ return rv;
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the wrapping key handle.
+ OSObject *wrapKey = (OSObject *)handleManager->getObject(hWrappingKey);
+ if (wrapKey == NULL_PTR || !wrapKey->isValid()) return CKR_WRAPPING_KEY_HANDLE_INVALID;
+
+ CK_BBOOL isWrapKeyOnToken = wrapKey->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isWrapKeyPrivate = wrapKey->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check user credentials for the wrapping key
+ rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check wrapping key class and type
+ if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
+ return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
+ return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_AES_KEY_WRAP && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
+ return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
+ return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
+ return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
+
+ // Check if the wrapping key can be used for wrapping
+ if (wrapKey->getBooleanValue(CKA_WRAP, false) == false)
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the wrapping key
+ if (!isMechanismPermitted(wrapKey, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Check the to be wrapped key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
+
+ CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check user credentials for the to be wrapped key
+ rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if the to be wrapped key can be wrapped
+ if (key->getBooleanValue(CKA_EXTRACTABLE, false) == false)
+ return CKR_KEY_UNEXTRACTABLE;
+ if (key->getBooleanValue(CKA_WRAP_WITH_TRUSTED, false) && wrapKey->getBooleanValue(CKA_TRUSTED, false) == false)
+ return CKR_KEY_NOT_WRAPPABLE;
+
+ // Check the class
+ CK_OBJECT_CLASS keyClass = key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
+ if (keyClass != CKO_SECRET_KEY && keyClass != CKO_PRIVATE_KEY)
+ return CKR_KEY_NOT_WRAPPABLE;
+ // CKM_RSA_PKCS and CKM_RSA_PKCS_OAEP can be used only on SECRET keys: PKCS#11 2.40 draft 2 section 2.1.6 PKCS #1 v1.5 RSA & section 2.1.8 PKCS #1 RSA OAEP
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && keyClass != CKO_SECRET_KEY)
+ return CKR_KEY_NOT_WRAPPABLE;
+
+ // Verify the wrap template attribute
+ if (wrapKey->attributeExists(CKA_WRAP_TEMPLATE))
+ {
+ OSAttribute attr = wrapKey->getAttribute(CKA_WRAP_TEMPLATE);
+
+ if (attr.isAttributeMapAttribute())
+ {
+ typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
+
+ const attrmap_type& map = attr.getAttributeMapValue();
+
+ for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
+ {
+ if (!key->attributeExists(it->first))
+ {
+ return CKR_KEY_NOT_WRAPPABLE;
+ }
+
+ OSAttribute keyAttr = key->getAttribute(it->first);
+ ByteString v1, v2;
+ if (!keyAttr.peekValue(v1) || !it->second.peekValue(v2) || (v1 != v2))
+ {
+ return CKR_KEY_NOT_WRAPPABLE;
+ }
+ }
+ }
+ }
+
+ // Get the key data to encrypt
+ ByteString keydata;
+ if (keyClass == CKO_SECRET_KEY)
+ {
+ if (isKeyPrivate)
+ {
+ bool bOK = token->decrypt(key->getByteStringValue(CKA_VALUE), keydata);
+ if (!bOK) return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ keydata = key->getByteStringValue(CKA_VALUE);
+ }
+ }
+ else
+ {
+ CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
+ AsymAlgo::Type alg = AsymAlgo::Unknown;
+ switch (keyType) {
+ case CKK_RSA:
+ alg = AsymAlgo::RSA;
+ break;
+ case CKK_DSA:
+ alg = AsymAlgo::DSA;
+ break;
+ case CKK_DH:
+ alg = AsymAlgo::DH;
+ break;
+#ifdef WITH_ECC
+ case CKK_EC:
+ // can be ecdh too but it doesn't matter
+ alg = AsymAlgo::ECDSA;
+ break;
+#endif
+ default:
+ return CKR_KEY_NOT_WRAPPABLE;
+ }
+ AsymmetricAlgorithm* asymCrypto = NULL;
+ PrivateKey* privateKey = NULL;
+ asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(alg);
+ if (asymCrypto == NULL)
+ return CKR_GENERAL_ERROR;
+ privateKey = asymCrypto->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_HOST_MEMORY;
+ }
+ switch (keyType) {
+ case CKK_RSA:
+ rv = getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key);
+ break;
+ case CKK_DSA:
+ rv = getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key);
+ break;
+ case CKK_DH:
+ rv = getDHPrivateKey((DHPrivateKey*)privateKey, token, key);
+ break;
+#ifdef WITH_ECC
+ case CKK_EC:
+ rv = getECPrivateKey((ECPrivateKey*)privateKey, token, key);
+ break;
+#endif
+ }
+ if (rv != CKR_OK)
+ {
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ return CKR_GENERAL_ERROR;
+ }
+ keydata = privateKey->PKCS8Encode();
+ asymCrypto->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+ }
+ if (keydata.size() == 0)
+ return CKR_KEY_NOT_WRAPPABLE;
+
+ keyClass = wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
+ ByteString wrapped;
+ if (keyClass == CKO_SECRET_KEY)
+ rv = SoftHSM::WrapKeySym(pMechanism, token, wrapKey, keydata, wrapped);
+ else
+ rv = SoftHSM::WrapKeyAsym(pMechanism, token, wrapKey, keydata, wrapped);
+ if (rv != CKR_OK)
+ return rv;
+
+ if (pWrappedKey != NULL) {
+ if (*pulWrappedKeyLen >= wrapped.size())
+ memcpy(pWrappedKey, wrapped.byte_str(), wrapped.size());
+ else
+ rv = CKR_BUFFER_TOO_SMALL;
+ }
+
+ *pulWrappedKeyLen = wrapped.size();
+ return rv;
+}
+
+// Internal: Unwrap blob using symmetric key
+CK_RV SoftHSM::UnwrapKeySym
+(
+ CK_MECHANISM_PTR pMechanism,
+ ByteString& wrapped,
+ Token* token,
+ OSObject* unwrapKey,
+ ByteString& keydata
+)
+{
+ // Get the symmetric algorithm matching the mechanism
+ SymAlgo::Type algo = SymAlgo::Unknown;
+ SymWrap::Type mode = SymWrap::Unknown;
+ size_t bb = 8;
+ switch(pMechanism->mechanism) {
+#ifdef HAVE_AES_KEY_WRAP
+ case CKM_AES_KEY_WRAP:
+ algo = SymAlgo::AES;
+ mode = SymWrap::AES_KEYWRAP;
+ break;
+#endif
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ case CKM_AES_KEY_WRAP_PAD:
+ algo = SymAlgo::AES;
+ mode = SymWrap::AES_KEYWRAP_PAD;
+ break;
+#endif
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
+ if (cipher == NULL) return CKR_MECHANISM_INVALID;
+
+ SymmetricKey* unwrappingkey = new SymmetricKey();
+
+ if (getSymmetricKey(unwrappingkey, token, unwrapKey) != CKR_OK)
+ {
+ cipher->recycleKey(unwrappingkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // adjust key bit length
+ unwrappingkey->setBitLen(unwrappingkey->getKeyBits().size() * bb);
+
+ // Unwrap the key
+ CK_RV rv = CKR_OK;
+ if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata))
+ rv = CKR_GENERAL_ERROR;
+ cipher->recycleKey(unwrappingkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return rv;
+}
+
+// Internal: Unwrap blob using asymmetric key
+CK_RV SoftHSM::UnwrapKeyAsym
+(
+ CK_MECHANISM_PTR pMechanism,
+ ByteString& wrapped,
+ Token* token,
+ OSObject* unwrapKey,
+ ByteString& keydata
+)
+{
+ // Get the symmetric algorithm matching the mechanism
+ AsymAlgo::Type algo = AsymAlgo::Unknown;
+ AsymMech::Type mode = AsymMech::Unknown;
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ algo = AsymAlgo::RSA;
+ mode = AsymMech::RSA_PKCS;
+ break;
+
+ case CKM_RSA_PKCS_OAEP:
+ algo = AsymAlgo::RSA;
+ mode = AsymMech::RSA_PKCS_OAEP;
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+ AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
+ if (cipher == NULL) return CKR_MECHANISM_INVALID;
+
+ PrivateKey* unwrappingkey = cipher->newPrivateKey();
+ if (unwrappingkey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
+ return CKR_HOST_MEMORY;
+ }
+
+ switch(pMechanism->mechanism) {
+ case CKM_RSA_PKCS:
+ case CKM_RSA_PKCS_OAEP:
+ if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK)
+ {
+ cipher->recyclePrivateKey(unwrappingkey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Unwrap the key
+ CK_RV rv = CKR_OK;
+ if (!cipher->unwrapKey(unwrappingkey, wrapped, keydata, mode))
+ rv = CKR_GENERAL_ERROR;
+ cipher->recyclePrivateKey(unwrappingkey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
+ return rv;
+}
+
+// Unwrap the specified key using the specified unwrapping key
+CK_RV SoftHSM::C_UnwrapKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hUnwrappingKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG ulWrappedKeyLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR hKey
+)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pWrappedKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (hKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ CK_RV rv;
+ // Check the mechanism
+ switch(pMechanism->mechanism)
+ {
+#ifdef HAVE_AES_KEY_WRAP
+ case CKM_AES_KEY_WRAP:
+ if ((ulWrappedKeyLen < 24) || ((ulWrappedKeyLen % 8) != 0))
+ return CKR_WRAPPED_KEY_LEN_RANGE;
+ // Does not handle optional init vector
+ if (pMechanism->pParameter != NULL_PTR ||
+ pMechanism->ulParameterLen != 0)
+ return CKR_ARGUMENTS_BAD;
+ break;
+#endif
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ case CKM_AES_KEY_WRAP_PAD:
+ if ((ulWrappedKeyLen < 16) || ((ulWrappedKeyLen % 8) != 0))
+ return CKR_WRAPPED_KEY_LEN_RANGE;
+ // Does not handle optional init vector
+ if (pMechanism->pParameter != NULL_PTR ||
+ pMechanism->ulParameterLen != 0)
+ return CKR_ARGUMENTS_BAD;
+ break;
+#endif
+ case CKM_RSA_PKCS:
+ // Input length checks needs to be done later when unwrapping key is known
+ break;
+ case CKM_RSA_PKCS_OAEP:
+ rv = MechParamCheckRSAPKCSOAEP(pMechanism);
+ if (rv != CKR_OK)
+ return rv;
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the unwrapping key handle.
+ OSObject *unwrapKey = (OSObject *)handleManager->getObject(hUnwrappingKey);
+ if (unwrapKey == NULL_PTR || !unwrapKey->isValid()) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
+
+ CK_BBOOL isUnwrapKeyOnToken = unwrapKey->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check user credentials
+ rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check unwrapping key class and type
+ if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
+ return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_AES_KEY_WRAP && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
+ return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
+ return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
+ return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
+ if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
+ return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
+
+ // Check if the unwrapping key can be used for unwrapping
+ if (unwrapKey->getBooleanValue(CKA_UNWRAP, false) == false)
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the unwrap key
+ if (!isMechanismPermitted(unwrapKey, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Extract information from the template that is needed to create the object.
+ CK_OBJECT_CLASS objClass;
+ CK_KEY_TYPE keyType;
+ CK_BBOOL isOnToken = CK_FALSE;
+ CK_BBOOL isPrivate = CK_TRUE;
+ CK_CERTIFICATE_TYPE dummy;
+ bool isImplicit = false;
+ rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
+ if (rv != CKR_OK)
+ {
+ ERROR_MSG("Mandatory attribute not present in template");
+ return rv;
+ }
+
+ // Report errors and/or unexpected usage.
+ if (objClass != CKO_SECRET_KEY && objClass != CKO_PRIVATE_KEY)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ // Key type will be handled at object creation
+
+ // Check authorization
+ rv = haveWrite(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Build unwrapped key template
+ const CK_ULONG maxAttribs = 32;
+ CK_ATTRIBUTE secretAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) }
+ };
+ CK_ULONG secretAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - secretAttribsCount))
+ return CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i = 0; i < ulCount; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ secretAttribs[secretAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ // Apply the unwrap template
+ if (unwrapKey->attributeExists(CKA_UNWRAP_TEMPLATE))
+ {
+ OSAttribute unwrapAttr = unwrapKey->getAttribute(CKA_UNWRAP_TEMPLATE);
+
+ if (unwrapAttr.isAttributeMapAttribute())
+ {
+ typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
+
+ const attrmap_type& map = unwrapAttr.getAttributeMapValue();
+
+ for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
+ {
+ CK_ATTRIBUTE* attr = NULL;
+ for (CK_ULONG i = 0; i < secretAttribsCount; ++i)
+ {
+ if (it->first == secretAttribs[i].type)
+ {
+ if (attr != NULL)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ attr = &secretAttribs[i];
+ ByteString value;
+ it->second.peekValue(value);
+ if (attr->ulValueLen != value.size())
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ if (memcmp(attr->pValue, value.const_byte_str(), value.size()) != 0)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+ }
+ if (attr == NULL)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+ }
+ }
+
+ *hKey = CK_INVALID_HANDLE;
+
+ // Unwrap the key
+ ByteString wrapped(pWrappedKey, ulWrappedKeyLen);
+ ByteString keydata;
+ if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
+ rv = UnwrapKeySym(pMechanism, wrapped, token, unwrapKey, keydata);
+ else if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
+ rv = UnwrapKeyAsym(pMechanism, wrapped, token, unwrapKey, keydata);
+ else
+ rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
+ if (rv != CKR_OK)
+ return rv;
+
+ // Create the secret object using C_CreateObject
+ rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, hKey, OBJECT_OP_UNWRAP);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*hKey);
+ if (osobject == NULL_PTR || !osobject->isValid())
+ rv = CKR_FUNCTION_FAILED;
+ if (osobject->startTransaction())
+ {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL, false);
+
+ // Common Secret Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, false);
+
+ // Secret Attributes
+ if (objClass == CKO_SECRET_KEY)
+ {
+ ByteString value;
+ if (isPrivate)
+ token->encrypt(keydata, value);
+ else
+ value = keydata;
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ }
+ else if (keyType == CKK_RSA)
+ {
+ bOK = bOK && setRSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
+ }
+ else if (keyType == CKK_DSA)
+ {
+ bOK = bOK && setDSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
+ }
+ else if (keyType == CKK_DH)
+ {
+ bOK = bOK && setDHPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
+ }
+ else if (keyType == CKK_EC)
+ {
+ bOK = bOK && setECPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
+ }
+ else
+ bOK = false;
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ }
+ else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Remove secret that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*hKey != CK_INVALID_HANDLE)
+ {
+ OSObject* obj = (OSObject*)handleManager->getObject(*hKey);
+ handleManager->destroyObject(*hKey);
+ if (obj) obj->destroyObject();
+ *hKey = CK_INVALID_HANDLE;
+ }
+
+ }
+
+ return rv;
+}
+
+// Derive a key from the specified base key
+CK_RV SoftHSM::C_DeriveKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey
+)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check the mechanism, only accept DH and ECDH derive
+ switch (pMechanism->mechanism)
+ {
+ case CKM_DH_PKCS_DERIVE:
+#ifdef WITH_ECC
+ case CKM_ECDH1_DERIVE:
+#endif
+#ifndef WITH_FIPS
+ case CKM_DES_ECB_ENCRYPT_DATA:
+ case CKM_DES_CBC_ENCRYPT_DATA:
+#endif
+ case CKM_DES3_ECB_ENCRYPT_DATA:
+ case CKM_DES3_CBC_ENCRYPT_DATA:
+ case CKM_AES_ECB_ENCRYPT_DATA:
+ case CKM_AES_CBC_ENCRYPT_DATA:
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism");
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL) return CKR_GENERAL_ERROR;
+
+ // Check the key handle.
+ OSObject *key = (OSObject *)handleManager->getObject(hBaseKey);
+ if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
+ CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
+
+ // Check user credentials
+ CK_RV rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+
+ return rv;
+ }
+
+ // Check if key can be used for derive
+ if (!key->getBooleanValue(CKA_DERIVE, false))
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+
+ // Check if the specified mechanism is allowed for the key
+ if (!isMechanismPermitted(key, pMechanism))
+ return CKR_MECHANISM_INVALID;
+
+ // Extract information from the template that is needed to create the object.
+ CK_OBJECT_CLASS objClass;
+ CK_KEY_TYPE keyType;
+ CK_BBOOL isOnToken = CK_FALSE;
+ CK_BBOOL isPrivate = CK_TRUE;
+ CK_CERTIFICATE_TYPE dummy;
+ bool isImplicit = false;
+ rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
+ if (rv != CKR_OK)
+ {
+ ERROR_MSG("Mandatory attribute not present in template");
+ return rv;
+ }
+
+ // Report errors and/or unexpected usage.
+ if (objClass != CKO_SECRET_KEY)
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ if (keyType != CKK_GENERIC_SECRET &&
+ keyType != CKK_DES &&
+ keyType != CKK_DES2 &&
+ keyType != CKK_DES3 &&
+ keyType != CKK_AES)
+ return CKR_TEMPLATE_INCONSISTENT;
+
+ // Check authorization
+ rv = haveWrite(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Derive DH secret
+ if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE)
+ {
+ // Check key class and type
+ if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ return this->deriveDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
+ }
+
+#ifdef WITH_ECC
+ // Derive ECDH secret
+ if (pMechanism->mechanism == CKM_ECDH1_DERIVE)
+ {
+ // Check key class and type
+ if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ return this->deriveECDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
+ }
+#endif
+
+ // Derive symmetric secret
+ if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
+ pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
+ pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA ||
+ pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA ||
+ pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA ||
+ pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA)
+ {
+ // Check key class and type
+ CK_KEY_TYPE baseKeyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
+ if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA &&
+ baseKeyType != CKK_DES)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA &&
+ baseKeyType != CKK_DES)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA &&
+ baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA &&
+ baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
+ baseKeyType != CKK_AES)
+ return CKR_KEY_TYPE_INCONSISTENT;
+ if (pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA &&
+ baseKeyType != CKK_AES)
+ return CKR_KEY_TYPE_INCONSISTENT;
+
+ return this->deriveSymmetric(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
+ }
+
+ return CKR_MECHANISM_INVALID;
+}
+
+// Seed the random number generator with new data
+CK_RV SoftHSM::C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pSeed == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the RNG
+ RNG* rng = CryptoFactory::i()->getRNG();
+ if (rng == NULL) return CKR_GENERAL_ERROR;
+
+ // Seed the RNG
+ ByteString seed(pSeed, ulSeedLen);
+ rng->seed(seed);
+
+ return CKR_OK;
+}
+
+// Generate the specified amount of random data
+CK_RV SoftHSM::C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pRandomData == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the RNG
+ RNG* rng = CryptoFactory::i()->getRNG();
+ if (rng == NULL) return CKR_GENERAL_ERROR;
+
+ // Generate random data
+ ByteString randomData;
+ if (!rng->generateRandom(randomData, ulRandomLen)) return CKR_GENERAL_ERROR;
+
+ // Return random data
+ if (ulRandomLen != 0)
+ {
+ memcpy(pRandomData, randomData.byte_str(), ulRandomLen);
+ }
+
+ return CKR_OK;
+}
+
+// Legacy function
+CK_RV SoftHSM::C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+// Legacy function
+CK_RV SoftHSM::C_CancelFunction(CK_SESSION_HANDLE hSession)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return CKR_FUNCTION_NOT_PARALLEL;
+}
+
+// Wait or poll for a slot event on the specified slot
+CK_RV SoftHSM::C_WaitForSlotEvent(CK_FLAGS /*flags*/, CK_SLOT_ID_PTR /*pSlot*/, CK_VOID_PTR /*pReserved*/)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+// Generate an AES secret key
+CK_RV SoftHSM::generateAES
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+ *phKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ size_t keyLen = 0;
+ bool checkValue = true;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_VALUE_LEN:
+ if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ keyLen = *(CK_ULONG*)pTemplate[i].pValue;
+ break;
+ case CKA_CHECK_VALUE:
+ if (pTemplate[i].ulValueLen > 0)
+ {
+ INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ checkValue = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // CKA_VALUE_LEN must be specified
+ if (keyLen == 0)
+ {
+ INFO_MSG("Missing CKA_VALUE_LEN in pTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // keyLen must be 16, 24, or 32
+ if (keyLen != 16 && keyLen != 24 && keyLen != 32)
+ {
+ INFO_MSG("bad AES key length");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Generate the secret key
+ AESKey* key = new AESKey(keyLen * 8);
+ SymmetricAlgorithm* aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
+ if (aes == NULL)
+ {
+ ERROR_MSG("Could not get SymmetricAlgorithm");
+ delete key;
+ return CKR_GENERAL_ERROR;
+ }
+ RNG* rng = CryptoFactory::i()->getRNG();
+ if (rng == NULL)
+ {
+ ERROR_MSG("Could not get RNG");
+ aes->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
+ return CKR_GENERAL_ERROR;
+ }
+ if (!aes->generateKey(*key, rng))
+ {
+ ERROR_MSG("Could not generate AES secret key");
+ aes->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
+ return CKR_GENERAL_ERROR;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ // Create the secret key object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_AES;
+ CK_ATTRIBUTE keyAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG keyAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - keyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ case CKA_CHECK_VALUE:
+ continue;
+ default:
+ keyAttribs[keyAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_AES_KEY_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Secret Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // AES Secret Key Attributes
+ ByteString value;
+ ByteString kcv;
+ if (isPrivate)
+ {
+ token->encrypt(key->getKeyBits(), value);
+ token->encrypt(key->getKeyCheckValue(), kcv);
+ }
+ else
+ {
+ value = key->getKeyBits();
+ kcv = key->getKeyCheckValue();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ if (checkValue)
+ bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Clean up
+ aes->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
+
+ // Remove the key that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (oskey) oskey->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate a DES secret key
+CK_RV SoftHSM::generateDES
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+ *phKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ bool checkValue = true;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CHECK_VALUE:
+ if (pTemplate[i].ulValueLen > 0)
+ {
+ INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ checkValue = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Generate the secret key
+ DESKey* key = new DESKey(56);
+ SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES);
+ if (des == NULL)
+ {
+ ERROR_MSG("Could not get SymmetricAlgorithm");
+ delete key;
+ return CKR_GENERAL_ERROR;
+ }
+ RNG* rng = CryptoFactory::i()->getRNG();
+ if (rng == NULL)
+ {
+ ERROR_MSG("Could not get RNG");
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+ return CKR_GENERAL_ERROR;
+ }
+ if (!des->generateKey(*key, rng))
+ {
+ ERROR_MSG("Could not generate DES secret key");
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+ return CKR_GENERAL_ERROR;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ // Create the secret key object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_DES;
+ CK_ATTRIBUTE keyAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG keyAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - keyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ case CKA_CHECK_VALUE:
+ continue;
+ default:
+ keyAttribs[keyAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES_KEY_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Secret Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // DES Secret Key Attributes
+ ByteString value;
+ ByteString kcv;
+ if (isPrivate)
+ {
+ token->encrypt(key->getKeyBits(), value);
+ token->encrypt(key->getKeyCheckValue(), kcv);
+ }
+ else
+ {
+ value = key->getKeyBits();
+ kcv = key->getKeyCheckValue();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ if (checkValue)
+ bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Clean up
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+
+ // Remove the key that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (oskey) oskey->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate a DES2 secret key
+CK_RV SoftHSM::generateDES2
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+ *phKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ bool checkValue = true;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CHECK_VALUE:
+ if (pTemplate[i].ulValueLen > 0)
+ {
+ INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ checkValue = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Generate the secret key
+ DESKey* key = new DESKey(112);
+ SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
+ if (des == NULL)
+ {
+ ERROR_MSG("Could not get SymmetricAlgorith");
+ delete key;
+ return CKR_GENERAL_ERROR;
+ }
+ RNG* rng = CryptoFactory::i()->getRNG();
+ if (rng == NULL)
+ {
+ ERROR_MSG("Could not get RNG");
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+ return CKR_GENERAL_ERROR;
+ }
+ if (!des->generateKey(*key, rng))
+ {
+ ERROR_MSG("Could not generate DES secret key");
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+ return CKR_GENERAL_ERROR;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ // Create the secret key object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_DES2;
+ CK_ATTRIBUTE keyAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG keyAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - keyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ case CKA_CHECK_VALUE:
+ continue;
+ default:
+ keyAttribs[keyAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES2_KEY_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Secret Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // DES Secret Key Attributes
+ ByteString value;
+ ByteString kcv;
+ if (isPrivate)
+ {
+ token->encrypt(key->getKeyBits(), value);
+ token->encrypt(key->getKeyCheckValue(), kcv);
+ }
+ else
+ {
+ value = key->getKeyBits();
+ kcv = key->getKeyCheckValue();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ if (checkValue)
+ bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Clean up
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+
+ // Remove the key that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (oskey) oskey->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate a DES3 secret key
+CK_RV SoftHSM::generateDES3
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+ *phKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ bool checkValue = true;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CHECK_VALUE:
+ if (pTemplate[i].ulValueLen > 0)
+ {
+ INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ checkValue = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Generate the secret key
+ DESKey* key = new DESKey(168);
+ SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
+ if (des == NULL)
+ {
+ ERROR_MSG("Could not get SymmetricAlgorithm");
+ delete key;
+ return CKR_GENERAL_ERROR;
+ }
+ RNG* rng = CryptoFactory::i()->getRNG();
+ if (rng == NULL)
+ {
+ ERROR_MSG("Could not get RNG");
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+ return CKR_GENERAL_ERROR;
+ }
+ if (!des->generateKey(*key, rng))
+ {
+ ERROR_MSG("Could not generate DES secret key");
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+ return CKR_GENERAL_ERROR;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ // Create the secret key object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_DES3;
+ CK_ATTRIBUTE keyAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG keyAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - keyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ case CKA_CHECK_VALUE:
+ continue;
+ default:
+ keyAttribs[keyAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES3_KEY_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Secret Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // DES Secret Key Attributes
+ ByteString value;
+ ByteString kcv;
+ if (isPrivate)
+ {
+ token->encrypt(key->getKeyBits(), value);
+ token->encrypt(key->getKeyCheckValue(), kcv);
+ }
+ else
+ {
+ value = key->getKeyBits();
+ kcv = key->getKeyCheckValue();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ if (checkValue)
+ bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Clean up
+ des->recycleKey(key);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+
+ // Remove the key that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (oskey) oskey->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate an RSA key pair
+CK_RV SoftHSM::generateRSA
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+)
+{
+ *phPublicKey = CK_INVALID_HANDLE;
+ *phPrivateKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired key information: bitlen and public exponent
+ size_t bitLen = 0;
+ ByteString exponent("010001");
+ for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_MODULUS_BITS:
+ if (pPublicKeyTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_MODULUS_BITS does not have the size of CK_ULONG");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ bitLen = *(CK_ULONG*)pPublicKeyTemplate[i].pValue;
+ break;
+ case CKA_PUBLIC_EXPONENT:
+ exponent = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // CKA_MODULUS_BITS must be specified to be able to generate a key pair.
+ if (bitLen == 0) {
+ INFO_MSG("Missing CKA_MODULUS_BITS in pPublicKeyTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // Set the parameters
+ RSAParameters p;
+ p.setE(exponent);
+ p.setBitLength(bitLen);
+
+ // Generate key pair
+ AsymmetricKeyPair* kp = NULL;
+ AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
+ if (rsa == NULL)
+ return CKR_GENERAL_ERROR;
+ if (!rsa->generateKeyPair(&kp, &p))
+ {
+ ERROR_MSG("Could not generate key pair");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+ return CKR_GENERAL_ERROR;
+ }
+
+ RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
+ RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
+
+ CK_RV rv = CKR_OK;
+
+ // Create a public key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE publicKeyType = CKK_RSA;
+ CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
+ { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
+ { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
+ { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
+ };
+ CK_ULONG publicKeyAttribsCount = 4;
+
+ // Add the additional
+ if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ case CKA_PUBLIC_EXPONENT:
+ continue;
+ default:
+ publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // RSA Public Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ if (isPublicKeyPrivate)
+ {
+ token->encrypt(pub->getN(), modulus);
+ token->encrypt(pub->getE(), publicExponent);
+ }
+ else
+ {
+ modulus = pub->getN();
+ publicExponent = pub->getE();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
+ bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Create a private key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE privateKeyType = CKK_RSA;
+ CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
+ { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
+ { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
+ { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
+ };
+ CK_ULONG privateKeyAttribsCount = 4;
+ if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPrivateKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Private Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // RSA Private Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ ByteString privateExponent;
+ ByteString prime1;
+ ByteString prime2;
+ ByteString exponent1;
+ ByteString exponent2;
+ ByteString coefficient;
+ if (isPrivateKeyPrivate)
+ {
+ token->encrypt(priv->getN(), modulus);
+ token->encrypt(priv->getE(), publicExponent);
+ token->encrypt(priv->getD(), privateExponent);
+ token->encrypt(priv->getP(), prime1);
+ token->encrypt(priv->getQ(), prime2);
+ token->encrypt(priv->getDP1(), exponent1);
+ token->encrypt(priv->getDQ1(), exponent2);
+ token->encrypt(priv->getPQ(), coefficient);
+ }
+ else
+ {
+ modulus = priv->getN();
+ publicExponent = priv->getE();
+ privateExponent = priv->getD();
+ prime1 = priv->getP();
+ prime2 = priv->getQ();
+ exponent1 = priv->getDP1();
+ exponent2 = priv->getDQ1();
+ coefficient = priv->getPQ();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
+ bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
+ bOK = bOK && osobject->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
+ bOK = bOK && osobject->setAttribute(CKA_PRIME_1, prime1);
+ bOK = bOK && osobject->setAttribute(CKA_PRIME_2, prime2);
+ bOK = bOK && osobject->setAttribute(CKA_EXPONENT_1,exponent1);
+ bOK = bOK && osobject->setAttribute(CKA_EXPONENT_2, exponent2);
+ bOK = bOK && osobject->setAttribute(CKA_COEFFICIENT, coefficient);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Clean up
+ rsa->recycleKeyPair(kp);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+
+ // Remove keys that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phPrivateKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
+ handleManager->destroyObject(*phPrivateKey);
+ if (ospriv) ospriv->destroyObject();
+ *phPrivateKey = CK_INVALID_HANDLE;
+ }
+
+ if (*phPublicKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
+ handleManager->destroyObject(*phPublicKey);
+ if (ospub) ospub->destroyObject();
+ *phPublicKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate a DSA key pair
+CK_RV SoftHSM::generateDSA
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate)
+{
+ *phPublicKey = CK_INVALID_HANDLE;
+ *phPrivateKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired key information
+ ByteString prime;
+ ByteString subprime;
+ ByteString generator;
+ for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_PRIME:
+ prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ case CKA_SUBPRIME:
+ subprime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ case CKA_BASE:
+ generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // The parameters must be specified to be able to generate a key pair.
+ if (prime.size() == 0 || subprime.size() == 0 || generator.size() == 0) {
+ INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // Set the parameters
+ DSAParameters p;
+ p.setP(prime);
+ p.setQ(subprime);
+ p.setG(generator);
+
+ // Generate key pair
+ AsymmetricKeyPair* kp = NULL;
+ AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
+ if (dsa == NULL) return CKR_GENERAL_ERROR;
+ if (!dsa->generateKeyPair(&kp, &p))
+ {
+ ERROR_MSG("Could not generate key pair");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+ return CKR_GENERAL_ERROR;
+ }
+
+ DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
+ DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
+
+ CK_RV rv = CKR_OK;
+
+ // Create a public key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE publicKeyType = CKK_DSA;
+ CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
+ { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
+ { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
+ { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
+ };
+ CK_ULONG publicKeyAttribsCount = 4;
+
+ // Add the additional
+ if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // DSA Public Key Attributes
+ ByteString value;
+ if (isPublicKeyPrivate)
+ {
+ token->encrypt(pub->getY(), value);
+ }
+ else
+ {
+ value = pub->getY();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Create a private key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE privateKeyType = CKK_DSA;
+ CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
+ { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
+ { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
+ { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
+ };
+ CK_ULONG privateKeyAttribsCount = 4;
+ if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPrivateKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Private Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // DSA Private Key Attributes
+ ByteString bPrime;
+ ByteString bSubprime;
+ ByteString bGenerator;
+ ByteString bValue;
+ if (isPrivateKeyPrivate)
+ {
+ token->encrypt(priv->getP(), bPrime);
+ token->encrypt(priv->getQ(), bSubprime);
+ token->encrypt(priv->getG(), bGenerator);
+ token->encrypt(priv->getX(), bValue);
+ }
+ else
+ {
+ bPrime = priv->getP();
+ bSubprime = priv->getQ();
+ bGenerator = priv->getG();
+ bValue = priv->getX();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
+ bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, bSubprime);
+ bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Clean up
+ dsa->recycleKeyPair(kp);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+
+ // Remove keys that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phPrivateKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
+ handleManager->destroyObject(*phPrivateKey);
+ if (ospriv) ospriv->destroyObject();
+ *phPrivateKey = CK_INVALID_HANDLE;
+ }
+
+ if (*phPublicKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
+ handleManager->destroyObject(*phPublicKey);
+ if (ospub) ospub->destroyObject();
+ *phPublicKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate a DSA domain parameter set
+CK_RV SoftHSM::generateDSAParameters
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+ *phKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ size_t bitLen = 0;
+ size_t qLen = 0;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_PRIME_BITS:
+ if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ bitLen = *(CK_ULONG*)pTemplate[i].pValue;
+ break;
+ case CKA_SUBPRIME_BITS:
+ if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_SUBPRIME_BITS does not have the size of CK_ULONG");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ qLen = *(CK_ULONG*)pTemplate[i].pValue;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // CKA_PRIME_BITS must be specified
+ if (bitLen == 0)
+ {
+ INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // No real choice for CKA_SUBPRIME_BITS
+ if ((qLen != 0) &&
+ (((bitLen >= 2048) && (qLen != 256)) ||
+ ((bitLen < 2048) && (qLen != 160))))
+ INFO_MSG("CKA_SUBPRIME_BITS is ignored");
+
+
+ // Generate domain parameters
+ AsymmetricParameters* p = NULL;
+ AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
+ if (dsa == NULL) return CKR_GENERAL_ERROR;
+ if (!dsa->generateParameters(&p, (void *)bitLen))
+ {
+ ERROR_MSG("Could not generate parameters");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+ return CKR_GENERAL_ERROR;
+ }
+
+ DSAParameters* params = (DSAParameters*) p;
+
+ CK_RV rv = CKR_OK;
+
+ // Create the domain parameter object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
+ CK_KEY_TYPE keyType = CKK_DSA;
+ CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG paramsAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - paramsAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ paramsAttribs[paramsAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_PARAMETER_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // DSA Domain Parameters Attributes
+ ByteString prime;
+ ByteString subprime;
+ ByteString generator;
+ if (isPrivate)
+ {
+ token->encrypt(params->getP(), prime);
+ token->encrypt(params->getQ(), subprime);
+ token->encrypt(params->getG(), generator);
+ }
+ else
+ {
+ prime = params->getP();
+ subprime = params->getQ();
+ generator = params->getG();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
+ bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, subprime);
+ bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Clean up
+ dsa->recycleParameters(p);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+
+ // Remove parameters that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (osparams) osparams->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate an EC key pair
+CK_RV SoftHSM::generateEC
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate)
+{
+ *phPublicKey = CK_INVALID_HANDLE;
+ *phPrivateKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired key information
+ ByteString params;
+ for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_EC_PARAMS:
+ params = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // The parameters must be specified to be able to generate a key pair.
+ if (params.size() == 0) {
+ INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // Set the parameters
+ ECParameters p;
+ p.setEC(params);
+
+ // Generate key pair
+ AsymmetricKeyPair* kp = NULL;
+ AsymmetricAlgorithm* ec = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
+ if (ec == NULL) return CKR_GENERAL_ERROR;
+ if (!ec->generateKeyPair(&kp, &p))
+ {
+ ERROR_MSG("Could not generate key pair");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
+ return CKR_GENERAL_ERROR;
+ }
+
+ ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
+ ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
+
+ CK_RV rv = CKR_OK;
+
+ // Create a public key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE publicKeyType = CKK_EC;
+ CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
+ { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
+ { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
+ { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
+ };
+ CK_ULONG publicKeyAttribsCount = 4;
+
+ // Add the additional
+ if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // EC Public Key Attributes
+ ByteString point;
+ if (isPublicKeyPrivate)
+ {
+ token->encrypt(pub->getQ(), point);
+ }
+ else
+ {
+ point = pub->getQ();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_EC_POINT, point);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Create a private key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE privateKeyType = CKK_EC;
+ CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
+ { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
+ { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
+ { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
+ };
+ CK_ULONG privateKeyAttribsCount = 4;
+ if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPrivateKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Private Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // EC Private Key Attributes
+ ByteString group;
+ ByteString value;
+ if (isPrivateKeyPrivate)
+ {
+ token->encrypt(priv->getEC(), group);
+ token->encrypt(priv->getD(), value);
+ }
+ else
+ {
+ group = priv->getEC();
+ value = priv->getD();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_EC_PARAMS, group);
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Clean up
+ ec->recycleKeyPair(kp);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
+
+ // Remove keys that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phPrivateKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
+ handleManager->destroyObject(*phPrivateKey);
+ if (ospriv) ospriv->destroyObject();
+ *phPrivateKey = CK_INVALID_HANDLE;
+ }
+
+ if (*phPublicKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
+ handleManager->destroyObject(*phPublicKey);
+ if (ospub) ospub->destroyObject();
+ *phPublicKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate a DH key pair
+CK_RV SoftHSM::generateDH
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate)
+{
+ *phPublicKey = CK_INVALID_HANDLE;
+ *phPrivateKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired key information
+ ByteString prime;
+ ByteString generator;
+ for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_PRIME:
+ prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ case CKA_BASE:
+ generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // The parameters must be specified to be able to generate a key pair.
+ if (prime.size() == 0 || generator.size() == 0) {
+ INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // Extract optional bit length
+ size_t bitLen = 0;
+ for (CK_ULONG i = 0; i < ulPrivateKeyAttributeCount; i++)
+ {
+ switch (pPrivateKeyTemplate[i].type)
+ {
+ case CKA_VALUE_BITS:
+ bitLen = *(CK_ULONG*)pPrivateKeyTemplate[i].pValue;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Set the parameters
+ DHParameters p;
+ p.setP(prime);
+ p.setG(generator);
+ p.setXBitLength(bitLen);
+
+ // Generate key pair
+ AsymmetricKeyPair* kp = NULL;
+ AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
+ if (dh == NULL) return CKR_GENERAL_ERROR;
+ if (!dh->generateKeyPair(&kp, &p))
+ {
+ ERROR_MSG("Could not generate key pair");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ return CKR_GENERAL_ERROR;
+ }
+
+ DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey();
+ DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
+
+ CK_RV rv = CKR_OK;
+
+ // Create a public key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE publicKeyType = CKK_DH;
+ CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
+ { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
+ { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
+ { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
+ };
+ CK_ULONG publicKeyAttribsCount = 4;
+
+ // Add the additional
+ if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // DH Public Key Attributes
+ ByteString value;
+ if (isPublicKeyPrivate)
+ {
+ token->encrypt(pub->getY(), value);
+ }
+ else
+ {
+ value = pub->getY();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Create a private key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE privateKeyType = CKK_DH;
+ CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
+ { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
+ { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
+ { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
+ };
+ CK_ULONG privateKeyAttribsCount = 4;
+ if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPrivateKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Private Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // DH Private Key Attributes
+ ByteString bPrime;
+ ByteString bGenerator;
+ ByteString bValue;
+ if (isPrivateKeyPrivate)
+ {
+ token->encrypt(priv->getP(), bPrime);
+ token->encrypt(priv->getG(), bGenerator);
+ token->encrypt(priv->getX(), bValue);
+ }
+ else
+ {
+ bPrime = priv->getP();
+ bGenerator = priv->getG();
+ bValue = priv->getX();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
+ bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
+
+ if (bitLen == 0)
+ {
+ bOK = bOK && osobject->setAttribute(CKA_VALUE_BITS, (unsigned long)priv->getX().bits());
+ }
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Clean up
+ dh->recycleKeyPair(kp);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+
+ // Remove keys that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phPrivateKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
+ handleManager->destroyObject(*phPrivateKey);
+ if (ospriv) ospriv->destroyObject();
+ *phPrivateKey = CK_INVALID_HANDLE;
+ }
+
+ if (*phPublicKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
+ handleManager->destroyObject(*phPublicKey);
+ if (ospub) ospub->destroyObject();
+ *phPublicKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate a DH domain parameter set
+CK_RV SoftHSM::generateDHParameters
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+ *phKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ size_t bitLen = 0;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_PRIME_BITS:
+ if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ bitLen = *(CK_ULONG*)pTemplate[i].pValue;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // CKA_PRIME_BITS must be specified
+ if (bitLen == 0)
+ {
+ INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // Generate domain parameters
+ AsymmetricParameters* p = NULL;
+ AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
+ if (dh == NULL) return CKR_GENERAL_ERROR;
+ if (!dh->generateParameters(&p, (void *)bitLen))
+ {
+ ERROR_MSG("Could not generate parameters");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ return CKR_GENERAL_ERROR;
+ }
+
+ DHParameters* params = (DHParameters*) p;
+
+ CK_RV rv = CKR_OK;
+
+ // Create the domain parameter object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
+ CK_KEY_TYPE keyType = CKK_DH;
+ CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG paramsAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - paramsAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ paramsAttribs[paramsAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_PARAMETER_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // DH Domain Parameters Attributes
+ ByteString prime;
+ ByteString generator;
+ if (isPrivate)
+ {
+ token->encrypt(params->getP(), prime);
+ token->encrypt(params->getG(), generator);
+ }
+ else
+ {
+ prime = params->getP();
+ generator = params->getG();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
+ bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Clean up
+ dh->recycleParameters(p);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+
+ // Remove parameters that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (osparams) osparams->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Generate a GOST key pair
+CK_RV SoftHSM::generateGOST
+(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate)
+{
+ *phPublicKey = CK_INVALID_HANDLE;
+ *phPrivateKey = CK_INVALID_HANDLE;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired key information
+ ByteString param_3410;
+ ByteString param_3411;
+ ByteString param_28147;
+ for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_GOSTR3410_PARAMS:
+ param_3410 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ case CKA_GOSTR3411_PARAMS:
+ param_3411 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ case CKA_GOST28147_PARAMS:
+ param_28147 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // The parameters must be specified to be able to generate a key pair.
+ if (param_3410.size() == 0 || param_3411.size() == 0) {
+ INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ // Set the parameters
+ ECParameters p;
+ p.setEC(param_3410);
+
+ // Generate key pair
+ AsymmetricKeyPair* kp = NULL;
+ AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
+ if (gost == NULL) return CKR_GENERAL_ERROR;
+ if (!gost->generateKeyPair(&kp, &p))
+ {
+ ERROR_MSG("Could not generate key pair");
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
+ return CKR_GENERAL_ERROR;
+ }
+
+ GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey();
+ GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey();
+
+ CK_RV rv = CKR_OK;
+
+ // Create a public key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE publicKeyType = CKK_GOSTR3410;
+ CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
+ { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
+ { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
+ { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
+ };
+ CK_ULONG publicKeyAttribsCount = 4;
+
+ // Add the additional
+ if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPublicKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // EC Public Key Attributes
+ ByteString point;
+ if (isPublicKeyPrivate)
+ {
+ token->encrypt(pub->getQ(), point);
+ }
+ else
+ {
+ point = pub->getQ();
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, point);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Create a private key using C_CreateObject
+ if (rv == CKR_OK)
+ {
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE privateKeyType = CKK_GOSTR3410;
+ CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
+ { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
+ { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
+ { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
+ { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
+ };
+ CK_ULONG privateKeyAttribsCount = 4;
+ if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
+ {
+ switch (pPrivateKeyTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ continue;
+ default:
+ privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
+
+ // Store the attributes that are being supplied by the key generation to the object
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Key Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
+ CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
+ bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
+
+ // Common Private Key Attributes
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
+
+ // GOST Private Key Attributes
+ ByteString value;
+ ByteString param_a;
+ ByteString param_b;
+ ByteString param_c;
+ if (isPrivateKeyPrivate)
+ {
+ token->encrypt(priv->getD(), value);
+ token->encrypt(priv->getEC(), param_a);
+ token->encrypt(param_3411, param_b);
+ token->encrypt(param_28147, param_c);
+ }
+ else
+ {
+ value = priv->getD();
+ param_a = priv->getEC();
+ param_b = param_3411;
+ param_c = param_28147;
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ bOK = bOK && osobject->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
+ bOK = bOK && osobject->setAttribute(CKA_GOSTR3411_PARAMS, param_b);
+ bOK = bOK && osobject->setAttribute(CKA_GOST28147_PARAMS, param_c);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+
+ // Clean up
+ gost->recycleKeyPair(kp);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
+
+ // Remove keys that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phPrivateKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
+ handleManager->destroyObject(*phPrivateKey);
+ if (ospriv) ospriv->destroyObject();
+ *phPrivateKey = CK_INVALID_HANDLE;
+ }
+
+ if (*phPublicKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
+ handleManager->destroyObject(*phPublicKey);
+ if (ospub) ospub->destroyObject();
+ *phPublicKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Derive a DH secret
+CK_RV SoftHSM::deriveDH
+(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_KEY_TYPE keyType,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+ *phKey = CK_INVALID_HANDLE;
+
+ if (pMechanism->pParameter == NULL_PTR) return CKR_MECHANISM_PARAM_INVALID;
+ if (pMechanism->ulParameterLen == 0) return CKR_MECHANISM_PARAM_INVALID;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ size_t byteLen = 0;
+ bool checkValue = true;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_VALUE:
+ INFO_MSG("CKA_VALUE must not be included");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ case CKA_VALUE_LEN:
+ if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ byteLen = *(CK_ULONG*)pTemplate[i].pValue;
+ break;
+ case CKA_CHECK_VALUE:
+ if (pTemplate[i].ulValueLen > 0)
+ {
+ INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ checkValue = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Check the length
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ if (byteLen == 0)
+ {
+ INFO_MSG("CKA_VALUE_LEN must be set");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ break;
+#ifndef WITH_FIPS
+ case CKK_DES:
+ if (byteLen != 0)
+ {
+ INFO_MSG("CKA_VALUE_LEN must not be set");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ byteLen = 8;
+ break;
+#endif
+ case CKK_DES2:
+ if (byteLen != 0)
+ {
+ INFO_MSG("CKA_VALUE_LEN must not be set");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ byteLen = 16;
+ break;
+ case CKK_DES3:
+ if (byteLen != 0)
+ {
+ INFO_MSG("CKA_VALUE_LEN must not be set");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ byteLen = 24;
+ break;
+ case CKK_AES:
+ if (byteLen != 16 && byteLen != 24 && byteLen != 32)
+ {
+ INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ break;
+ default:
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Get the base key handle
+ OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
+ if (baseKey == NULL || !baseKey->isValid())
+ return CKR_KEY_HANDLE_INVALID;
+
+ // Get the DH algorithm handler
+ AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
+ if (dh == NULL)
+ return CKR_MECHANISM_INVALID;
+
+ // Get the keys
+ PrivateKey* privateKey = dh->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ return CKR_HOST_MEMORY;
+ }
+ if (getDHPrivateKey((DHPrivateKey*)privateKey, token, baseKey) != CKR_OK)
+ {
+ dh->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ return CKR_GENERAL_ERROR;
+ }
+
+ ByteString mechParameters;
+ mechParameters.resize(pMechanism->ulParameterLen);
+ memcpy(&mechParameters[0], pMechanism->pParameter, pMechanism->ulParameterLen);
+ PublicKey* publicKey = dh->newPublicKey();
+ if (publicKey == NULL)
+ {
+ dh->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ return CKR_HOST_MEMORY;
+ }
+ if (getDHPublicKey((DHPublicKey*)publicKey, (DHPrivateKey*)privateKey, mechParameters) != CKR_OK)
+ {
+ dh->recyclePrivateKey(privateKey);
+ dh->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Derive the secret
+ SymmetricKey* secret = NULL;
+ CK_RV rv = CKR_OK;
+ if (!dh->deriveKey(&secret, publicKey, privateKey))
+ rv = CKR_GENERAL_ERROR;
+ dh->recyclePrivateKey(privateKey);
+ dh->recyclePublicKey(publicKey);
+
+ // Create the secret object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
+ CK_ATTRIBUTE secretAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG secretAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - secretAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ case CKA_CHECK_VALUE:
+ continue;
+ default:
+ secretAttribs[secretAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
+
+ // Common Secret Key Attributes
+ if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
+ {
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ }
+ else
+ {
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
+ }
+ if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
+ {
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
+ }
+ else
+ {
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
+ }
+
+ // Secret Attributes
+ ByteString secretValue = secret->getKeyBits();
+ ByteString value;
+ ByteString plainKCV;
+ ByteString kcv;
+
+ if (byteLen > secretValue.size())
+ {
+ INFO_MSG("The derived secret is too short");
+ bOK = false;
+ }
+ else
+ {
+ // Truncate value when requested, remove from the leading end
+ if (byteLen < secretValue.size())
+ secretValue.split(secretValue.size() - byteLen);
+
+ // Fix the odd parity for DES
+ if (keyType == CKK_DES ||
+ keyType == CKK_DES2 ||
+ keyType == CKK_DES3)
+ {
+ for (size_t i = 0; i < secretValue.size(); i++)
+ {
+ secretValue[i] = odd_parity[secretValue[i]];
+ }
+ }
+
+ // Get the KCV
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ secret->setBitLen(byteLen * 8);
+ plainKCV = secret->getKeyCheckValue();
+ break;
+ case CKK_DES:
+ case CKK_DES2:
+ case CKK_DES3:
+ secret->setBitLen(byteLen * 7);
+ plainKCV = ((DESKey*)secret)->getKeyCheckValue();
+ break;
+ case CKK_AES:
+ secret->setBitLen(byteLen * 8);
+ plainKCV = ((AESKey*)secret)->getKeyCheckValue();
+ break;
+ default:
+ bOK = false;
+ break;
+ }
+
+ if (isPrivate)
+ {
+ token->encrypt(secretValue, value);
+ token->encrypt(plainKCV, kcv);
+ }
+ else
+ {
+ value = secretValue;
+ kcv = plainKCV;
+ }
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ if (checkValue)
+ bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Clean up
+ dh->recycleSymmetricKey(secret);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+
+ // Remove secret that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (ossecret) ossecret->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+// Derive an ECDH secret
+CK_RV SoftHSM::deriveECDH
+(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_KEY_TYPE keyType,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+#ifdef WITH_ECC
+ *phKey = CK_INVALID_HANDLE;
+
+ if ((pMechanism->pParameter == NULL_PTR) ||
+ (pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)))
+ {
+ DEBUG_MSG("pParameter must be of type CK_ECDH1_DERIVE_PARAMS");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->kdf != CKD_NULL)
+ {
+ DEBUG_MSG("kdf must be CKD_NULL");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulSharedDataLen != 0) ||
+ (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pSharedData != NULL_PTR))
+ {
+ DEBUG_MSG("there must be no shared data");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen == 0) ||
+ (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData == NULL_PTR))
+ {
+ DEBUG_MSG("there must be a public data");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ size_t byteLen = 0;
+ bool checkValue = true;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_VALUE:
+ INFO_MSG("CKA_VALUE must not be included");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ case CKA_VALUE_LEN:
+ if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ byteLen = *(CK_ULONG*)pTemplate[i].pValue;
+ break;
+ case CKA_CHECK_VALUE:
+ if (pTemplate[i].ulValueLen > 0)
+ {
+ INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ checkValue = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Check the length
+ // byteLen == 0 impiles return max size the ECC can derive
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ break;
+#ifndef WITH_FIPS
+ case CKK_DES:
+ if (byteLen != 0 && byteLen != 8)
+ {
+ INFO_MSG("CKA_VALUE_LEN must be 0 or 8");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ byteLen = 8;
+ break;
+#endif
+ case CKK_DES2:
+ if (byteLen != 0 && byteLen != 16)
+ {
+ INFO_MSG("CKA_VALUE_LEN must be 0 or 16");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ byteLen = 16;
+ break;
+ case CKK_DES3:
+ if (byteLen != 0 && byteLen != 24)
+ {
+ INFO_MSG("CKA_VALUE_LEN must be 0 or 24");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ byteLen = 24;
+ break;
+ case CKK_AES:
+ if (byteLen != 0 && byteLen != 16 && byteLen != 24 && byteLen != 32)
+ {
+ INFO_MSG("CKA_VALUE_LEN must be 0, 16, 24, or 32");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ break;
+ default:
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Get the base key handle
+ OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
+ if (baseKey == NULL || !baseKey->isValid())
+ return CKR_KEY_HANDLE_INVALID;
+
+ // Get the ECDH algorithm handler
+ AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
+ if (ecdh == NULL)
+ return CKR_MECHANISM_INVALID;
+
+ // Get the keys
+ PrivateKey* privateKey = ecdh->newPrivateKey();
+ if (privateKey == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
+ return CKR_HOST_MEMORY;
+ }
+ if (getECPrivateKey((ECPrivateKey*)privateKey, token, baseKey) != CKR_OK)
+ {
+ ecdh->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
+ return CKR_GENERAL_ERROR;
+ }
+
+ ByteString publicData;
+ publicData.resize(CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
+ memcpy(&publicData[0],
+ CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData,
+ CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
+ PublicKey* publicKey = ecdh->newPublicKey();
+ if (publicKey == NULL)
+ {
+ ecdh->recyclePrivateKey(privateKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
+ return CKR_HOST_MEMORY;
+ }
+ if (getECDHPublicKey((ECPublicKey*)publicKey, (ECPrivateKey*)privateKey, publicData) != CKR_OK)
+ {
+ ecdh->recyclePrivateKey(privateKey);
+ ecdh->recyclePublicKey(publicKey);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Derive the secret
+ SymmetricKey* secret = NULL;
+ CK_RV rv = CKR_OK;
+ if (!ecdh->deriveKey(&secret, publicKey, privateKey))
+ rv = CKR_GENERAL_ERROR;
+ ecdh->recyclePrivateKey(privateKey);
+ ecdh->recyclePublicKey(publicKey);
+
+ // Create the secret object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
+ CK_ATTRIBUTE secretAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG secretAttribsCount = 4;
+
+ // Add the additional
+ if (ulCount > (maxAttribs - secretAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ case CKA_CHECK_VALUE:
+ continue;
+ default:
+ secretAttribs[secretAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
+
+ // Common Secret Key Attributes
+ if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
+ {
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ }
+ else
+ {
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
+ }
+ if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
+ {
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
+ }
+ else
+ {
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
+ }
+
+ // Secret Attributes
+ ByteString secretValue = secret->getKeyBits();
+ ByteString value;
+ ByteString plainKCV;
+ ByteString kcv;
+
+ // For generic and AES keys:
+ // default to return max size available.
+ if (byteLen == 0)
+ {
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ byteLen = secretValue.size();
+ break;
+ case CKK_AES:
+ if (secretValue.size() >= 32)
+ byteLen = 32;
+ else if (secretValue.size() >= 24)
+ byteLen = 24;
+ else
+ byteLen = 16;
+ }
+ }
+
+ if (byteLen > secretValue.size())
+ {
+ INFO_MSG("The derived secret is too short");
+ bOK = false;
+ }
+ else
+ {
+ // Truncate value when requested, remove from the leading end
+ if (byteLen < secretValue.size())
+ secretValue.split(secretValue.size() - byteLen);
+
+ // Fix the odd parity for DES
+ if (keyType == CKK_DES ||
+ keyType == CKK_DES2 ||
+ keyType == CKK_DES3)
+ {
+ for (size_t i = 0; i < secretValue.size(); i++)
+ {
+ secretValue[i] = odd_parity[secretValue[i]];
+ }
+ }
+
+ // Get the KCV
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ secret->setBitLen(byteLen * 8);
+ plainKCV = secret->getKeyCheckValue();
+ break;
+ case CKK_DES:
+ case CKK_DES2:
+ case CKK_DES3:
+ secret->setBitLen(byteLen * 7);
+ plainKCV = ((DESKey*)secret)->getKeyCheckValue();
+ break;
+ case CKK_AES:
+ secret->setBitLen(byteLen * 8);
+ plainKCV = ((AESKey*)secret)->getKeyCheckValue();
+ break;
+ default:
+ bOK = false;
+ break;
+ }
+
+ if (isPrivate)
+ {
+ token->encrypt(secretValue, value);
+ token->encrypt(plainKCV, kcv);
+ }
+ else
+ {
+ value = secretValue;
+ kcv = plainKCV;
+ }
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ if (checkValue)
+ bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Clean up
+ ecdh->recycleSymmetricKey(secret);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
+
+ // Remove secret that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (ossecret) ossecret->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+#else
+ return CKR_MECHANISM_INVALID;
+#endif
+}
+
+// Derive an symmetric secret
+CK_RV SoftHSM::deriveSymmetric
+(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_KEY_TYPE keyType,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate)
+{
+ *phKey = CK_INVALID_HANDLE;
+
+ if (pMechanism->pParameter == NULL_PTR)
+ {
+ DEBUG_MSG("pParameter must be supplied");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ ByteString data;
+
+ if ((pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
+ pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA) &&
+ pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
+ {
+ CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
+ CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
+ if (ulLen == 0 || pData == NULL_PTR)
+ {
+ DEBUG_MSG("There must be data in the parameter");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if (ulLen % 8 != 0)
+ {
+ DEBUG_MSG("The data must be a multiple of 8 bytes long");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ data.resize(ulLen);
+ memcpy(&data[0],
+ pData,
+ ulLen);
+ }
+ else if ((pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
+ pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA) &&
+ pMechanism->ulParameterLen == sizeof(CK_DES_CBC_ENCRYPT_DATA_PARAMS))
+ {
+ CK_BYTE_PTR pData = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
+ CK_ULONG length = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
+ if (length == 0 || pData == NULL_PTR)
+ {
+ DEBUG_MSG("There must be data in the parameter");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if (length % 8 != 0)
+ {
+ DEBUG_MSG("The data must be a multiple of 8 bytes long");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ data.resize(length);
+ memcpy(&data[0],
+ pData,
+ length);
+ }
+ else if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
+ pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
+ {
+ CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
+ CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
+ if (ulLen == 0 || pData == NULL_PTR)
+ {
+ DEBUG_MSG("There must be data in the parameter");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if (ulLen % 16 != 0)
+ {
+ DEBUG_MSG("The data must be a multiple of 16 bytes long");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ data.resize(ulLen);
+ memcpy(&data[0],
+ pData,
+ ulLen);
+ }
+ else if ((pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA) &&
+ pMechanism->ulParameterLen == sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))
+ {
+ CK_BYTE_PTR pData = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
+ CK_ULONG length = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
+ if (length == 0 || pData == NULL_PTR)
+ {
+ DEBUG_MSG("There must be data in the parameter");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if (length % 16 != 0)
+ {
+ DEBUG_MSG("The data must be a multiple of 16 bytes long");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ data.resize(length);
+ memcpy(&data[0],
+ pData,
+ length);
+ }
+ else
+ {
+ DEBUG_MSG("pParameter is invalid");
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL)
+ return CKR_GENERAL_ERROR;
+
+ // Extract desired parameter information
+ size_t byteLen = 0;
+ bool checkValue = true;
+ for (CK_ULONG i = 0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_VALUE:
+ INFO_MSG("CKA_VALUE must not be included");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ case CKA_VALUE_LEN:
+ if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
+ {
+ INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ byteLen = *(CK_ULONG*)pTemplate[i].pValue;
+ break;
+ case CKA_CHECK_VALUE:
+ if (pTemplate[i].ulValueLen > 0)
+ {
+ INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ checkValue = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Check the length
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ if (byteLen == 0)
+ {
+ INFO_MSG("CKA_VALUE_LEN must be set");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ break;
+#ifndef WITH_FIPS
+ case CKK_DES:
+ if (byteLen != 0)
+ {
+ INFO_MSG("CKA_VALUE_LEN must not be set");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ byteLen = 8;
+ break;
+#endif
+ case CKK_DES2:
+ if (byteLen != 0)
+ {
+ INFO_MSG("CKA_VALUE_LEN must not be set");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ byteLen = 16;
+ break;
+ case CKK_DES3:
+ if (byteLen != 0)
+ {
+ INFO_MSG("CKA_VALUE_LEN must not be set");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ byteLen = 24;
+ break;
+ case CKK_AES:
+ if (byteLen != 16 && byteLen != 24 && byteLen != 32)
+ {
+ INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ break;
+ default:
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ // Get the symmetric algorithm matching the mechanism
+ SymAlgo::Type algo = SymAlgo::Unknown;
+ SymMode::Type mode = SymMode::Unknown;
+ bool padding = false;
+ ByteString iv;
+ size_t bb = 8;
+ switch(pMechanism->mechanism) {
+#ifndef WITH_FIPS
+ case CKM_DES_ECB_ENCRYPT_DATA:
+ algo = SymAlgo::DES;
+ mode = SymMode::ECB;
+ bb = 7;
+ break;
+ case CKM_DES_CBC_ENCRYPT_DATA:
+ algo = SymAlgo::DES;
+ mode = SymMode::CBC;
+ bb = 7;
+ iv.resize(8);
+ memcpy(&iv[0],
+ &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
+ 8);
+ break;
+#endif
+ case CKM_DES3_ECB_ENCRYPT_DATA:
+ algo = SymAlgo::DES3;
+ mode = SymMode::ECB;
+ bb = 7;
+ break;
+ case CKM_DES3_CBC_ENCRYPT_DATA:
+ algo = SymAlgo::DES3;
+ mode = SymMode::CBC;
+ bb = 7;
+ iv.resize(8);
+ memcpy(&iv[0],
+ &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
+ 8);
+ break;
+ case CKM_AES_ECB_ENCRYPT_DATA:
+ algo = SymAlgo::AES;
+ mode = SymMode::ECB;
+ break;
+ case CKM_AES_CBC_ENCRYPT_DATA:
+ algo = SymAlgo::AES;
+ mode = SymMode::CBC;
+ iv.resize(16);
+ memcpy(&iv[0],
+ &(CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
+ 16);
+ break;
+ default:
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Check the key handle
+ OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
+ if (baseKey == NULL_PTR || !baseKey->isValid()) return CKR_OBJECT_HANDLE_INVALID;
+
+ SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
+ if (cipher == NULL) return CKR_MECHANISM_INVALID;
+
+ SymmetricKey* secretkey = new SymmetricKey();
+
+ if (getSymmetricKey(secretkey, token, baseKey) != CKR_OK)
+ {
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // adjust key bit length
+ secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
+
+ // Initialize encryption
+ if (!cipher->encryptInit(secretkey, mode, iv, padding))
+ {
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_MECHANISM_INVALID;
+ }
+
+ // Get the data
+ ByteString secretValue;
+
+ // Encrypt the data
+ if (!cipher->encryptUpdate(data, secretValue))
+ {
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Finalize encryption
+ ByteString encryptedFinal;
+ if (!cipher->encryptFinal(encryptedFinal))
+ {
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return CKR_GENERAL_ERROR;
+ }
+ cipher->recycleKey(secretkey);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ secretValue += encryptedFinal;
+
+ // Create the secret object using C_CreateObject
+ const CK_ULONG maxAttribs = 32;
+ CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
+ CK_ATTRIBUTE secretAttribs[maxAttribs] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
+ { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ };
+ CK_ULONG secretAttribsCount = 4;
+
+ // Add the additional
+ CK_RV rv = CKR_OK;
+ if (ulCount > (maxAttribs - secretAttribsCount))
+ rv = CKR_TEMPLATE_INCONSISTENT;
+ for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CLASS:
+ case CKA_TOKEN:
+ case CKA_PRIVATE:
+ case CKA_KEY_TYPE:
+ case CKA_CHECK_VALUE:
+ continue;
+ default:
+ secretAttribs[secretAttribsCount++] = pTemplate[i];
+ }
+ }
+
+ if (rv == CKR_OK)
+ rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
+
+ // Store the attributes that are being supplied
+ if (rv == CKR_OK)
+ {
+ OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
+ if (osobject == NULL_PTR || !osobject->isValid()) {
+ rv = CKR_FUNCTION_FAILED;
+ } else if (osobject->startTransaction()) {
+ bool bOK = true;
+
+ // Common Attributes
+ bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
+
+ // Common Secret Key Attributes
+ if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
+ {
+ bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
+ }
+ else
+ {
+ bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
+ }
+ if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
+ {
+ bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
+ }
+ else
+ {
+ bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
+ }
+
+ ByteString value;
+ ByteString plainKCV;
+ ByteString kcv;
+
+ if (byteLen > secretValue.size())
+ {
+ INFO_MSG("The derived secret is too short");
+ bOK = false;
+ }
+ else
+ {
+ // Truncate value when requested, remove from the trailing end
+ if (byteLen < secretValue.size())
+ secretValue.resize(byteLen);
+
+ // Fix the odd parity for DES
+ if (keyType == CKK_DES ||
+ keyType == CKK_DES2 ||
+ keyType == CKK_DES3)
+ {
+ for (size_t i = 0; i < secretValue.size(); i++)
+ {
+ secretValue[i] = odd_parity[secretValue[i]];
+ }
+ }
+
+ // Get the KCV
+ SymmetricKey* secret = new SymmetricKey();
+ secret->setKeyBits(secretValue);
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ secret->setBitLen(byteLen * 8);
+ plainKCV = secret->getKeyCheckValue();
+ break;
+ case CKK_DES:
+ case CKK_DES2:
+ case CKK_DES3:
+ secret->setBitLen(byteLen * 7);
+ plainKCV = ((DESKey*)secret)->getKeyCheckValue();
+ break;
+ case CKK_AES:
+ secret->setBitLen(byteLen * 8);
+ plainKCV = ((AESKey*)secret)->getKeyCheckValue();
+ break;
+ default:
+ bOK = false;
+ break;
+ }
+ delete secret;
+
+ if (isPrivate)
+ {
+ token->encrypt(secretValue, value);
+ token->encrypt(plainKCV, kcv);
+ }
+ else
+ {
+ value = secretValue;
+ kcv = plainKCV;
+ }
+ }
+ bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
+ if (checkValue)
+ bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
+
+ if (bOK)
+ bOK = osobject->commitTransaction();
+ else
+ osobject->abortTransaction();
+
+ if (!bOK)
+ rv = CKR_FUNCTION_FAILED;
+ } else
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ // Remove secret that may have been created already when the function fails.
+ if (rv != CKR_OK)
+ {
+ if (*phKey != CK_INVALID_HANDLE)
+ {
+ OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
+ handleManager->destroyObject(*phKey);
+ if (ossecret) ossecret->destroyObject();
+ *phKey = CK_INVALID_HANDLE;
+ }
+ }
+
+ return rv;
+}
+
+CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject, int op)
+{
+ if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
+
+ if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Get the session
+ Session* session = (Session*)handleManager->getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Get the slot
+ Slot* slot = session->getSlot();
+ if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Get the token
+ Token* token = session->getToken();
+ if (token == NULL_PTR) return CKR_GENERAL_ERROR;
+
+ // Extract information from the template that is needed to create the object.
+ CK_OBJECT_CLASS objClass = CKO_DATA;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_CERTIFICATE_TYPE certType = CKC_X_509;
+ CK_BBOOL isOnToken = CK_FALSE;
+ CK_BBOOL isPrivate = CK_TRUE;
+ bool isImplicit = false;
+ CK_RV rv = extractObjectInformation(pTemplate,ulCount,objClass,keyType,certType, isOnToken, isPrivate, isImplicit);
+ if (rv != CKR_OK)
+ {
+ ERROR_MSG("Mandatory attribute not present in template");
+ return rv;
+ }
+
+ // Check user credentials
+ rv = haveWrite(session->getState(), isOnToken, isPrivate);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_USER_NOT_LOGGED_IN)
+ INFO_MSG("User is not authorized");
+ if (rv == CKR_SESSION_READ_ONLY)
+ INFO_MSG("Session is read-only");
+
+ return rv;
+ }
+
+ // Change order of attributes
+ const CK_ULONG maxAttribs = 32;
+ CK_ATTRIBUTE attribs[maxAttribs];
+ CK_ATTRIBUTE saveAttribs[maxAttribs];
+ CK_ULONG attribsCount = 0;
+ CK_ULONG saveAttribsCount = 0;
+ if (ulCount > maxAttribs)
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ for (CK_ULONG i=0; i < ulCount; i++)
+ {
+ switch (pTemplate[i].type)
+ {
+ case CKA_CHECK_VALUE:
+ saveAttribs[saveAttribsCount++] = pTemplate[i];
+ break;
+ default:
+ attribs[attribsCount++] = pTemplate[i];
+ }
+ }
+ for (CK_ULONG i=0; i < saveAttribsCount; i++)
+ {
+ attribs[attribsCount++] = saveAttribs[i];
+ }
+
+ P11Object* p11object = NULL;
+ rv = newP11Object(objClass,keyType,certType,&p11object);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Create the object in session or on the token
+ OSObject *object = NULL_PTR;
+ if (isOnToken)
+ {
+ object = (OSObject*) token->createObject();
+ }
+ else
+ {
+ object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
+ }
+
+ if (object == NULL || !p11object->init(object))
+ {
+ delete p11object;
+ return CKR_GENERAL_ERROR;
+ }
+
+ rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, attribs,attribsCount,op);
+ delete p11object;
+ if (rv != CKR_OK)
+ return rv;
+
+ if (op == OBJECT_OP_CREATE)
+ {
+ if (objClass == CKO_PUBLIC_KEY &&
+ (!object->startTransaction() ||
+ !object->setAttribute(CKA_LOCAL, false) ||
+ !object->commitTransaction()))
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ if ((objClass == CKO_SECRET_KEY || objClass == CKO_PRIVATE_KEY) &&
+ (!object->startTransaction() ||
+ !object->setAttribute(CKA_LOCAL, false) ||
+ !object->setAttribute(CKA_ALWAYS_SENSITIVE, false) ||
+ !object->setAttribute(CKA_NEVER_EXTRACTABLE, false) ||
+ !object->commitTransaction()))
+ {
+ return CKR_GENERAL_ERROR;
+ }
+ }
+
+ if (isOnToken)
+ {
+ *phObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, object);
+ } else {
+ *phObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, object);
+ }
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key)
+{
+ if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // RSA Private Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ ByteString privateExponent;
+ ByteString prime1;
+ ByteString prime2;
+ ByteString exponent1;
+ ByteString exponent2;
+ ByteString coefficient;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIVATE_EXPONENT), privateExponent);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_1), prime1);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_2), prime2);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_1), exponent1);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_2), exponent2);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_COEFFICIENT), coefficient);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ modulus = key->getByteStringValue(CKA_MODULUS);
+ publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
+ privateExponent = key->getByteStringValue(CKA_PRIVATE_EXPONENT);
+ prime1 = key->getByteStringValue(CKA_PRIME_1);
+ prime2 = key->getByteStringValue(CKA_PRIME_2);
+ exponent1 = key->getByteStringValue(CKA_EXPONENT_1);
+ exponent2 = key->getByteStringValue(CKA_EXPONENT_2);
+ coefficient = key->getByteStringValue(CKA_COEFFICIENT);
+ }
+
+ privateKey->setN(modulus);
+ privateKey->setE(publicExponent);
+ privateKey->setD(privateExponent);
+ privateKey->setP(prime1);
+ privateKey->setQ(prime2);
+ privateKey->setDP1(exponent1);
+ privateKey->setDQ1(exponent2);
+ privateKey->setPQ(coefficient);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key)
+{
+ if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // RSA Public Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ modulus = key->getByteStringValue(CKA_MODULUS);
+ publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
+ }
+
+ publicKey->setN(modulus);
+ publicKey->setE(publicExponent);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getDSAPrivateKey(DSAPrivateKey* privateKey, Token* token, OSObject* key)
+{
+ if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // DSA Private Key Attributes
+ ByteString prime;
+ ByteString subprime;
+ ByteString generator;
+ ByteString value;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ prime = key->getByteStringValue(CKA_PRIME);
+ subprime = key->getByteStringValue(CKA_SUBPRIME);
+ generator = key->getByteStringValue(CKA_BASE);
+ value = key->getByteStringValue(CKA_VALUE);
+ }
+
+ privateKey->setP(prime);
+ privateKey->setQ(subprime);
+ privateKey->setG(generator);
+ privateKey->setX(value);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getDSAPublicKey(DSAPublicKey* publicKey, Token* token, OSObject* key)
+{
+ if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // DSA Public Key Attributes
+ ByteString prime;
+ ByteString subprime;
+ ByteString generator;
+ ByteString value;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ prime = key->getByteStringValue(CKA_PRIME);
+ subprime = key->getByteStringValue(CKA_SUBPRIME);
+ generator = key->getByteStringValue(CKA_BASE);
+ value = key->getByteStringValue(CKA_VALUE);
+ }
+
+ publicKey->setP(prime);
+ publicKey->setQ(subprime);
+ publicKey->setG(generator);
+ publicKey->setY(value);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getECPrivateKey(ECPrivateKey* privateKey, Token* token, OSObject* key)
+{
+ if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // EC Private Key Attributes
+ ByteString group;
+ ByteString value;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ group = key->getByteStringValue(CKA_EC_PARAMS);
+ value = key->getByteStringValue(CKA_VALUE);
+ }
+
+ privateKey->setEC(group);
+ privateKey->setD(value);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key)
+{
+ if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // EC Public Key Attributes
+ ByteString group;
+ ByteString point;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_POINT), point);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ group = key->getByteStringValue(CKA_EC_PARAMS);
+ point = key->getByteStringValue(CKA_EC_POINT);
+ }
+
+ publicKey->setEC(group);
+ publicKey->setQ(point);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key)
+{
+ if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // DH Private Key Attributes
+ ByteString prime;
+ ByteString generator;
+ ByteString value;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ prime = key->getByteStringValue(CKA_PRIME);
+ generator = key->getByteStringValue(CKA_BASE);
+ value = key->getByteStringValue(CKA_VALUE);
+ }
+
+ privateKey->setP(prime);
+ privateKey->setG(generator);
+ privateKey->setX(value);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams)
+{
+ if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Copy Domain Parameters from Private Key
+ publicKey->setP(privateKey->getP());
+ publicKey->setG(privateKey->getG());
+
+ // Set value
+ publicKey->setY(pubParams);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData)
+{
+ if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Copy Domain Parameters from Private Key
+ publicKey->setEC(privateKey->getEC());
+
+ // Set value
+ ByteString data = getECDHPubData(pubData);
+ publicKey->setQ(data);
+
+ return CKR_OK;
+}
+
+// ECDH pubData can be in RAW or DER format.
+// Need to convert RAW as SoftHSM uses DER.
+ByteString SoftHSM::getECDHPubData(ByteString& pubData)
+{
+ size_t len = pubData.size();
+ size_t controlOctets = 2;
+ if (len == 65 || len == 97 || len == 133)
+ {
+ // Raw: Length matches the public key size of P-256, P-384, or P-521
+ controlOctets = 0;
+ }
+ else if (len < controlOctets || pubData[0] != 0x04)
+ {
+ // Raw: Too short or does not start with 0x04
+ controlOctets = 0;
+ }
+ else if (pubData[1] < 0x80)
+ {
+ // Raw: Length octet does not match remaining data length
+ if (pubData[1] != (len - controlOctets)) controlOctets = 0;
+ }
+ else
+ {
+ size_t lengthOctets = pubData[1] & 0x7F;
+ controlOctets += lengthOctets;
+
+ if (controlOctets >= len)
+ {
+ // Raw: Too short
+ controlOctets = 0;
+ }
+ else
+ {
+ ByteString length(&pubData[2], lengthOctets);
+
+ if (length.long_val() != (len - controlOctets))
+ {
+ // Raw: Length octets does not match remaining data length
+ controlOctets = 0;
+ }
+ }
+ }
+
+ // DER format
+ if (controlOctets != 0) return pubData;
+
+ // RAW format
+ ByteString header;
+ if (len < 0x80)
+ {
+ header.resize(2);
+ header[0] = (unsigned char)0x04;
+ header[1] = (unsigned char)(len & 0x7F);
+ }
+ else
+ {
+ // Count significate bytes
+ size_t bytes = sizeof(size_t);
+ for(; bytes > 0; bytes--)
+ {
+ size_t value = len >> ((bytes - 1) * 8);
+ if (value & 0xFF) break;
+ }
+
+ // Set header data
+ header.resize(2 + bytes);
+ header[0] = (unsigned char)0x04;
+ header[1] = (unsigned char)(0x80 | bytes);
+ for (size_t i = 1; i <= bytes; i++)
+ {
+ header[2+bytes-i] = (unsigned char) (len & 0xFF);
+ len >>= 8;
+ }
+ }
+
+ return header + pubData;
+}
+
+CK_RV SoftHSM::getGOSTPrivateKey(GOSTPrivateKey* privateKey, Token* token, OSObject* key)
+{
+ if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // GOST Private Key Attributes
+ ByteString value;
+ ByteString param;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ value = key->getByteStringValue(CKA_VALUE);
+ param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
+ }
+
+ privateKey->setD(value);
+ privateKey->setEC(param);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getGOSTPublicKey(GOSTPublicKey* publicKey, Token* token, OSObject* key)
+{
+ if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ // GOST Public Key Attributes
+ ByteString point;
+ ByteString param;
+ if (isKeyPrivate)
+ {
+ bool bOK = true;
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), point);
+ bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
+ if (!bOK)
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ point = key->getByteStringValue(CKA_VALUE);
+ param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
+ }
+
+ publicKey->setQ(point);
+ publicKey->setEC(param);
+
+ return CKR_OK;
+}
+
+CK_RV SoftHSM::getSymmetricKey(SymmetricKey* skey, Token* token, OSObject* key)
+{
+ if (skey == NULL) return CKR_ARGUMENTS_BAD;
+ if (token == NULL) return CKR_ARGUMENTS_BAD;
+ if (key == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
+ bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
+
+ ByteString keybits;
+ if (isKeyPrivate)
+ {
+ if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
+ return CKR_GENERAL_ERROR;
+ }
+ else
+ {
+ keybits = key->getByteStringValue(CKA_VALUE);
+ }
+
+ skey->setKeyBits(keybits);
+
+ return CKR_OK;
+}
+
+bool SoftHSM::setRSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
+{
+ AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
+ if (rsa == NULL)
+ return false;
+ PrivateKey* priv = rsa->newPrivateKey();
+ if (priv == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+ return false;
+ }
+ if (!priv->PKCS8Decode(ber))
+ {
+ rsa->recyclePrivateKey(priv);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+ return false;
+ }
+ // RSA Private Key Attributes
+ ByteString modulus;
+ ByteString publicExponent;
+ ByteString privateExponent;
+ ByteString prime1;
+ ByteString prime2;
+ ByteString exponent1;
+ ByteString exponent2;
+ ByteString coefficient;
+ if (isPrivate)
+ {
+ token->encrypt(((RSAPrivateKey*)priv)->getN(), modulus);
+ token->encrypt(((RSAPrivateKey*)priv)->getE(), publicExponent);
+ token->encrypt(((RSAPrivateKey*)priv)->getD(), privateExponent);
+ token->encrypt(((RSAPrivateKey*)priv)->getP(), prime1);
+ token->encrypt(((RSAPrivateKey*)priv)->getQ(), prime2);
+ token->encrypt(((RSAPrivateKey*)priv)->getDP1(), exponent1);
+ token->encrypt(((RSAPrivateKey*)priv)->getDQ1(), exponent2);
+ token->encrypt(((RSAPrivateKey*)priv)->getPQ(), coefficient);
+ }
+ else
+ {
+ modulus = ((RSAPrivateKey*)priv)->getN();
+ publicExponent = ((RSAPrivateKey*)priv)->getE();
+ privateExponent = ((RSAPrivateKey*)priv)->getD();
+ prime1 = ((RSAPrivateKey*)priv)->getP();
+ prime2 = ((RSAPrivateKey*)priv)->getQ();
+ exponent1 = ((RSAPrivateKey*)priv)->getDP1();
+ exponent2 = ((RSAPrivateKey*)priv)->getDQ1();
+ coefficient = ((RSAPrivateKey*)priv)->getPQ();
+ }
+ bool bOK = true;
+ bOK = bOK && key->setAttribute(CKA_MODULUS, modulus);
+ bOK = bOK && key->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
+ bOK = bOK && key->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
+ bOK = bOK && key->setAttribute(CKA_PRIME_1, prime1);
+ bOK = bOK && key->setAttribute(CKA_PRIME_2, prime2);
+ bOK = bOK && key->setAttribute(CKA_EXPONENT_1,exponent1);
+ bOK = bOK && key->setAttribute(CKA_EXPONENT_2, exponent2);
+ bOK = bOK && key->setAttribute(CKA_COEFFICIENT, coefficient);
+
+ rsa->recyclePrivateKey(priv);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+
+ return bOK;
+}
+
+bool SoftHSM::setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
+{
+ AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
+ if (dsa == NULL)
+ return false;
+ PrivateKey* priv = dsa->newPrivateKey();
+ if (priv == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+ return false;
+ }
+ if (!priv->PKCS8Decode(ber))
+ {
+ dsa->recyclePrivateKey(priv);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+ return false;
+ }
+ // DSA Private Key Attributes
+ ByteString prime;
+ ByteString subprime;
+ ByteString generator;
+ ByteString value;
+ if (isPrivate)
+ {
+ token->encrypt(((DSAPrivateKey*)priv)->getP(), prime);
+ token->encrypt(((DSAPrivateKey*)priv)->getQ(), subprime);
+ token->encrypt(((DSAPrivateKey*)priv)->getG(), generator);
+ token->encrypt(((DSAPrivateKey*)priv)->getX(), value);
+ }
+ else
+ {
+ prime = ((DSAPrivateKey*)priv)->getP();
+ subprime = ((DSAPrivateKey*)priv)->getQ();
+ generator = ((DSAPrivateKey*)priv)->getG();
+ value = ((DSAPrivateKey*)priv)->getX();
+ }
+ bool bOK = true;
+ bOK = bOK && key->setAttribute(CKA_PRIME, prime);
+ bOK = bOK && key->setAttribute(CKA_SUBPRIME, subprime);
+ bOK = bOK && key->setAttribute(CKA_BASE, generator);
+ bOK = bOK && key->setAttribute(CKA_VALUE, value);
+
+ dsa->recyclePrivateKey(priv);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+
+ return bOK;
+}
+
+bool SoftHSM::setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
+{
+ AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
+ if (dh == NULL)
+ return false;
+ PrivateKey* priv = dh->newPrivateKey();
+ if (priv == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ return false;
+ }
+ if (!priv->PKCS8Decode(ber))
+ {
+ dh->recyclePrivateKey(priv);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ return false;
+ }
+ // DH Private Key Attributes
+ ByteString prime;
+ ByteString generator;
+ ByteString value;
+ if (isPrivate)
+ {
+ token->encrypt(((DHPrivateKey*)priv)->getP(), prime);
+ token->encrypt(((DHPrivateKey*)priv)->getG(), generator);
+ token->encrypt(((DHPrivateKey*)priv)->getX(), value);
+ }
+ else
+ {
+ prime = ((DHPrivateKey*)priv)->getP();
+ generator = ((DHPrivateKey*)priv)->getG();
+ value = ((DHPrivateKey*)priv)->getX();
+ }
+ bool bOK = true;
+ bOK = bOK && key->setAttribute(CKA_PRIME, prime);
+ bOK = bOK && key->setAttribute(CKA_BASE, generator);
+ bOK = bOK && key->setAttribute(CKA_VALUE, value);
+
+ dh->recyclePrivateKey(priv);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+
+ return bOK;
+}
+bool SoftHSM::setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
+{
+ AsymmetricAlgorithm* ecc = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
+ if (ecc == NULL)
+ return false;
+ PrivateKey* priv = ecc->newPrivateKey();
+ if (priv == NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
+ return false;
+ }
+ if (!priv->PKCS8Decode(ber))
+ {
+ ecc->recyclePrivateKey(priv);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
+ return false;
+ }
+ // EC Private Key Attributes
+ ByteString group;
+ ByteString value;
+ if (isPrivate)
+ {
+ token->encrypt(((ECPrivateKey*)priv)->getEC(), group);
+ token->encrypt(((ECPrivateKey*)priv)->getD(), value);
+ }
+ else
+ {
+ group = ((ECPrivateKey*)priv)->getEC();
+ value = ((ECPrivateKey*)priv)->getD();
+ }
+ bool bOK = true;
+ bOK = bOK && key->setAttribute(CKA_EC_PARAMS, group);
+ bOK = bOK && key->setAttribute(CKA_VALUE, value);
+
+ ecc->recyclePrivateKey(priv);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
+
+ return bOK;
+}
+
+CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
+{
+ // This is a programming error
+ if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) {
+ ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (pMechanism->pParameter == NULL_PTR ||
+ pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
+ {
+ ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter;
+ if (params->hashAlg != CKM_SHA_1)
+ {
+ ERROR_MSG("hashAlg must be CKM_SHA_1");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (params->mgf != CKG_MGF1_SHA1)
+ {
+ ERROR_MSG("mgf must be CKG_MGF1_SHA1");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (params->source != CKZ_DATA_SPECIFIED)
+ {
+ ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (params->pSourceData != NULL)
+ {
+ ERROR_MSG("pSourceData must be NULL");
+ return CKR_ARGUMENTS_BAD;
+ }
+ if (params->ulSourceDataLen != 0)
+ {
+ ERROR_MSG("ulSourceDataLen must be 0");
+ return CKR_ARGUMENTS_BAD;
+ }
+ return CKR_OK;
+}
+
+bool SoftHSM::isMechanismPermitted(OSObject* key, CK_MECHANISM_PTR pMechanism) {
+ OSAttribute attribute = key->getAttribute(CKA_ALLOWED_MECHANISMS);
+ std::set<CK_MECHANISM_TYPE> allowed = attribute.getMechanismTypeSetValue();
+ if (allowed.empty()) {
+ return true;
+ }
+
+ return allowed.find(pMechanism->mechanism) != allowed.end();
+}
diff --git a/SoftHSMv2/src/lib/SoftHSM.h b/SoftHSMv2/src/lib/SoftHSM.h
new file mode 100644
index 0000000..19909e4
--- /dev/null
+++ b/SoftHSMv2/src/lib/SoftHSM.h
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SoftHSM.h
+
+ This is the main class of the SoftHSM; it has the PKCS #11 interface and
+ dispatches all calls to the relevant components of the SoftHSM. The SoftHSM
+ class is a singleton implementation.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "cryptoki.h"
+#include "SessionObjectStore.h"
+#include "ObjectStore.h"
+#include "SessionManager.h"
+#include "SlotManager.h"
+#include "HandleManager.h"
+#include "RSAPublicKey.h"
+#include "RSAPrivateKey.h"
+#include "DSAPublicKey.h"
+#include "DSAPrivateKey.h"
+#include "ECPublicKey.h"
+#include "ECPrivateKey.h"
+#include "DHPublicKey.h"
+#include "DHPrivateKey.h"
+#include "GOSTPublicKey.h"
+#include "GOSTPrivateKey.h"
+
+#include <memory>
+
+class SoftHSM
+{
+public:
+ // Return the one-and-only instance
+ static SoftHSM* i();
+
+ // This will destroy the one-and-only instance.
+ static void reset();
+
+ // Destructor
+ virtual ~SoftHSM();
+
+ // PKCS #11 functions
+ CK_RV C_Initialize(CK_VOID_PTR pInitArgs);
+ CK_RV C_Finalize(CK_VOID_PTR pReserved);
+ CK_RV C_GetInfo(CK_INFO_PTR pInfo);
+ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
+ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo);
+ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo);
+ CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount);
+ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo);
+ CK_RV C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel);
+ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen);
+ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen);
+ CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession);
+ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession);
+ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID);
+ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo);
+ CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen);
+ CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey);
+ CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen);
+ CK_RV C_Logout(CK_SESSION_HANDLE hSession);
+ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject);
+ CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject);
+ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject);
+ CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize);
+ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
+ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount);
+ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession);
+ CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen);
+ CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen);
+ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen);
+ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+ CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen);
+ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen);
+ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism);
+ CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen);
+ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen);
+ CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject);
+ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen);
+ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen);
+ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen);
+ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen);
+ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen);
+ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen);
+ CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen);
+ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen);
+ CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+ CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pDecryptedPart, CK_ULONG_PTR pulDecryptedPartLen);
+ CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen);
+ CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen);
+ CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey);
+ CK_RV C_GenerateKeyPair
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey
+ );
+ CK_RV C_WrapKey
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey,
+ CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG_PTR pulWrappedKeyLen
+ );
+ CK_RV C_UnwrapKey
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hUnwrappingKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG ulWrappedKeyLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR hKey
+ );
+ CK_RV C_DeriveKey
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey
+ );
+ CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen);
+ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen);
+ CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession);
+ CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession);
+ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved);
+
+private:
+ // Constructor
+ SoftHSM();
+
+ // The one-and-only instance
+#ifdef HAVE_CXX11
+ static std::unique_ptr<SoftHSM> instance;
+#else
+ static std::auto_ptr<SoftHSM> instance;
+#endif
+
+ // Is the SoftHSM PKCS #11 library initialised?
+ bool isInitialised;
+ bool isRemovable;
+
+ SessionObjectStore* sessionObjectStore;
+ ObjectStore* objectStore;
+ SlotManager* slotManager;
+ SessionManager* sessionManager;
+ HandleManager* handleManager;
+
+ // Encrypt/Decrypt variants
+ CK_RV SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV AsymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV AsymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+
+ // Sign/Verify variants
+ CK_RV MacSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV MacVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+ CK_RV AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey);
+
+ // Key generation
+ CK_RV generateDES
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV generateDES2
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV generateDES3
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV generateAES
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV generateRSA
+ (CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+ );
+ CK_RV generateDSA
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+ );
+ CK_RV generateDSAParameters
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV generateEC
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+ );
+ CK_RV generateDH
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+ );
+ CK_RV generateDHParameters
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV generateGOST
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_BBOOL isPublicKeyOnToken,
+ CK_BBOOL isPublicKeyPrivate,
+ CK_BBOOL isPrivateKeyOnToken,
+ CK_BBOOL isPrivateKeyPrivate
+ );
+ CK_RV deriveDH
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_KEY_TYPE keyType,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV deriveECDH
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_KEY_TYPE keyType,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV deriveSymmetric
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_KEY_TYPE keyType,
+ CK_BBOOL isOnToken,
+ CK_BBOOL isPrivate
+ );
+ CK_RV CreateObject
+ (
+ CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phObject,
+ int op
+ );
+
+ CK_RV getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key);
+ CK_RV getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key);
+ CK_RV getDSAPrivateKey(DSAPrivateKey* privateKey, Token* token, OSObject* key);
+ CK_RV getDSAPublicKey(DSAPublicKey* publicKey, Token* token, OSObject* key);
+ CK_RV getECPrivateKey(ECPrivateKey* privateKey, Token* token, OSObject* key);
+ CK_RV getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key);
+ CK_RV getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key);
+ CK_RV getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams);
+ CK_RV getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData);
+ CK_RV getGOSTPrivateKey(GOSTPrivateKey* privateKey, Token* token, OSObject* key);
+ CK_RV getGOSTPublicKey(GOSTPublicKey* publicKey, Token* token, OSObject* key);
+ CK_RV getSymmetricKey(SymmetricKey* skey, Token* token, OSObject* key);
+
+ ByteString getECDHPubData(ByteString& pubData);
+
+ bool setRSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
+ bool setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
+ bool setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
+ bool setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
+
+
+ CK_RV WrapKeyAsym
+ (
+ CK_MECHANISM_PTR pMechanism,
+ Token *token,
+ OSObject *wrapKey,
+ ByteString &keydata,
+ ByteString &wrapped
+ );
+
+ CK_RV WrapKeySym
+ (
+ CK_MECHANISM_PTR pMechanism,
+ Token *token,
+ OSObject *wrapKey,
+ ByteString &keydata,
+ ByteString &wrapped
+ );
+
+ CK_RV UnwrapKeyAsym
+ (
+ CK_MECHANISM_PTR pMechanism,
+ ByteString &wrapped,
+ Token* token,
+ OSObject *unwrapKey,
+ ByteString &keydata
+ );
+
+ CK_RV UnwrapKeySym
+ (
+ CK_MECHANISM_PTR pMechanism,
+ ByteString &wrapped,
+ Token* token,
+ OSObject *unwrapKey,
+ ByteString &keydata
+ );
+
+ CK_RV MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism);
+
+ static bool isMechanismPermitted(OSObject* key, CK_MECHANISM_PTR pMechanism);
+};
+
diff --git a/SoftHSMv2/src/lib/access.cpp b/SoftHSMv2/src/lib/access.cpp
new file mode 100644
index 0000000..66473d1
--- /dev/null
+++ b/SoftHSMv2/src/lib/access.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ access.cpp
+
+ Implements the access rules.
+ *****************************************************************************/
+
+#include "access.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+// Checks if a read operation is allowed on a given object type.
+//
+// Type of session
+// Type of object R/O Public | R/W Public | R/O User | R/W User | R/W SO
+// ------------------------------------------------------------------------------
+// Public session object OK | OK | OK | OK | OK
+// Private session object UNLI | UNLI | OK | OK | UNLI
+// Public token object OK | OK | OK | OK | OK
+// Private token object UNLI | UNLI | OK | OK | UNLI
+//
+// OK = CKR_OK
+// SRO = CKR_SESSION_READ_ONLY
+// UNLI = CKR_USER_NOT_LOGGED_IN
+
+// Can we do read operations?
+CK_RV haveRead(CK_STATE sessionState, CK_BBOOL /*isTokenObject*/, CK_BBOOL isPrivateObject)
+{
+ switch (sessionState)
+ {
+ case CKS_RO_PUBLIC_SESSION:
+ case CKS_RW_PUBLIC_SESSION:
+ case CKS_RW_SO_FUNCTIONS:
+ return isPrivateObject ? CKR_USER_NOT_LOGGED_IN : CKR_OK;
+ case CKS_RO_USER_FUNCTIONS:
+ case CKS_RW_USER_FUNCTIONS:
+ return CKR_OK;
+ }
+ return CKR_GENERAL_ERROR; // internal error, switch should have covered every state
+}
+
+// Checks if a write operation is allowed on a given object type.
+//
+// Type of session
+// Type of object R/O Public | R/W Public | R/O User | R/W User | R/W SO
+// ------------------------------------------------------------------------------
+// Public session object OK | OK | OK | OK | OK
+// Private session object UNLI | UNLI | OK | OK | UNLI
+// Public token object SRO | OK | SRO | OK | OK
+// Private token object SRO/UNLI | UNLI | SRO | OK | UNLI
+//
+// OK = CKR_OK
+// SRO = CKR_SESSION_READ_ONLY
+// UNLI = CKR_USER_NOT_LOGGED_IN
+// In the situation where both SRO and UNLI may be returned we favor SRO.
+
+// Can we do write operations?
+CK_RV haveWrite(CK_STATE sessionState, CK_BBOOL isTokenObject, CK_BBOOL isPrivateObject)
+{
+ switch (sessionState)
+ {
+ case CKS_RO_PUBLIC_SESSION:
+ if (isTokenObject)
+ return CKR_SESSION_READ_ONLY;
+ else
+ return isPrivateObject ? CKR_USER_NOT_LOGGED_IN : CKR_OK;
+ case CKS_RW_PUBLIC_SESSION:
+ case CKS_RW_SO_FUNCTIONS:
+ return isPrivateObject ? CKR_USER_NOT_LOGGED_IN : CKR_OK;
+ case CKS_RO_USER_FUNCTIONS:
+ return isTokenObject ? CKR_SESSION_READ_ONLY : CKR_OK;
+ case CKS_RW_USER_FUNCTIONS:
+ return CKR_OK;
+ }
+ return CKR_GENERAL_ERROR; // internal error, switch should have covered every state
+}
diff --git a/SoftHSMv2/src/lib/access.h b/SoftHSMv2/src/lib/access.h
new file mode 100644
index 0000000..36f303f
--- /dev/null
+++ b/SoftHSMv2/src/lib/access.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ access.h
+
+ Implements the access rules.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ACCESS_H
+#define _SOFTHSM_V2_ACCESS_H
+
+#include "cryptoki.h"
+
+CK_RV haveRead(CK_STATE sessionState, CK_BBOOL isTokenObject, CK_BBOOL isPrivateObject);
+CK_RV haveWrite(CK_STATE sessionState, CK_BBOOL isTokenObject, CK_BBOOL isPrivateObject);
+
+#endif /* !_SOFTHSM_V2_ACCESS_H */
+
diff --git a/SoftHSMv2/src/lib/common/Configuration.cpp b/SoftHSMv2/src/lib/common/Configuration.cpp
new file mode 100644
index 0000000..a7f6cc6
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/Configuration.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Configuration.cpp
+
+ Loads the configuration and supports retrieval of configuration information
+ *****************************************************************************/
+
+#include <string>
+#include <map>
+#include "Configuration.h"
+#include "log.h"
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+std::unique_ptr<Configuration> Configuration::instance(nullptr);
+#else
+std::auto_ptr<Configuration> Configuration::instance(NULL);
+#endif
+
+// Add all valid configurations
+const struct config Configuration::valid_config[] = {
+ { "directories.tokendir", CONFIG_TYPE_STRING },
+ { "objectstore.backend", CONFIG_TYPE_STRING },
+ { "log.level", CONFIG_TYPE_STRING },
+ { "slots.removable", CONFIG_TYPE_BOOL },
+ { "", CONFIG_TYPE_UNSUPPORTED }
+};
+
+// Return the one-and-only instance
+Configuration* Configuration::i()
+{
+ if (instance.get() == NULL)
+ {
+ instance.reset(new Configuration());
+ }
+
+ return instance.get();
+}
+
+// Constructor
+Configuration::Configuration()
+{
+ configLoader = NULL;
+}
+
+// Get the type of the configuration value
+int Configuration::getType(std::string key)
+{
+ for (int i = 0; valid_config[i].key.compare("") != 0; i++)
+ {
+ if (valid_config[i].key.compare(key) == 0)
+ {
+ return valid_config[i].type;
+ }
+ }
+
+ return CONFIG_TYPE_UNSUPPORTED;
+}
+
+// Retrieve a string based configuration value
+std::string Configuration::getString(std::string key, std::string ifEmpty /* = "" */)
+{
+ if (stringConfiguration.find(key) != stringConfiguration.end())
+ {
+ return stringConfiguration[key];
+ }
+ else
+ {
+ WARNING_MSG("Missing %s in configuration. Using default value: %s", key.c_str(), ifEmpty.c_str());
+ return ifEmpty;
+ }
+}
+
+// Retrieve an integer configuration value
+int Configuration::getInt(std::string key, int ifEmpty /* = 0 */)
+{
+ if (integerConfiguration.find(key) != integerConfiguration.end())
+ {
+ return integerConfiguration[key];
+ }
+ else
+ {
+ WARNING_MSG("Missing %s in configuration. Using default value: %i", key.c_str(), ifEmpty);
+ return ifEmpty;
+ }
+}
+
+// Retrieve a boolean configuration value
+bool Configuration::getBool(std::string key, bool ifEmpty /* = false */)
+{
+ if (booleanConfiguration.find(key) != booleanConfiguration.end())
+ {
+ return booleanConfiguration[key];
+ }
+ else
+ {
+ WARNING_MSG("Missing %s in configuration. Using default value: %s", key.c_str(), ifEmpty ? "true" : "false");
+ return ifEmpty;
+ }
+}
+
+// Set a string based configuration value
+void Configuration::setString(std::string key, std::string value)
+{
+ stringConfiguration[key] = value;
+}
+
+// Set an integer based configuration value
+void Configuration::setInt(std::string key, int value)
+{
+ integerConfiguration[key] = value;
+}
+
+// Set a boolean configuration value
+void Configuration::setBool(std::string key, bool value)
+{
+ booleanConfiguration[key] = value;
+}
+
+// Reload the configuration
+bool Configuration::reload()
+{
+ if (configLoader == NULL)
+ {
+ return false;
+ }
+
+ // Discard the current configuration
+ stringConfiguration.clear();
+ integerConfiguration.clear();
+ booleanConfiguration.clear();
+
+ // Reload the configuration
+ if (!configLoader->loadConfiguration())
+ {
+ ERROR_MSG("Failed to load the SoftHSM configuration");
+
+ return false;
+ }
+
+ return true;
+}
+
+// Reload the configuration using the specified configuration loader
+bool Configuration::reload(ConfigLoader* inConfigLoader)
+{
+ configLoader = inConfigLoader;
+
+ return reload();
+}
+
diff --git a/SoftHSMv2/src/lib/common/Configuration.h b/SoftHSMv2/src/lib/common/Configuration.h
new file mode 100644
index 0000000..eacb493
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/Configuration.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Configuration.h
+
+ Loads the configuration and supports retrieval of configuration information
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_CONFIGURATION_H
+#define _SOFTHSM_V2_CONFIGURATION_H
+
+#include "config.h"
+#include <string>
+#include <map>
+#include <memory>
+
+enum
+{
+ CONFIG_TYPE_UNSUPPORTED,
+ CONFIG_TYPE_STRING,
+ CONFIG_TYPE_INT,
+ CONFIG_TYPE_BOOL
+};
+
+struct config
+{
+ std::string key;
+ int type;
+};
+
+class ConfigLoader
+{
+public:
+ virtual ~ConfigLoader() { }
+
+ // Trigger loading of the configuration
+ virtual bool loadConfiguration() = 0;
+};
+
+class Configuration
+{
+public:
+ static Configuration* i();
+
+ virtual ~Configuration() { }
+
+ // Get the type of the configuration value
+ int getType(std::string key);
+
+ // Retrieve a string based configuration value
+ std::string getString(std::string key, std::string ifEmpty = std::string(""));
+
+ // Retrieve an integer configuration value
+ int getInt(std::string key, int ifEmpty = 0);
+
+ // Retrieve a boolean configuration value
+ bool getBool(std::string key, bool ifEmpty = false);
+
+ // Set a string based configuration value
+ void setString(std::string key, std::string value);
+
+ // Set an integer based configuration value
+ void setInt(std::string key, int value);
+
+ // Set a boolean configuration value
+ void setBool(std::string key, bool value);
+
+ // Reload the configuration
+ bool reload();
+
+ // Reload the configuration using the specified configuration loader
+ bool reload(ConfigLoader* inConfigLoader);
+
+private:
+ Configuration();
+
+#ifdef HAVE_CXX11
+ static std::unique_ptr<Configuration> instance;
+#else
+ static std::auto_ptr<Configuration> instance;
+#endif
+
+ std::map<std::string, std::string> stringConfiguration;
+ std::map<std::string, int> integerConfiguration;
+ std::map<std::string, bool> booleanConfiguration;
+
+ ConfigLoader* configLoader;
+
+ static const struct config valid_config[];
+};
+
+#endif // !_SOFTHSM_V2_CONFIGURATION_H
+
diff --git a/SoftHSMv2/src/lib/common/HandleFactory.h b/SoftHSMv2/src/lib/common/HandleFactory.h
new file mode 100644
index 0000000..0b9dc1f
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/HandleFactory.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleFactory.h
+
+ This is a template class for handling handles ;-)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLEFACTORY_H
+#define _SOFTHSM_V2_HANDLEFACTORY_H
+
+#include "config.h"
+#include "log.h"
+#include "MutexFactory.h"
+#include <map>
+#include <queue>
+
+template <class hType, class oType> class HandleFactory
+{
+public:
+ // Constructor
+ HandleFactory()
+ {
+ nextFree = (hType) 1;
+ handleMutex = MutexFactory::i()->getMutex();
+ }
+
+ // Destructor
+ virtual ~HandleFactory()
+ {
+ MutexFactory::i()->recycleMutex(handleMutex);
+ }
+
+ // Get a new handle for the specified object
+ hType getHandle(oType object)
+ {
+ MutexLocker lock(handleMutex);
+
+ hType handle;
+
+ if (!recycledHandles.empty())
+ {
+ handle = recycledHandles.front();
+ recycledHandles.pop();
+ }
+ else
+ {
+ handle = nextFree++;
+ }
+
+ handleMap[handle] = object;
+
+ return handle;
+ }
+
+ // Check whether the specified handle is valid
+ bool isValid(hType handle)
+ {
+ MutexLocker lock(handleMutex);
+
+ return (handleMap.find(handle) != handleMap.end());
+ }
+
+ // Return the object for the specified handle
+ oType getObjectByHandle(hType handle)
+ {
+ MutexLocker lock(handleMutex);
+
+ return handleMap[handle];
+ }
+
+ // Discard the specified handle
+ void deleteHandle(hType handle)
+ {
+ MutexLocker lock(handleMutex);
+
+ handleMap.erase(handle);
+
+ recycledHandles.push(handle);
+ }
+
+private:
+ // The handle map
+ std::map<hType, oType> handleMap;
+
+ // The set of recycled handles
+ std::queue<hType> recycledHandles;
+
+ // The next free handle
+ hType nextFree;
+
+ // Cross-thread synchronisation
+ Mutex* handleMutex;
+};
+
+#endif // !_SOFTHSM_V2_HANDLEFACTORY_H
+
diff --git a/SoftHSMv2/src/lib/common/Makefile.am b/SoftHSMv2/src/lib/common/Makefile.am
new file mode 100644
index 0000000..bf18b1a
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/Makefile.am
@@ -0,0 +1,28 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../pkcs11
+
+noinst_LTLIBRARIES = libsofthsm_common.la
+libsofthsm_common_la_SOURCES = Configuration.cpp \
+ fatal.cpp \
+ log.cpp \
+ osmutex.cpp \
+ SimpleConfigLoader.cpp \
+ MutexFactory.cpp
+
+man_MANS = softhsm2.conf.5
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/softhsm2.conf.5.in
+
+install-data-hook:
+ test -d ${DESTDIR}${sysconfdir} || \
+ ${INSTALL} -d ${DESTDIR}${sysconfdir}
+ test -f ${DESTDIR}${sysconfdir}/softhsm2.conf || \
+ ${INSTALL_DATA} ${top_builddir}/src/lib/common/softhsm2.conf ${DESTDIR}${sysconfdir}
+ ${INSTALL_DATA} ${top_builddir}/src/lib/common/softhsm2.conf ${DESTDIR}${sysconfdir}/softhsm2.conf.sample
+ test -d ${DESTDIR}${softhsmtokendir} || \
+ ${INSTALL} -d -m 1777 ${DESTDIR}${softhsmtokendir}
diff --git a/SoftHSMv2/src/lib/common/MutexFactory.cpp b/SoftHSMv2/src/lib/common/MutexFactory.cpp
new file mode 100644
index 0000000..1cfc0da
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/MutexFactory.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ MutexFactory.cpp
+
+ This factory produces OS specific mutex objects
+ *****************************************************************************/
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "osmutex.h"
+#include <memory>
+#include <stddef.h>
+
+/*****************************************************************************
+ Mutex implementation
+ *****************************************************************************/
+
+// Constructor
+Mutex::Mutex()
+{
+ isValid = (MutexFactory::i()->CreateMutex(&handle) == CKR_OK);
+}
+
+// Destructor
+Mutex::~Mutex()
+{
+ if (isValid)
+ {
+ MutexFactory::i()->DestroyMutex(handle);
+ }
+}
+
+// Lock the mutex
+bool Mutex::lock()
+{
+ return (isValid && (MutexFactory::i()->LockMutex(handle) == CKR_OK));
+}
+
+// Unlock the mutex
+void Mutex::unlock()
+{
+ if (isValid)
+ {
+ MutexFactory::i()->UnlockMutex(handle);
+ }
+}
+
+/*****************************************************************************
+ MutexLocker implementation
+ *****************************************************************************/
+
+// Constructor
+MutexLocker::MutexLocker(Mutex* inMutex)
+{
+ mutex = inMutex;
+
+ if (mutex != NULL) mutex->lock();
+}
+
+// Destructor
+MutexLocker::~MutexLocker()
+{
+ if (mutex != NULL) mutex->unlock();
+}
+
+/*****************************************************************************
+ MutexFactory implementation
+ *****************************************************************************/
+
+// Constructor
+MutexFactory::MutexFactory()
+{
+ createMutex = OSCreateMutex;
+ destroyMutex = OSDestroyMutex;
+ lockMutex = OSLockMutex;
+ unlockMutex = OSUnlockMutex;
+
+ enabled = true;
+}
+
+// Destructor
+MutexFactory::~MutexFactory()
+{
+}
+
+// Return the one-and-only instance
+MutexFactory* MutexFactory::i()
+{
+ if (!instance.get())
+ {
+ instance.reset(new MutexFactory());
+ }
+
+ return instance.get();
+}
+
+// Get a mutex instance
+Mutex* MutexFactory::getMutex()
+{
+ return new Mutex();
+}
+
+// Recycle a mutex instance
+void MutexFactory::recycleMutex(Mutex* mutex)
+{
+ if (mutex != NULL) delete mutex;
+}
+
+// Set the function pointers
+void MutexFactory::setCreateMutex(CK_CREATEMUTEX inCreateMutex)
+{
+ createMutex = inCreateMutex;
+}
+
+void MutexFactory::setDestroyMutex(CK_DESTROYMUTEX inDestroyMutex)
+{
+ destroyMutex = inDestroyMutex;
+}
+
+void MutexFactory::setLockMutex(CK_LOCKMUTEX inLockMutex)
+{
+ lockMutex = inLockMutex;
+}
+
+void MutexFactory::setUnlockMutex(CK_UNLOCKMUTEX inUnlockMutex)
+{
+ unlockMutex = inUnlockMutex;
+}
+
+void MutexFactory::enable()
+{
+ enabled = true;
+}
+
+void MutexFactory::disable()
+{
+ enabled = false;
+}
+
+CK_RV MutexFactory::CreateMutex(CK_VOID_PTR_PTR newMutex)
+{
+ if (!enabled) return CKR_OK;
+
+ return (this->createMutex)(newMutex);
+}
+
+CK_RV MutexFactory::DestroyMutex(CK_VOID_PTR mutex)
+{
+ if (!enabled) return CKR_OK;
+
+ return (this->destroyMutex)(mutex);
+}
+
+CK_RV MutexFactory::LockMutex(CK_VOID_PTR mutex)
+{
+ if (!enabled) return CKR_OK;
+
+ return (this->lockMutex)(mutex);
+}
+
+CK_RV MutexFactory::UnlockMutex(CK_VOID_PTR mutex)
+{
+ if (!enabled) return CKR_OK;
+
+ return (this->unlockMutex)(mutex);
+}
+
diff --git a/SoftHSMv2/src/lib/common/MutexFactory.h b/SoftHSMv2/src/lib/common/MutexFactory.h
new file mode 100644
index 0000000..167dc3d
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/MutexFactory.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ MutexFactory.h
+
+ This factory produces OS specific mutex objects
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_MUTEXFACTORY_H
+#define _SOFTHSM_V2_MUTEXFACTORY_H
+
+#include "config.h"
+#include "osmutex.h"
+#include "cryptoki.h"
+#include <memory>
+
+class Mutex
+{
+public:
+ // Constructor
+ Mutex();
+
+ // Destructor
+ virtual ~Mutex();
+
+ // Lock the mutex
+ bool lock();
+
+ // Unlock the mutex
+ void unlock();
+
+private:
+ // The mutex handle
+ CK_VOID_PTR handle;
+
+ // Is the mutex valid?
+ bool isValid;
+};
+
+class MutexLocker
+{
+public:
+ // Constructor
+ MutexLocker(Mutex* inMutex);
+
+ // Destructor
+ virtual ~MutexLocker();
+
+private:
+ // The mutex to lock
+ Mutex* mutex;
+};
+
+class MutexFactory
+{
+public:
+ // Return the one-and-only instance
+ static MutexFactory* i();
+
+ // Destructor
+ virtual ~MutexFactory();
+
+ // Get a mutex instance
+ Mutex* getMutex();
+
+ // Recycle a mutex instance
+ void recycleMutex(Mutex* mutex);
+
+ // Set the function pointers
+ void setCreateMutex(CK_CREATEMUTEX inCreateMutex);
+ void setDestroyMutex(CK_DESTROYMUTEX inDestroyMutex);
+ void setLockMutex(CK_LOCKMUTEX inLockMutex);
+ void setUnlockMutex(CK_UNLOCKMUTEX inUnlockMutex);
+
+ // Enable/disable mutex handling
+ void enable();
+ void disable();
+
+private:
+ // Constructor
+ MutexFactory();
+
+ // Mutex operations
+ friend class Mutex;
+
+ CK_RV CreateMutex(CK_VOID_PTR_PTR newMutex);
+ CK_RV DestroyMutex(CK_VOID_PTR mutex);
+ CK_RV LockMutex(CK_VOID_PTR mutex);
+ CK_RV UnlockMutex(CK_VOID_PTR mutex);
+
+ // The one-and-only instance
+#ifdef HAVE_CXX11
+ static std::unique_ptr<MutexFactory> instance;
+#else
+ static std::auto_ptr<MutexFactory> instance;
+#endif
+
+ // The function pointers
+ CK_CREATEMUTEX createMutex;
+ CK_DESTROYMUTEX destroyMutex;
+ CK_LOCKMUTEX lockMutex;
+ CK_UNLOCKMUTEX unlockMutex;
+
+ // Can we do mutex handling?
+ bool enabled;
+};
+
+#endif // !_SOFTHSM_V2_MUTEXFACTORY_H
+
diff --git a/SoftHSMv2/src/lib/common/Serialisable.h b/SoftHSMv2/src/lib/common/Serialisable.h
new file mode 100644
index 0000000..819940e
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/Serialisable.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Serialisable.h
+
+ Interface description for serialisable classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SERIALISABLE_H
+#define _SOFTHSM_V2_SERIALISABLE_H
+
+#include "config.h"
+#include "ByteString.h"
+
+class ByteString;
+
+class Serialisable
+{
+public:
+ // Serialise the data content of a class
+ virtual ByteString serialise() const = 0;
+
+ // Default destructor
+ virtual ~Serialisable() { }
+};
+
+#endif // !_SOFTHSM_V2_SERIALISABLE_H
+
diff --git a/SoftHSMv2/src/lib/common/SimpleConfigLoader.cpp b/SoftHSMv2/src/lib/common/SimpleConfigLoader.cpp
new file mode 100644
index 0000000..3212d82
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/SimpleConfigLoader.cpp
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2010 .SE, The Internet Infrastructure Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SimpleConfigLoader.cpp
+
+ Loads the configuration from the configuration file.
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <algorithm>
+#include <limits.h>
+#ifdef _WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+#endif
+#include "config.h"
+#if defined(HAVE_GETPWUID_R)
+# include <sys/types.h>
+# include <pwd.h>
+#endif
+#include "SimpleConfigLoader.h"
+#include "log.h"
+#include "Configuration.h"
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+std::unique_ptr<SimpleConfigLoader> SimpleConfigLoader::instance(nullptr);
+#else
+std::auto_ptr<SimpleConfigLoader> SimpleConfigLoader::instance(NULL);
+#endif
+
+// Return the one-and-only instance
+SimpleConfigLoader* SimpleConfigLoader::i()
+{
+ if (instance.get() == NULL)
+ {
+ instance.reset(new SimpleConfigLoader());
+ }
+
+ return instance.get();
+}
+
+// Constructor
+SimpleConfigLoader::SimpleConfigLoader()
+{
+}
+
+// Load the configuration
+bool SimpleConfigLoader::loadConfiguration()
+{
+ char* configPath = getConfigPath();
+
+ FILE* fp = fopen(configPath,"r");
+
+ if (fp == NULL)
+ {
+ ERROR_MSG("Could not open the config file: %s", configPath);
+ free(configPath);
+ return false;
+ }
+ free(configPath);
+
+ char fileBuf[1024];
+
+ // Format in config file
+ //
+ // <name> = <value>
+ // # Line is ignored
+
+ size_t line = 0;
+ while (fgets(fileBuf, sizeof(fileBuf), fp) != NULL)
+ {
+ line++;
+
+ // End the string at the first comment or newline
+ fileBuf[strcspn(fileBuf, "#\n\r")] = '\0';
+
+ // Skip empty lines
+ if (fileBuf[0] == '\0')
+ {
+ continue;
+ }
+
+ // Get the first part of the line
+ char* name = strtok(fileBuf, "=");
+ if (name == NULL)
+ {
+ WARNING_MSG("Bad format on line %lu, skip", (unsigned long)line);
+ continue;
+ }
+
+ // Trim the name
+ char* trimmedName = trimString(name);
+ if (trimmedName == NULL)
+ {
+ WARNING_MSG("Bad format on line %lu, skip", (unsigned long)line);
+ continue;
+ }
+
+ // Get the second part of the line
+ char* value = strtok(NULL, "=");
+ if(value == NULL) {
+ WARNING_MSG("Bad format on line %lu, skip", (unsigned long)line);
+ free(trimmedName);
+ continue;
+ }
+
+ // Trim the value
+ char* trimmedValue = trimString(value);
+ if (trimmedValue == NULL)
+ {
+ WARNING_MSG("Bad format on line %lu, skip", (unsigned long)line);
+ free(trimmedName);
+ continue;
+ }
+
+ // Save name,value
+ std::string stringName(trimmedName);
+ std::string stringValue(trimmedValue);
+ free(trimmedName);
+ free(trimmedValue);
+
+ switch (Configuration::i()->getType(stringName))
+ {
+ case CONFIG_TYPE_STRING:
+ Configuration::i()->setString(stringName, stringValue);
+ break;
+ case CONFIG_TYPE_INT:
+ Configuration::i()->setInt(stringName, atoi(stringValue.c_str()));
+ break;
+ case CONFIG_TYPE_BOOL:
+ bool boolValue;
+ if (string2bool(stringValue, &boolValue))
+ {
+ Configuration::i()->setBool(stringName, boolValue);
+ }
+ else
+ {
+ WARNING_MSG("The value %s is not a boolean", stringValue.c_str());
+ }
+ break;
+ case CONFIG_TYPE_UNSUPPORTED:
+ default:
+ WARNING_MSG("The following configuration is not supported: %s = %s",
+ stringName.c_str(), stringValue.c_str());
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ return true;
+}
+
+// Get the boolean value from a string
+bool SimpleConfigLoader::string2bool(std::string stringValue, bool* boolValue)
+{
+ // Convert to lowercase
+ std::transform(stringValue.begin(), stringValue.end(), stringValue.begin(), tolower);
+
+ if (stringValue.compare("true") == 0)
+ {
+ *boolValue = true;
+ return true;
+ }
+
+ if (stringValue.compare("false") == 0)
+ {
+ *boolValue = false;
+ return true;
+ }
+
+ return false;
+}
+
+#define CONFIG_FILE ".config/softhsm2/softhsm2.conf"
+
+/* Returns a user-specific path for configuration.
+ */
+static char *get_user_path(void)
+{
+#ifdef _WIN32
+ char path[512];
+ const char *home_drive = getenv("HOMEDRIVE");
+ const char *home_path = getenv("HOMEPATH");
+
+ if (home_drive && home_path) {
+ snprintf(path, sizeof(path), "%s%s\\softhsm2.conf", home_drive, home_path);
+
+ if (_access(path, 0) == 0)
+ return strdup(path);
+ }
+ goto fail;
+#else
+ char path[_POSIX_PATH_MAX];
+ const char *home_dir = getenv("HOME");
+
+ if (home_dir != NULL && home_dir[0] != 0) {
+ snprintf(path, sizeof(path), "%s/" CONFIG_FILE, home_dir);
+ if (access(path, R_OK) == 0)
+ return strdup(path);
+ else
+ goto fail;
+ }
+
+# if defined(HAVE_GETPWUID_R)
+ if (home_dir == NULL || home_dir[0] == '\0') {
+ struct passwd *pwd;
+ struct passwd _pwd;
+ int ret;
+ char tmp[512];
+
+ ret = getpwuid_r(getuid(), &_pwd, tmp, sizeof(tmp), &pwd);
+ if (ret == 0 && pwd != NULL) {
+ snprintf(path, sizeof(path), "%s/" CONFIG_FILE, pwd->pw_dir);
+ if (access(path, R_OK) == 0)
+ return strdup(path);
+ else
+ goto fail;
+ }
+ }
+# endif
+#endif
+
+ fail:
+ return NULL;
+}
+
+static char *get_env_var_path(void)
+{
+#ifdef _WIN32
+
+ LPSTR value = NULL;
+ DWORD size = 0;
+
+ size = GetEnvironmentVariableA("SOFTHSM2_CONF", value, size);
+ if (size == 0) {
+ return NULL;
+ }
+
+ value = (LPSTR) malloc(size);
+ if (NULL == value) {
+ return NULL;
+ }
+
+ if (GetEnvironmentVariableA("SOFTHSM2_CONF", value, size) != (size - 1)) {
+ free(value);
+ return NULL;
+ }
+
+ return value;
+
+#else
+
+ char *value = getenv("SOFTHSM2_CONF");
+
+ if (value == NULL) {
+ return value;
+ } else {
+ return strdup(value);
+ }
+
+#endif
+}
+
+char* SimpleConfigLoader::getConfigPath()
+{
+ char* configPath = get_env_var_path();
+ char* tpath;
+
+ if (configPath != NULL)
+ {
+ return configPath;
+ }
+ else
+ {
+ tpath = get_user_path();
+ if (tpath != NULL)
+ {
+ return tpath;
+ }
+ }
+
+ return strdup(DEFAULT_SOFTHSM2_CONF);
+}
+
+char* SimpleConfigLoader::trimString(char* text)
+{
+ if (text == NULL)
+ {
+ return NULL;
+ }
+
+ int startPos = 0;
+ int endPos = strlen(text) - 1;
+
+ // Find the first position without a space
+ while (startPos <= endPos && isspace((int)*(text + startPos)))
+ {
+ startPos++;
+ }
+ // Find the last position without a space
+ while (startPos <= endPos && isspace((int)*(text + endPos)))
+ {
+ endPos--;
+ }
+
+ // We must have a valid string
+ int length = endPos - startPos + 1;
+ if (length <= 0)
+ {
+ return NULL;
+ }
+
+ // Create the trimmed text
+ char* trimmedText = (char*)malloc(length + 1);
+ if (trimmedText == NULL)
+ {
+ return NULL;
+ }
+ trimmedText[length] = '\0';
+ memcpy(trimmedText, text + startPos, length);
+
+ return trimmedText;
+}
diff --git a/SoftHSMv2/src/lib/common/SimpleConfigLoader.h b/SoftHSMv2/src/lib/common/SimpleConfigLoader.h
new file mode 100644
index 0000000..e992cfb
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/SimpleConfigLoader.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 .SE, The Internet Infrastructure Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SimpleConfigLoader.h
+
+ Loads the configuration from the configuration file.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SIMPLECONFIGLOADER_H
+#define _SOFTHSM_V2_SIMPLECONFIGLOADER_H
+
+#include <memory>
+#include "config.h"
+#include "Configuration.h"
+
+class SimpleConfigLoader : public ConfigLoader
+{
+public:
+ static SimpleConfigLoader* i();
+
+ virtual ~SimpleConfigLoader() { }
+
+ virtual bool loadConfiguration();
+
+private:
+ SimpleConfigLoader();
+ char* getConfigPath();
+ char* trimString(char* text);
+ bool string2bool(std::string stringValue, bool* boolValue);
+
+#ifdef HAVE_CXX11
+ static std::unique_ptr<SimpleConfigLoader> instance;
+#else
+ static std::auto_ptr<SimpleConfigLoader> instance;
+#endif
+};
+
+#endif // !_SOFTHSM_V2_SIMPLECONFIGLOADER_H
+
diff --git a/SoftHSMv2/src/lib/common/fatal.cpp b/SoftHSMv2/src/lib/common/fatal.cpp
new file mode 100644
index 0000000..4da26f4
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/fatal.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ fatal.cpp
+
+ Implementens calls for handling fatal exceptions. When a fatal exception
+ occurs, this code ensures that as much of the securely allocated memory as
+ possible is wiped clean.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "fatal.h"
+#include "SecureMemoryRegistry.h"
+#include "cryptoki.h"
+
+void FatalException(void)
+{
+ try
+ {
+ DEBUG_MSG("Fatal exception handler called");
+ }
+ catch (...)
+ {
+ }
+
+ // Wipe as much of the securely allocated memory as possible
+ SecureMemoryRegistry::i()->wipe();
+
+ try
+ {
+ ERROR_MSG("A fatal exception occurred; exiting...");
+ }
+ catch (...)
+ {
+ }
+
+ exit(CKR_GENERAL_ERROR);
+}
+
diff --git a/SoftHSMv2/src/lib/common/fatal.h b/SoftHSMv2/src/lib/common/fatal.h
new file mode 100644
index 0000000..124265e
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/fatal.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ fatal.h
+
+ Implementens calls for handling fatal exceptions. When a fatal exception
+ occurs, this code ensures that as much of the securely allocated memory as
+ possible is wiped clean.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FATAL_H
+#define _SOFTHSM_V2_FATAL_H
+
+#include "config.h"
+#include "log.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif // __cplusplus
+
+void FatalException(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // !_SOFTHSM_V2_FATAL_H
+
diff --git a/SoftHSMv2/src/lib/common/log.cpp b/SoftHSMv2/src/lib/common/log.cpp
new file mode 100644
index 0000000..7400f6a
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/log.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ log.cpp
+
+ Implements logging functions. This file is based on the concepts from
+ SoftHSM v1 but extends the logging functions with support for a variable
+ argument list as defined in stdarg (3).
+ *****************************************************************************/
+
+#include "config.h"
+#include <stdarg.h>
+#include <syslog.h>
+#include <stdio.h>
+#include <sstream>
+#include <vector>
+#include "log.h"
+
+int softLogLevel = LOG_DEBUG;
+
+bool setLogLevel(const std::string &loglevel)
+{
+ if (loglevel == "ERROR")
+ {
+ softLogLevel = LOG_ERR;
+ }
+ else if (loglevel == "WARNING")
+ {
+ softLogLevel = LOG_WARNING;
+ }
+ else if (loglevel == "INFO")
+ {
+ softLogLevel = LOG_INFO;
+ }
+ else if (loglevel == "DEBUG")
+ {
+ softLogLevel = LOG_DEBUG;
+ }
+ else
+ {
+ ERROR_MSG("Unknown value (%s) for log.level in configuration", loglevel.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+void softHSMLog(const int loglevel, const char* functionName, const char* fileName, const int lineNo, const char* format, ...)
+{
+ if (loglevel > softLogLevel) return;
+
+ std::stringstream prepend;
+
+#ifdef SOFTHSM_LOG_FILE_AND_LINE
+ prepend << fileName << "(" << lineNo << ")";
+#ifndef SOFTHSM_LOG_FUNCTION_NAME
+ (void) functionName;
+ prepend << ":";
+#endif // !SOFTHSM_LOG_FUNCTION_NAME
+ prepend << " ";
+#endif // SOFTHSM_LOG_FILE_AND_LINE
+
+#ifdef SOFTHSM_LOG_FUNCTION_NAME
+ prepend << functionName << ": ";
+#endif // SOFTHSM_LOG_FUNCTION_NAME
+
+ // Print the format to a log message
+ std::vector<char> logMessage;
+ va_list args;
+
+ logMessage.resize(4096);
+
+ va_start(args, format);
+ vsnprintf(&logMessage[0], 4096, format, args);
+ va_end(args);
+
+ // And log it
+ syslog(loglevel, "%s%s", prepend.str().c_str(), &logMessage[0]);
+
+#ifdef DEBUG_LOG_STDERR
+ fprintf(stderr, "%s%s\n", prepend.str().c_str(), &logMessage[0]);
+ fflush(stderr);
+#endif // DEBUG_LOG_STDERR
+}
+
diff --git a/SoftHSMv2/src/lib/common/log.h b/SoftHSMv2/src/lib/common/log.h
new file mode 100644
index 0000000..cf91aaf
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/log.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ log.h
+
+ Implements logging functions. This file is based on the concepts from
+ SoftHSM v1 but extends the logging functions with support for a variable
+ argument list as defined in stdarg (3).
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_LOG_H
+#define _SOFTHSM_V2_LOG_H
+
+#include "config.h"
+
+#include <syslog.h>
+#include <string>
+
+/* Unset this define if you don't want to log the source file name and line number */
+#define SOFTHSM_LOG_FILE_AND_LINE
+
+/* Set this define to log the function name */
+/* #define SOFTHSM_LOG_FUNCTION_NAME */
+
+/* Define this symbol (either here or in the build setup) to log to stderr */
+/* #define DEBUG_LOG_STDERR */
+
+/* Logging errors */
+#ifndef _WIN32
+#define ERROR_MSG(...) softHSMLog(LOG_ERR, __func__, __FILE__, __LINE__, __VA_ARGS__);
+#else
+#define ERROR_MSG(...) softHSMLog(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__);
+#endif
+
+/* Logging warnings */
+#ifndef _WIN32
+#define WARNING_MSG(...) softHSMLog(LOG_WARNING, __func__, __FILE__, __LINE__, __VA_ARGS__);
+#else
+#define WARNING_MSG(...) softHSMLog(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__);
+#endif
+
+/* Logging information */
+#ifndef _WIN32
+#define INFO_MSG(...) softHSMLog(LOG_INFO, __func__, __FILE__, __LINE__, __VA_ARGS__);
+#else
+#define INFO_MSG(...) softHSMLog(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__);
+#endif
+
+/* Logging debug information */
+#ifndef _WIN32
+#define DEBUG_MSG(...) softHSMLog(LOG_DEBUG, __func__, __FILE__, __LINE__, __VA_ARGS__);
+#else
+#define DEBUG_MSG(...) softHSMLog(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__);
+#endif
+
+/* Function definitions */
+bool setLogLevel(const std::string &loglevel);
+void softHSMLog(const int loglevel, const char* functionName, const char* fileName, const int lineNo, const char* format, ...);
+
+#endif /* !_SOFTHSM_V2_LOG_H */
+
diff --git a/SoftHSMv2/src/lib/common/osmutex.cpp b/SoftHSMv2/src/lib/common/osmutex.cpp
new file mode 100644
index 0000000..28db10e
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/osmutex.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2008-2010 .SE (The Internet Infrastructure Foundation).
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ osmutex.cpp
+
+ Contains OS-specific implementations of intraprocess mutex functions. This
+ implementation is based on SoftHSM v1
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "osmutex.h"
+
+#ifdef HAVE_PTHREAD_H
+
+#include <stdlib.h>
+#include <pthread.h>
+
+CK_RV OSCreateMutex(CK_VOID_PTR_PTR newMutex)
+{
+ int rv;
+
+ /* Allocate memory */
+ pthread_mutex_t* pthreadMutex = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
+
+ if (pthreadMutex == NULL)
+ {
+ ERROR_MSG("Failed to allocate memory for a new mutex");
+
+ return CKR_HOST_MEMORY;
+ }
+
+ /* Initialise the mutex */
+ if ((rv = pthread_mutex_init(pthreadMutex, NULL)) != 0)
+ {
+ free(pthreadMutex);
+
+ ERROR_MSG("Failed to initialise POSIX mutex (0x%08X)", rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ *newMutex = pthreadMutex;
+
+ return CKR_OK;
+}
+
+CK_RV OSDestroyMutex(CK_VOID_PTR mutex)
+{
+ int rv;
+ pthread_mutex_t* pthreadMutex = (pthread_mutex_t*) mutex;
+
+ if (pthreadMutex == NULL)
+ {
+ ERROR_MSG("Cannot destroy NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if ((rv = pthread_mutex_destroy(pthreadMutex)) != 0)
+ {
+ ERROR_MSG("Failed to destroy POSIX mutex (0x%08X)", rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ free(pthreadMutex);
+
+ return CKR_OK;
+}
+
+CK_RV OSLockMutex(CK_VOID_PTR mutex)
+{
+ int rv;
+ pthread_mutex_t* pthreadMutex = (pthread_mutex_t*) mutex;
+
+ if (pthreadMutex == NULL)
+ {
+ ERROR_MSG("Cannot lock NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if ((rv = pthread_mutex_lock(pthreadMutex)) != 0)
+ {
+ ERROR_MSG("Failed to lock POSIX mutex 0x%08X (0x%08X)", pthreadMutex, rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV OSUnlockMutex(CK_VOID_PTR mutex)
+{
+ int rv;
+ pthread_mutex_t* pthreadMutex = (pthread_mutex_t*) mutex;
+
+ if (pthreadMutex == NULL)
+ {
+ ERROR_MSG("Cannot unlock NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if ((rv = pthread_mutex_unlock(pthreadMutex)) != 0)
+ {
+ ERROR_MSG("Failed to unlock POSIX mutex 0x%08X (0x%08X)", pthreadMutex, rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+#elif _WIN32
+
+CK_RV OSCreateMutex(CK_VOID_PTR_PTR newMutex)
+{
+ HANDLE hMutex;
+
+ hMutex = CreateMutex(NULL, FALSE, NULL);
+ if (hMutex == NULL)
+ {
+ DWORD rv = GetLastError();
+
+ ERROR_MSG("Failed to initialise WIN32 mutex (0x%08X)", rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ *newMutex = hMutex;
+
+ return CKR_OK;
+}
+
+CK_RV OSDestroyMutex(CK_VOID_PTR mutex)
+{
+ HANDLE hMutex = (HANDLE) mutex;
+
+ if (hMutex == NULL)
+ {
+ ERROR_MSG("Cannot destroy NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if (CloseHandle(hMutex) == 0)
+ {
+ DWORD rv = GetLastError();
+
+ ERROR_MSG("Failed to destroy WIN32 mutex (0x%08X)", rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV OSLockMutex(CK_VOID_PTR mutex)
+{
+ DWORD rv;
+ HANDLE hMutex = (HANDLE) mutex;
+
+ if (hMutex == NULL)
+ {
+ ERROR_MSG("Cannot lock NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ rv = WaitForSingleObject(hMutex, INFINITE);
+ if (rv != WAIT_OBJECT_0)
+ {
+ // WAIT_ABANDONED 0x00000080
+ // WAIT_OBJECT_0 0x00000000
+ // WAIT_TIMEOUT 0x00000102
+ // WAIT_FAILED 0xFFFFFFFF
+
+ if (rv == WAIT_FAILED)
+ rv = GetLastError();
+
+ ERROR_MSG("Failed to lock WIN32 mutex 0x%08X (0x%08X)", hMutex, rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV OSUnlockMutex(CK_VOID_PTR mutex)
+{
+ HANDLE hMutex = (HANDLE) mutex;
+
+ if (hMutex == NULL)
+ {
+ ERROR_MSG("Cannot unlock NULL mutex");
+
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if (ReleaseMutex(hMutex) == 0)
+ {
+ DWORD rv = GetLastError();
+
+ ERROR_MSG("Failed to unlock WIN32 mutex 0x%08X (0x%08X)", hMutex, rv);
+
+ return CKR_GENERAL_ERROR;
+ }
+
+ return CKR_OK;
+}
+
+#else
+#error "There are no mutex implementations for your operating system yet"
+#endif
+
diff --git a/SoftHSMv2/src/lib/common/osmutex.h b/SoftHSMv2/src/lib/common/osmutex.h
new file mode 100644
index 0000000..103dc67
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/osmutex.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2008-2010 .SE (The Internet Infrastructure Foundation).
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ osmutex.h
+
+ Contains OS-specific implementations of intraprocess mutex functions. This
+ implementation is based on SoftHSM v1
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSMUTEX_H
+#define _SOFTHSM_V2_OSMUTEX_H
+
+#include "config.h"
+#include "cryptoki.h"
+
+CK_RV OSCreateMutex(CK_VOID_PTR_PTR newMutex);
+CK_RV OSDestroyMutex(CK_VOID_PTR mutex);
+CK_RV OSLockMutex(CK_VOID_PTR mutex);
+CK_RV OSUnlockMutex(CK_VOID_PTR mutex);
+
+#endif /* !_SOFTHSM_V2_OSMUTEX_H */
+
diff --git a/SoftHSMv2/src/lib/common/softhsm2.conf.5.in b/SoftHSMv2/src/lib/common/softhsm2.conf.5.in
new file mode 100644
index 0000000..5291a09
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/softhsm2.conf.5.in
@@ -0,0 +1,86 @@
+.TH softhsm2.conf 5 "30 October 2014" "SoftHSM"
+.SH NAME
+softhsm2.conf \- SoftHSM configuration file
+.SH SYNOPSIS
+.B softhsm2.conf
+.SH DESCRIPTION
+This is the configuration file for SoftHSM. It can be found on a
+default location, but can also be relocated by using the
+environment variable. Any configuration must be done according
+to the file format found in this document.
+.SH FILE FORMAT
+Each configuration option is a pair of name and value separated by
+a equality sign. The configuration option must be located on a single line.
+.LP
+.RS
+.nf
+<name> = <value>
+.fi
+.RE
+.LP
+It is also possible to add comments in the file by using the hash sign.
+Anything after the hash sign will be ignored.
+.LP
+.RS
+.nf
+# A comment
+.RE
+.LP
+Any empty lines or lines that does not have the correct format will be ignored.
+.SH DIRECTORIES.TOKENDIR
+The location where SoftHSM can store the tokens.
+.LP
+.RS
+.nf
+directories.tokendir = @softhsmtokendir@
+.fi
+.RE
+.LP
+.SH OBJECTSTORE.BACKEND
+The backend to use by SoftHSM to store token objects. Either "file" or "db" is supported.
+In order to use the "db" backend, the SoftHSM build needs to be configured with "configure --with-objectstore-backend-db"
+.LP
+.RS
+.nf
+objectstore.backend = file
+.fi
+.RE
+.LP
+.SH LOG.LEVEL
+The log level which can be set to ERROR, WARNING, INFO or DEBUG.
+.LP
+.RS
+.nf
+log.level = INFO
+.fi
+.RE
+.LP
+.SH SLOTS.REMOVABLE
+If set to true CKF_REMOVABLE_DEVICE is set in the flags returned by C_GetSlotInfo. Default is false.
+.LP
+.RS
+.nf
+slots.removable = true
+.fi
+.RE
+.LP
+.SH ENVIRONMENT
+.TP
+SOFTHSM2_CONF
+When defined, the value will be used as path to the configuration file.
+.SH FILES
+.TP
+.I ~/.config/softhsm2/softhsm2.conf
+default user-specific location of the SoftHSM configuration file; if it exists it will override the system wide configuration
+.TP
+.I @default_softhsm2_conf@
+default system-wide location of the SoftHSM configuration file
+.TP
+.I @default_softhsm2_conf@.sample
+an example of a SoftHSM configuration file
+.SH AUTHOR
+Written by Rickard Bellgrim, Francis Dupont, René Post, and Roland van Rijswijk.
+.SH "SEE ALSO"
+.IR softhsm2-keyconv (1),
+.IR softhsm2-migrate (1),
+.IR softhsm2-util (1)
diff --git a/SoftHSMv2/src/lib/common/softhsm2.conf.in b/SoftHSMv2/src/lib/common/softhsm2.conf.in
new file mode 100644
index 0000000..3d5728d
--- /dev/null
+++ b/SoftHSMv2/src/lib/common/softhsm2.conf.in
@@ -0,0 +1,10 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = @softhsmtokendir@
+objectstore.backend = file
+
+# ERROR, WARNING, INFO, DEBUG
+log.level = ERROR
+
+# If CKF_REMOVABLE_DEVICE flag should be set
+slots.removable = false
diff --git a/SoftHSMv2/src/lib/crypto/AESKey.cpp b/SoftHSMv2/src/lib/crypto/AESKey.cpp
new file mode 100644
index 0000000..9b511b5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/AESKey.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AESKey.cpp
+
+ AES key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include "AESKey.h"
+#include "CryptoFactory.h"
+
+// Get key check value
+ByteString AESKey::getKeyCheckValue() const
+{
+ ByteString iv;
+ ByteString data;
+ ByteString encryptedData;
+ ByteString encryptedFinal;
+
+ SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
+ if (cipher == NULL) return encryptedData;
+
+ // Single block of null (0x00) bytes
+ data.resize(cipher->getBlockSize());
+ memset(&data[0], 0, data.size());
+
+ if (!cipher->encryptInit(this, SymMode::ECB, iv, false) ||
+ !cipher->encryptUpdate(data, encryptedData) ||
+ !cipher->encryptFinal(encryptedFinal))
+ {
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return encryptedData;
+ }
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+
+ encryptedData += encryptedFinal;
+ encryptedData.resize(3);
+
+ return encryptedData;
+}
diff --git a/SoftHSMv2/src/lib/crypto/AESKey.h b/SoftHSMv2/src/lib/crypto/AESKey.h
new file mode 100644
index 0000000..6505b9d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/AESKey.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AESKey.h
+
+ AES key symmetric key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_AESKEY_H
+#define _SOFTHSM_V2_AESKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "SymmetricKey.h"
+
+class AESKey : public SymmetricKey
+{
+public:
+ // Base constructor
+ AESKey(size_t inBitLen = 0) : SymmetricKey(inBitLen) { }
+
+ // Get the key check value
+ virtual ByteString getKeyCheckValue() const;
+};
+
+#endif // !SOFTHSM_V2_AESKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.cpp
new file mode 100644
index 0000000..20a50a5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricAlgorithm.cpp
+
+ Base class for asymmetric algorithm classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "AsymmetricAlgorithm.h"
+
+// Base constructor
+AsymmetricAlgorithm::AsymmetricAlgorithm()
+{
+ currentOperation = NONE;
+ currentMechanism = AsymMech::Unknown;
+ currentPadding = AsymMech::Unknown;
+ currentPublicKey = NULL;
+ currentPrivateKey = NULL;
+}
+
+// Signing functions
+bool AsymmetricAlgorithm::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ // Compose from multi-part operations
+ return (signInit(privateKey, mechanism, param, paramLen) && signUpdate(dataToSign) && signFinal(signature));
+}
+
+bool AsymmetricAlgorithm::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ if ((currentOperation != NONE) || (privateKey == NULL))
+ {
+ return false;
+ }
+
+ currentPrivateKey = privateKey;
+ currentMechanism = mechanism;
+ currentOperation = SIGN;
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::signUpdate(const ByteString& /*dataToSign*/)
+{
+ if (currentOperation != SIGN)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::signFinal(ByteString& /*signature*/)
+{
+ if (currentOperation != SIGN)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+ currentPrivateKey = NULL;
+ currentMechanism = AsymMech::Unknown;
+
+ return true;
+}
+
+// Verification functions
+bool AsymmetricAlgorithm::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ // Compose from multi-part operations
+ return (verifyInit(publicKey, mechanism, param, paramLen) && verifyUpdate(originalData) && verifyFinal(signature));
+}
+
+bool AsymmetricAlgorithm::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ if ((currentOperation != NONE) || (publicKey == NULL))
+ {
+ return false;
+ }
+
+ currentOperation = VERIFY;
+ currentPublicKey = publicKey;
+ currentMechanism = mechanism;
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::verifyUpdate(const ByteString& /*originalData*/)
+{
+ if (currentOperation != VERIFY)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool AsymmetricAlgorithm::verifyFinal(const ByteString& /*signature*/)
+{
+ if (currentOperation != VERIFY)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+ currentPublicKey = NULL;
+ currentMechanism = AsymMech::Unknown;
+
+ return true;
+}
+
+// Returns true for mechanisms which have 'tick mark' in Wrap&Unwrap column in PKCS #11 Mechanisms v2.40
+bool AsymmetricAlgorithm::isWrappingMech(AsymMech::Type padding)
+{
+ switch (padding)
+ {
+ case AsymMech::RSA:
+ case AsymMech::RSA_PKCS:
+ case AsymMech::RSA_PKCS_OAEP:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+// Wrap/Unwrap keys
+bool AsymmetricAlgorithm::wrapKey(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding)
+{
+ if (!isWrappingMech(padding))
+ return false;
+
+ return encrypt(publicKey, data, encryptedData, padding);
+}
+
+bool AsymmetricAlgorithm::unwrapKey(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding)
+{
+ if (!isWrappingMech(padding))
+ return false;
+
+ return decrypt(privateKey, encryptedData, data, padding);
+}
+
+
+bool AsymmetricAlgorithm::generateParameters(AsymmetricParameters** /*ppParams*/, void* /*parameters = NULL*/, RNG* /*rng = NULL*/)
+{
+ return false;
+}
+
+bool AsymmetricAlgorithm::deriveKey(SymmetricKey** /*ppSymmetricKey*/, PublicKey* /*publicKey*/, PrivateKey* /*privateKey*/)
+{
+ return false;
+}
+
+bool AsymmetricAlgorithm::reconstructParameters(AsymmetricParameters** /*ppParams*/, ByteString& /*serialisedData*/)
+{
+ return false;
+}
+
+AsymmetricParameters* AsymmetricAlgorithm::newParameters()
+{
+ return NULL;
+}
+
+// Key recycling -- override these functions in a derived class if you need to perform specific cleanup
+void AsymmetricAlgorithm::recycleKeyPair(AsymmetricKeyPair* toRecycle)
+{
+ delete toRecycle;
+}
+
+void AsymmetricAlgorithm::recycleParameters(AsymmetricParameters* toRecycle)
+{
+ delete toRecycle;
+}
+
+void AsymmetricAlgorithm::recyclePublicKey(PublicKey* toRecycle)
+{
+ delete toRecycle;
+}
+
+void AsymmetricAlgorithm::recyclePrivateKey(PrivateKey* toRecycle)
+{
+ delete toRecycle;
+}
+
+void AsymmetricAlgorithm::recycleSymmetricKey(SymmetricKey* toRecycle)
+{
+ delete toRecycle;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h
new file mode 100644
index 0000000..ca0d840
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricAlgorithm.h
+
+ Base class for asymmetric algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMMETRICALGORITHM_H
+#define _SOFTHSM_V2_ASYMMETRICALGORITHM_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricParameters.h"
+#include "HashAlgorithm.h"
+#include "PublicKey.h"
+#include "PrivateKey.h"
+#include "RNG.h"
+#include "SymmetricKey.h"
+
+struct AsymAlgo
+{
+ enum Type
+ {
+ Unknown,
+ RSA,
+ DSA,
+ DH,
+ ECDH,
+ ECDSA,
+ GOST
+ };
+};
+
+struct AsymMech
+{
+ enum Type
+ {
+ Unknown,
+ RSA,
+ RSA_MD5_PKCS,
+ RSA_PKCS,
+ RSA_PKCS_OAEP,
+ RSA_SHA1_PKCS,
+ RSA_SHA224_PKCS,
+ RSA_SHA256_PKCS,
+ RSA_SHA384_PKCS,
+ RSA_SHA512_PKCS,
+ RSA_PKCS_PSS,
+ RSA_SHA1_PKCS_PSS,
+ RSA_SHA224_PKCS_PSS,
+ RSA_SHA256_PKCS_PSS,
+ RSA_SHA384_PKCS_PSS,
+ RSA_SHA512_PKCS_PSS,
+ RSA_SSL,
+ DSA,
+ DSA_SHA1,
+ DSA_SHA224,
+ DSA_SHA256,
+ DSA_SHA384,
+ DSA_SHA512,
+ ECDSA,
+ GOST,
+ GOST_GOST
+ };
+};
+
+struct AsymRSAMGF
+{
+ enum Type
+ {
+ Unknown,
+ MGF1_SHA1,
+ MGF1_SHA224,
+ MGF1_SHA256,
+ MGF1_SHA384,
+ MGF1_SHA512
+ };
+};
+
+struct RSA_PKCS_PSS_PARAMS
+{
+ HashAlgo::Type hashAlg;
+ AsymRSAMGF::Type mgf;
+ size_t sLen;
+};
+
+class AsymmetricAlgorithm
+{
+public:
+ // Base constructors
+ AsymmetricAlgorithm();
+
+ // Destructor
+ virtual ~AsymmetricAlgorithm() { }
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding) = 0;
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding) = 0;
+
+ // Wrap/Unwrap keys
+ bool wrapKey(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+ bool unwrapKey(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL) = 0;
+ virtual unsigned long getMinKeySize() = 0;
+ virtual unsigned long getMaxKeySize() = 0;
+ virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL);
+ virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData) = 0;
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) = 0;
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) = 0;
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey() = 0;
+ virtual PrivateKey* newPrivateKey() = 0;
+ virtual AsymmetricParameters* newParameters();
+
+ // Key recycling -- override these functions in a derived class if you need to perform specific cleanup
+ virtual void recycleKeyPair(AsymmetricKeyPair* toRecycle);
+ virtual void recycleParameters(AsymmetricParameters* toRecycle);
+ virtual void recyclePublicKey(PublicKey* toRecycle);
+ virtual void recyclePrivateKey(PrivateKey* toRecycle);
+ virtual void recycleSymmetricKey(SymmetricKey* toRecycle);
+
+protected:
+ PublicKey* currentPublicKey;
+ PrivateKey* currentPrivateKey;
+
+ AsymMech::Type currentMechanism;
+ AsymMech::Type currentPadding;
+
+private:
+ enum
+ {
+ NONE,
+ SIGN,
+ VERIFY
+ }
+ currentOperation;
+
+ bool isWrappingMech(AsymMech::Type padding);
+};
+
+#endif // !_SOFTHSM_V2_ASYMMETRICALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.cpp b/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.cpp
new file mode 100644
index 0000000..a31c17e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricKeyPair.cpp
+
+ Asymmetric key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "AsymmetricKeyPair.h"
+
+ByteString AsymmetricKeyPair::serialise() const
+{
+ return getConstPublicKey()->serialise().serialise() + getConstPrivateKey()->serialise().serialise();
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.h b/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.h
new file mode 100644
index 0000000..8ff63ef
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricKeyPair.h
+
+ Base class for asymmetric key-pair classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMMETRICKEYPAIR_H
+#define _SOFTHSM_V2_ASYMMETRICKEYPAIR_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "PublicKey.h"
+#include "PrivateKey.h"
+#include "Serialisable.h"
+
+class AsymmetricKeyPair : public Serialisable
+{
+public:
+ // Base constructors
+ AsymmetricKeyPair() { }
+
+ AsymmetricKeyPair(const AsymmetricKeyPair& /*in*/) { }
+
+ // Destructor
+ virtual ~AsymmetricKeyPair() { }
+
+ // Return the public key
+ virtual PublicKey* getPublicKey() = 0;
+ virtual const PublicKey* getConstPublicKey() const = 0;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey() = 0;
+ virtual const PrivateKey* getConstPrivateKey() const = 0;
+
+ // Serialise the contents
+ virtual ByteString serialise() const;
+};
+
+#endif // !_SOFTHSM_V2_ASYMMETRICKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricParameters.h b/SoftHSMv2/src/lib/crypto/AsymmetricParameters.h
new file mode 100644
index 0000000..12c607b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/AsymmetricParameters.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymmetricParameters.h
+
+ Base class for asymmetric parameter classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMMETRICPARAMETERS_H
+#define _SOFTHSM_V2_ASYMMETRICPARAMETERS_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+
+class AsymmetricParameters : public Serialisable
+{
+public:
+ // Base constructors
+ AsymmetricParameters() { }
+
+ AsymmetricParameters(const AsymmetricParameters& /*in*/) { }
+
+ // Destructor
+ virtual ~AsymmetricParameters() { }
+
+ // Check if it is of the given type
+ virtual bool areOfType(const char* type) = 0;
+
+ // Serialisation
+ virtual ByteString serialise() const = 0;
+};
+
+#endif // !_SOFTHSM_V2_ASYMMETRICPARAMETERS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanAES.cpp b/SoftHSMv2/src/lib/crypto/BotanAES.cpp
new file mode 100644
index 0000000..0c67a09
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanAES.cpp
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanAES.cpp
+
+ Botan AES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanAES.h"
+#include <algorithm>
+#include <botan/rfc3394.h>
+#include <botan/version.h>
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+#include <botan/libstate.h>
+#endif
+
+// Wrap/Unwrap keys
+bool BotanAES::wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out)
+{
+ // Check key bit length; AES only supports 128, 192 or 256 bit keys
+ if ((key->getBitLen() != 128) &&
+ (key->getBitLen() != 192) &&
+ (key->getBitLen() != 256))
+ {
+ ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen());
+
+ return false;
+ }
+
+ // Determine the wrapping mode
+ if (mode == SymWrap::AES_KEYWRAP)
+ {
+ // RFC 3394 AES key wrap
+ if (in.size() < 16)
+ {
+ ERROR_MSG("key data to wrap too small");
+
+ return false;
+ }
+ if ((in.size() % 8) != 0)
+ {
+ ERROR_MSG("key data to wrap not aligned");
+
+ return false;
+ }
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> data(in.size());
+ memcpy(data.data(), in.const_byte_str(), in.size());
+ Botan::secure_vector<Botan::byte> wrapped;
+#else
+ Botan::MemoryVector<Botan::byte> data(in.size());
+ memcpy(data.begin(), in.const_byte_str(), in.size());
+ Botan::SecureVector<Botan::byte> wrapped;
+#endif
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+ try
+ {
+ wrapped = Botan::rfc3394_keywrap(data, botanKey, af);
+ }
+#else
+ try
+ {
+ wrapped = Botan::rfc3394_keywrap(data, botanKey);
+ }
+#endif
+ catch (...)
+ {
+ ERROR_MSG("AES key wrap failed");
+
+ return false;
+ }
+ out.resize(wrapped.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&out[0], wrapped.data(), out.size());
+#else
+ memcpy(&out[0], wrapped.begin(), out.size());
+#endif
+
+ return true;
+ }
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ else if (mode == SymWrap::AES_KEYWRAP_PAD)
+ {
+ // RFC 5649 AES key wrap with pad
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> data(in.size());
+ memcpy(data.data(), in.const_byte_str(), in.size());
+ Botan::secure_vector<Botan::byte> wrapped;
+#else
+ Botan::MemoryVector<Botan::byte> data(in.size());
+ memcpy(data.begin(), in.const_byte_str(), in.size());
+ Botan::SecureVector<Botan::byte> wrapped;
+#endif
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+ try
+ {
+ wrapped = Botan::rfc5649_keywrap(data, botanKey, af);
+ }
+#else
+ try
+ {
+ wrapped = Botan::rfc5649_keywrap(data, botanKey);
+ }
+#endif
+ catch (...)
+ {
+ ERROR_MSG("AES key wrap failed");
+
+ return false;
+ }
+ out.resize(wrapped.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&out[0], wrapped.data(), out.size());
+#else
+ memcpy(&out[0], wrapped.begin(), out.size());
+#endif
+
+ return true;
+ }
+#endif
+ else
+ {
+ ERROR_MSG("unknown AES key wrap mode %i", mode);
+
+ return false;
+ }
+}
+
+bool BotanAES::unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out)
+{
+ // Check key bit length; AES only supports 128, 192 or 256 bit keys
+ if ((key->getBitLen() != 128) &&
+ (key->getBitLen() != 192) &&
+ (key->getBitLen() != 256))
+ {
+ ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen());
+
+ return false;
+ }
+
+ // Determine the unwrapping mode
+ if (mode == SymWrap::AES_KEYWRAP)
+ {
+ // RFC 3394 AES key wrap
+ if (in.size() < 24)
+ {
+ ERROR_MSG("key data to unwrap too small");
+
+ return false;
+ }
+ if ((in.size() % 8) != 0)
+ {
+ ERROR_MSG("key data to unwrap not aligned");
+
+ return false;
+ }
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> wrapped(in.size());
+ memcpy(wrapped.data(), in.const_byte_str(), in.size());
+ Botan::secure_vector<Botan::byte> unwrapped;
+#else
+ Botan::MemoryVector<Botan::byte> wrapped(in.size());
+ memcpy(wrapped.begin(), in.const_byte_str(), in.size());
+ Botan::SecureVector<Botan::byte> unwrapped;
+#endif
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+ try
+ {
+ unwrapped = Botan::rfc3394_keyunwrap(wrapped, botanKey, af);
+ }
+#else
+ try
+ {
+ unwrapped = Botan::rfc3394_keyunwrap(wrapped, botanKey);
+ }
+#endif
+ catch (...)
+ {
+ ERROR_MSG("AES key unwrap failed");
+
+ return false;
+ }
+ out.resize(unwrapped.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&out[0], unwrapped.data(), out.size());
+#else
+ memcpy(&out[0], unwrapped.begin(), out.size());
+#endif
+
+ return true;
+ }
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ else if (mode == SymWrap::AES_KEYWRAP_PAD)
+ {
+ // RFC 5649 AES key wrap with wrap
+ if (in.size() < 16)
+ {
+ ERROR_MSG("key data to unwrap too small");
+
+ return false;
+ }
+ if ((in.size() % 8) != 0)
+ {
+ ERROR_MSG("key data to unwrap not aligned");
+
+ return false;
+ }
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> wrapped(in.size());
+ memcpy(wrapped.data(), in.const_byte_str(), in.size());
+ Botan::secure_vector<Botan::byte> unwrapped;
+#else
+ Botan::MemoryVector<Botan::byte> wrapped(in.size());
+ memcpy(wrapped.begin(), in.const_byte_str(), in.size());
+ Botan::SecureVector<Botan::byte> unwrapped;
+#endif
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+ try
+ {
+ unwrapped = Botan::rfc5649_keyunwrap(wrapped, botanKey, af);
+ }
+#else
+ try
+ {
+ unwrapped = Botan::rfc5649_keyunwrap(wrapped, botanKey);
+ }
+#endif
+ catch (...)
+ {
+ ERROR_MSG("AES key unwrap failed");
+
+ return false;
+ }
+ out.resize(unwrapped.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&out[0], unwrapped.data(), out.size());
+#else
+ memcpy(&out[0], unwrapped.begin(), out.size());
+#endif
+
+ return true;
+ }
+#endif
+ else
+ {
+ ERROR_MSG("unknown AES key wrap mode %i", mode);
+
+ return false;
+ }
+}
+
+std::string BotanAES::getCipher() const
+{
+ std::string algo;
+ std::string mode;
+ std::string padding;
+
+ if (currentKey == NULL) return "";
+
+ // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys
+ switch (currentKey->getBitLen())
+ {
+ case 128:
+ algo = "AES-128";
+ break;
+ case 192:
+ algo = "AES-192";
+ break;
+ case 256:
+ algo = "AES-256";
+ break;
+ default:
+ ERROR_MSG("Invalid AES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return "";
+ }
+
+ // Determine the cipher mode
+ switch (currentCipherMode)
+ {
+ case SymMode::CBC:
+ mode = "CBC";
+ break;
+ case SymMode::CTR:
+ return algo + "/CTR-BE";
+ case SymMode::ECB:
+ mode = "ECB";
+ break;
+#ifdef WITH_AES_GCM
+ case SymMode::GCM:
+ return algo + "/GCM(" + std::to_string(currentTagBytes) + ")";
+#endif
+ default:
+ ERROR_MSG("Invalid AES cipher mode %i", currentCipherMode);
+
+ return "";
+ }
+
+ // Check padding mode
+ if (currentPaddingMode)
+ {
+ padding = "PKCS7";
+ }
+ else
+ {
+ padding = "NoPadding";
+ }
+
+ return algo + "/" + mode + "/" + padding;
+}
+
+size_t BotanAES::getBlockSize() const
+{
+ // The block size is 128 bits
+ return 128 >> 3;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanAES.h b/SoftHSMv2/src/lib/crypto/BotanAES.h
new file mode 100644
index 0000000..4bc38ab
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanAES.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanAES.h
+
+ Botan AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANAES_H
+#define _SOFTHSM_V2_BOTANAES_H
+
+#include <string>
+#include "config.h"
+#include "BotanSymmetricAlgorithm.h"
+
+class BotanAES : public BotanSymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~BotanAES() { }
+
+ // Wrap/Unwrap keys
+ virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out);
+
+ virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out);
+
+ // Return the block size
+ virtual size_t getBlockSize() const;
+
+protected:
+ // Return the right Botan cipher for the operation
+ virtual std::string getCipher() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANAES_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp
new file mode 100644
index 0000000..b4df224
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanCryptoFactory.cpp
+
+ This is a Botan based cryptographic algorithm factory
+ *****************************************************************************/
+#include "config.h"
+#include "BotanCryptoFactory.h"
+#include "BotanAES.h"
+#include "BotanDES.h"
+#include "BotanDSA.h"
+#include "BotanDH.h"
+#ifdef WITH_ECC
+#include "BotanECDH.h"
+#include "BotanECDSA.h"
+#endif
+#include "BotanMD5.h"
+#include "BotanRNG.h"
+#include "BotanRSA.h"
+#include "BotanSHA1.h"
+#include "BotanSHA224.h"
+#include "BotanSHA256.h"
+#include "BotanSHA384.h"
+#include "BotanSHA512.h"
+#ifdef WITH_GOST
+#include "BotanGOST.h"
+#include "BotanGOSTR3411.h"
+#endif
+#include "BotanMAC.h"
+
+#include <botan/init.h>
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+#include <botan/libstate.h>
+#endif
+
+// Constructor
+BotanCryptoFactory::BotanCryptoFactory()
+{
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ wasInitialized = false;
+
+ // Check if Botan has already been initialized
+ if (Botan::Global_State_Management::global_state_exists())
+ {
+ wasInitialized = true;
+ }
+
+ // Init the Botan crypto library
+ if (!wasInitialized)
+ {
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+ }
+#else
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+#endif
+
+ // Create mutex
+ rngsMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+BotanCryptoFactory::~BotanCryptoFactory()
+{
+ // Delete the RNGs
+#ifdef HAVE_PTHREAD_H
+ std::map<pthread_t,RNG*>::iterator it;
+ for (it=rngs.begin(); it != rngs.end(); it++)
+ {
+ delete (BotanRNG*)it->second;
+ }
+#elif _WIN32
+ std::map<DWORD,RNG*>::iterator it;
+ for (it=rngs.begin(); it != rngs.end(); it++)
+ {
+ delete (BotanRNG*)it->second;
+ }
+#endif
+
+ // Delete the mutex
+ MutexFactory::i()->recycleMutex(rngsMutex);
+
+ // Deinitialize the Botan crypto lib
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ if (!wasInitialized)
+ {
+ Botan::LibraryInitializer::deinitialize();
+ }
+#else
+ Botan::LibraryInitializer::deinitialize();
+#endif
+}
+
+// Return the one-and-only instance
+BotanCryptoFactory* BotanCryptoFactory::i()
+{
+ if (!instance.get())
+ {
+ instance.reset(new BotanCryptoFactory());
+ }
+
+ return instance.get();
+}
+
+// This will destroy the one-and-only instance.
+void BotanCryptoFactory::reset()
+{
+ instance.reset();
+}
+
+// Create a concrete instance of a symmetric algorithm
+SymmetricAlgorithm* BotanCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm)
+{
+ switch (algorithm)
+ {
+ case SymAlgo::AES:
+ return new BotanAES();
+ case SymAlgo::DES:
+ case SymAlgo::DES3:
+ return new BotanDES();
+ default:
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%i'", algorithm);
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Create a concrete instance of an asymmetric algorithm
+AsymmetricAlgorithm* BotanCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm)
+{
+ switch (algorithm)
+ {
+ case AsymAlgo::RSA:
+ return new BotanRSA();
+ case AsymAlgo::DSA:
+ return new BotanDSA();
+ case AsymAlgo::DH:
+ return new BotanDH();
+#ifdef WITH_ECC
+ case AsymAlgo::ECDH:
+ return new BotanECDH();
+ case AsymAlgo::ECDSA:
+ return new BotanECDSA();
+#endif
+#ifdef WITH_GOST
+ case AsymAlgo::GOST:
+ return new BotanGOST();
+#endif
+ default:
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%i'", algorithm);
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Create a concrete instance of a hash algorithm
+HashAlgorithm* BotanCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm)
+{
+ switch (algorithm)
+ {
+ case HashAlgo::MD5:
+ return new BotanMD5();
+ case HashAlgo::SHA1:
+ return new BotanSHA1();
+ case HashAlgo::SHA224:
+ return new BotanSHA224();
+ case HashAlgo::SHA256:
+ return new BotanSHA256();
+ case HashAlgo::SHA384:
+ return new BotanSHA384();
+ case HashAlgo::SHA512:
+ return new BotanSHA512();
+#ifdef WITH_GOST
+ case HashAlgo::GOST:
+ return new BotanGOSTR3411();
+#endif
+ default:
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%i'", algorithm);
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Create a concrete instance of a MAC algorithm
+MacAlgorithm* BotanCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm)
+{
+ switch (algorithm)
+ {
+ case MacAlgo::HMAC_MD5:
+ return new BotanHMACMD5();
+ case MacAlgo::HMAC_SHA1:
+ return new BotanHMACSHA1();
+ case MacAlgo::HMAC_SHA224:
+ return new BotanHMACSHA224();
+ case MacAlgo::HMAC_SHA256:
+ return new BotanHMACSHA256();
+ case MacAlgo::HMAC_SHA384:
+ return new BotanHMACSHA384();
+ case MacAlgo::HMAC_SHA512:
+ return new BotanHMACSHA512();
+#ifdef WITH_GOST
+ case MacAlgo::HMAC_GOST:
+ return new BotanHMACGOSTR3411();
+#endif
+ case MacAlgo::CMAC_DES:
+ return new BotanCMACDES();
+ case MacAlgo::CMAC_AES:
+ return new BotanCMACAES();
+ default:
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%i'", algorithm);
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Get the global RNG (may be an unique RNG per thread)
+RNG* BotanCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */)
+{
+ if (name == RNGImpl::Default)
+ {
+ RNG *threadRNG = NULL;
+
+ // Lock access to the map
+ MutexLocker lock(rngsMutex);
+
+#ifdef HAVE_PTHREAD_H
+ // Get thread ID
+ pthread_t threadID = pthread_self();
+
+ // Find the RNG
+ std::map<pthread_t,RNG*>::iterator findIt;
+ findIt=rngs.find(threadID);
+ if (findIt != rngs.end())
+ {
+ return findIt->second;
+ }
+
+ threadRNG = new BotanRNG();
+ rngs[threadID] = threadRNG;
+#elif _WIN32
+ // Get thread ID
+ DWORD threadID = GetCurrentThreadId();
+
+ // Find the RNG
+ std::map<DWORD,RNG*>::iterator findIt;
+ findIt=rngs.find(threadID);
+ if (findIt != rngs.end())
+ {
+ return findIt->second;
+ }
+
+ threadRNG = new BotanRNG();
+ rngs[threadID] = threadRNG;
+#else
+#error "There are no thread-specific data implementations for your operating system yet"
+#endif
+ return threadRNG;
+ }
+ else
+ {
+ // No RNG implementation is available
+ ERROR_MSG("Unknown RNG '%i'", name);
+
+ return NULL;
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.h b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.h
new file mode 100644
index 0000000..df7556d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanCryptoFactory.h
+
+ This is a Botan based cryptographic algorithm factory
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANCRYPTOFACTORY_H
+#define _SOFTHSM_V2_BOTANCRYPTOFACTORY_H
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#include "config.h"
+#include "CryptoFactory.h"
+#include "SymmetricAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include "MacAlgorithm.h"
+#include "RNG.h"
+#include "MutexFactory.h"
+#include <memory>
+#include <map>
+#include <botan/version.h>
+
+class BotanCryptoFactory : public CryptoFactory
+{
+public:
+ // Return the one-and-only instance
+ static BotanCryptoFactory* i();
+
+ // This will destroy the one-and-only instance.
+ static void reset();
+
+ // Create a concrete instance of a symmetric algorithm
+ SymmetricAlgorithm* getSymmetricAlgorithm(SymAlgo::Type algorithm);
+
+ // Create a concrete instance of an asymmetric algorithm
+ AsymmetricAlgorithm* getAsymmetricAlgorithm(AsymAlgo::Type algorithm);
+
+ // Create a concrete instance of a hash algorithm
+ HashAlgorithm* getHashAlgorithm(HashAlgo::Type algorithm);
+
+ // Create a concrete instance of a MAC algorithm
+ MacAlgorithm* getMacAlgorithm(MacAlgo::Type algorithm);
+
+ // Get the global RNG (may be an unique RNG per thread)
+ RNG* getRNG(RNGImpl::Type name = RNGImpl::Default);
+
+ // Destructor
+ ~BotanCryptoFactory();
+
+private:
+ // Constructor
+ BotanCryptoFactory();
+
+ // The one-and-only instance
+#ifdef HAVE_CXX11
+ static std::unique_ptr<BotanCryptoFactory> instance;
+#else
+ static std::auto_ptr<BotanCryptoFactory> instance;
+#endif
+
+ // Thread specific RNG
+#ifdef HAVE_PTHREAD_H
+ std::map<pthread_t, RNG*> rngs;
+#elif _WIN32
+ std::map<DWORD, RNG*> rngs;
+#endif
+ Mutex* rngsMutex;
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ bool wasInitialized;
+#endif
+};
+
+#endif // !_SOFTHSM_V2_BOTANCRYPTOFACTORY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDES.cpp b/SoftHSMv2/src/lib/crypto/BotanDES.cpp
new file mode 100644
index 0000000..393cf4d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDES.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDES.cpp
+
+ Botan (3)DES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanDES.h"
+#include <algorithm>
+#include "odd.h"
+
+bool BotanDES::wrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/)
+{
+ ERROR_MSG("DES does not support key wrapping");
+
+ return false;
+}
+
+bool BotanDES::unwrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/)
+{
+ ERROR_MSG("DES does not support key unwrapping");
+
+ return false;
+}
+
+std::string BotanDES::getCipher() const
+{
+ std::string algo;
+ std::string mode;
+ std::string padding;
+
+ if (currentKey == NULL) return "";
+
+ // Check currentKey bit length; 3DES only supports 56-bit, 112-bit or 168-bit keys
+ switch (currentKey->getBitLen())
+ {
+ case 56:
+ // People shouldn't really be using 56-bit DES keys, generate a warning
+ DEBUG_MSG("CAUTION: use of 56-bit DES keys is not recommended!");
+ algo = "DES";
+ break;
+ case 112:
+ case 168:
+ algo = "TripleDES";
+ break;
+ default:
+ ERROR_MSG("Invalid DES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return "";
+ }
+
+ // Determine the cipher mode
+ switch (currentCipherMode)
+ {
+ case SymMode::CBC:
+ mode = "CBC";
+ break;
+ case SymMode::CFB:
+ mode = "CFB";
+ break;
+ case SymMode::ECB:
+ mode = "ECB";
+ break;
+ case SymMode::OFB:
+ mode = "OFB";
+ break;
+ default:
+ ERROR_MSG("Invalid DES cipher mode %i", currentCipherMode);
+
+ return "";
+ }
+
+ // Check padding mode
+ if (currentCipherMode == SymMode::OFB ||
+ currentCipherMode == SymMode::CFB)
+ {
+ padding = "";
+ }
+ else if (currentPaddingMode)
+ {
+ padding = "/PKCS7";
+ }
+ else
+ {
+ padding = "/NoPadding";
+ }
+
+ return algo + "/" + mode + padding;
+}
+
+bool BotanDES::generateKey(SymmetricKey& key, RNG* rng /* = NULL */)
+{
+ if (rng == NULL)
+ {
+ return false;
+ }
+
+ if (key.getBitLen() == 0)
+ {
+ return false;
+ }
+
+ ByteString keyBits;
+
+ // don't count parity bit
+ if (!rng->generateRandom(keyBits, key.getBitLen()/7))
+ {
+ return false;
+ }
+
+ // fix the odd parity
+ size_t i;
+ for (i = 0; i < keyBits.size(); i++)
+ {
+ keyBits[i] = odd_parity[keyBits[i]];
+ }
+
+
+ return key.setKeyBits(keyBits);
+}
+
+size_t BotanDES::getBlockSize() const
+{
+ // The block size is 64 bits
+ return 64 >> 3;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDES.h b/SoftHSMv2/src/lib/crypto/BotanDES.h
new file mode 100644
index 0000000..4f81fe6
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDES.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDES.h
+
+ Botan (3)DES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDES_H
+#define _SOFTHSM_V2_BOTANDES_H
+
+#include <string>
+#include "config.h"
+#include "BotanSymmetricAlgorithm.h"
+
+class BotanDES : public BotanSymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~BotanDES() { }
+
+ // Wrap/Unwrap keys
+ virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out);
+
+ virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out);
+
+ // Generate key
+ virtual bool generateKey(SymmetricKey& key, RNG* rng = NULL);
+
+ // Return the block size
+ virtual size_t getBlockSize() const;
+
+protected:
+ // Return the right Botan cipher for the operation
+ virtual std::string getCipher() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANDES_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDH.cpp b/SoftHSMv2/src/lib/crypto/BotanDH.cpp
new file mode 100644
index 0000000..5adc239
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDH.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDH.cpp
+
+ Botan Diffie-Hellman asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDH.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "DHParameters.h"
+#include "BotanDHKeyPair.h"
+#include "BotanUtil.h"
+#include <algorithm>
+#include <botan/dl_group.h>
+#include <botan/dh.h>
+#include <botan/pubkey.h>
+#include <botan/version.h>
+
+// Signing functions
+bool BotanDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("DH does not support signing");
+
+ return false;
+}
+
+bool BotanDH::signUpdate(const ByteString& /*dataToSign*/)
+{
+ ERROR_MSG("DH does not support signing");
+
+ return false;
+}
+
+bool BotanDH::signFinal(ByteString& /*signature*/)
+{
+ ERROR_MSG("DH does not support signing");
+
+ return false;
+}
+
+// Verification functions
+bool BotanDH::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("DH does not support verifying");
+
+ return false;
+}
+
+bool BotanDH::verifyUpdate(const ByteString& /*originalData*/)
+{
+ ERROR_MSG("DH does not support verifying");
+
+ return false;
+}
+
+bool BotanDH::verifyFinal(const ByteString& /*signature*/)
+{
+ ERROR_MSG("DH does not support verifying");
+
+ return false;
+}
+
+// Encryption functions
+bool BotanDH::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("DH does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool BotanDH::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("DH does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool BotanDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(DHParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for DH key generation");
+
+ return false;
+ }
+
+ DHParameters* params = (DHParameters*) parameters;
+
+ // Generate the key-pair
+ BotanDH_PrivateKey* dh = NULL;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+
+ // PKCS#3: 2^(l-1) <= x < 2^l
+ Botan::BigInt x;
+ if (params->getXBitLength() > 0)
+ {
+ x.randomize(*rng->getRNG(), params->getXBitLength());
+ }
+
+ dh = new BotanDH_PrivateKey(*rng->getRNG(),
+ Botan::DL_Group(BotanUtil::byteString2bigInt(params->getP()),
+ BotanUtil::byteString2bigInt(params->getG())),
+ x);
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("DH key generation failed with %s", e.what());
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanDHKeyPair* kp = new BotanDHKeyPair();
+
+ ((BotanDHPublicKey*) kp->getPublicKey())->setFromBotan(dh);
+ ((BotanDHPrivateKey*) kp->getPrivateKey())->setFromBotan(dh);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete dh;
+
+ return true;
+}
+
+bool BotanDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
+{
+ // Check parameters
+ if ((ppSymmetricKey == NULL) ||
+ (publicKey == NULL) ||
+ (privateKey == NULL))
+ {
+ return false;
+ }
+
+ // Get keys
+ Botan::DH_PublicKey* pub = ((BotanDHPublicKey*) publicKey)->getBotanKey();
+ BotanDH_PrivateKey* priv = ((BotanDHPrivateKey*) privateKey)->getBotanKey();
+ if (pub == NULL || priv == NULL || priv->impl == NULL)
+ {
+ ERROR_MSG("Failed to get Botan DH keys");
+
+ return false;
+ }
+
+ // Derive the secret
+ Botan::SymmetricKey sk;
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ Botan::PK_Key_Agreement ka(*priv->impl, *rng->getRNG(), "Raw");
+#else
+ Botan::PK_Key_Agreement ka(*priv->impl, "Raw");
+#endif
+ sk = ka.derive_key(0, pub->public_value());
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Botan DH key agreement failed: %s", e.what());
+
+ return false;
+ }
+
+ ByteString secret;
+
+ // We compensate that Botan removes leading zeros
+ int size = ((BotanDHPublicKey*) publicKey)->getOutputLength();
+ int keySize = sk.length();
+ secret.wipe(size);
+ memcpy(&secret[0] + size - keySize, sk.begin(), keySize);
+
+ *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
+ if (*ppSymmetricKey == NULL)
+ {
+ ERROR_MSG("Can't create DH secret");
+
+ return false;
+ }
+ if (!(*ppSymmetricKey)->setKeyBits(secret))
+ {
+ delete *ppSymmetricKey;
+ *ppSymmetricKey = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+unsigned long BotanDH::getMinKeySize()
+{
+ return 512;
+}
+
+unsigned long BotanDH::getMaxKeySize()
+{
+ return 4096;
+}
+
+bool BotanDH::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/)
+{
+ if ((ppParams == NULL) || (parameters == NULL))
+ {
+ return false;
+ }
+
+ size_t bitLen = (size_t) parameters;
+
+ if (bitLen < getMinKeySize() || bitLen > getMaxKeySize())
+ {
+ ERROR_MSG("This DH key size is not supported");
+
+ return false;
+ }
+
+ Botan::DL_Group* group = NULL;
+ try
+ {
+ BotanRNG* brng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ group = new Botan::DL_Group(*brng->getRNG(), Botan::DL_Group::Strong, bitLen);
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Failed to generate %d bit DH parameters: %s", bitLen, e.what());
+
+ return false;
+ }
+
+ // Store the DH parameters
+ DHParameters* params = new DHParameters();
+
+ ByteString p = BotanUtil::bigInt2ByteString(group->get_p());
+ params->setP(p);
+ ByteString g = BotanUtil::bigInt2ByteString(group->get_g());
+ params->setG(g);
+
+ *ppParams = params;
+
+ delete group;
+
+ return true;
+}
+
+bool BotanDH::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanDHKeyPair* kp = new BotanDHKeyPair();
+
+ bool rv = true;
+
+ if (!((DHPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((DHPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanDH::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanDHPublicKey* pub = new BotanDHPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanDH::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanDHPrivateKey* priv = new BotanDHPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanDH::newPublicKey()
+{
+ return (PublicKey*) new BotanDHPublicKey();
+}
+
+PrivateKey* BotanDH::newPrivateKey()
+{
+ return (PrivateKey*) new BotanDHPrivateKey();
+}
+
+AsymmetricParameters* BotanDH::newParameters()
+{
+ return (AsymmetricParameters*) new DHParameters();
+}
+
+bool BotanDH::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ DHParameters* params = new DHParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDH.h b/SoftHSMv2/src/lib/crypto/BotanDH.h
new file mode 100644
index 0000000..af2ac59
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDH.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDH.h
+
+ Botan Diffie-Hellman asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDH_H
+#define _SOFTHSM_V2_BOTANDH_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanDH : public AsymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~BotanDH() { }
+
+ // Signing functions
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL);
+ virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_BOTANDH_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.cpp
new file mode 100644
index 0000000..10c2131
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDHKeyPair.cpp
+
+ Botan Diffie-Hellman key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDHKeyPair.h"
+
+// Set the public key
+void BotanDHKeyPair::setPublicKey(BotanDHPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanDHKeyPair::setPrivateKey(BotanDHPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanDHKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanDHKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanDHKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanDHKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.h
new file mode 100644
index 0000000..629c6fd
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDHKeyPair.h
+
+ Botan DiffieHellman key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDHKEYPAIR_H
+#define _SOFTHSM_V2_BOTANDHKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "BotanDHPublicKey.h"
+#include "BotanDHPrivateKey.h"
+
+class BotanDHKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanDHPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanDHPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanDHPublicKey pubKey;
+
+ // The private key
+ BotanDHPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_BOTANDHKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.cpp
new file mode 100644
index 0000000..cb7a530
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.cpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDHPrivateKey.cpp
+
+ Botan Diffie-Hellman private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDHPrivateKey.h"
+#include "BotanCryptoFactory.h"
+#include "BotanRNG.h"
+#include "BotanUtil.h"
+#include <string.h>
+#include <botan/pkcs8.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+#include <botan/version.h>
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+std::vector<Botan::byte> BotanDH_PrivateKey::public_value() const
+{
+ return impl->public_value();
+}
+#else
+Botan::MemoryVector<Botan::byte> BotanDH_PrivateKey::public_value() const
+{
+ return impl->public_value();
+}
+#endif
+
+// Redefine of DH_PrivateKey constructor with the correct format
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+BotanDH_PrivateKey::BotanDH_PrivateKey(
+ const Botan::AlgorithmIdentifier& alg_id,
+ const Botan::secure_vector<Botan::byte>& key_bits,
+ Botan::RandomNumberGenerator& rng) :
+ Botan::DL_Scheme_PrivateKey(alg_id, key_bits, Botan::DL_Group::PKCS3_DH_PARAMETERS)
+{
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,27)
+ impl = new Botan::DH_PrivateKey(rng, m_group, m_x);
+#else
+ impl = new Botan::DH_PrivateKey(rng, group, x);
+#endif
+}
+#else
+BotanDH_PrivateKey::BotanDH_PrivateKey(
+ const Botan::AlgorithmIdentifier& alg_id,
+ const Botan::MemoryRegion<Botan::byte>& key_bits,
+ Botan::RandomNumberGenerator& rng) :
+ Botan::DL_Scheme_PrivateKey(alg_id, key_bits, Botan::DL_Group::PKCS3_DH_PARAMETERS)
+{
+ impl = new Botan::DH_PrivateKey(rng, group, x);
+}
+#endif
+
+BotanDH_PrivateKey::BotanDH_PrivateKey(Botan::RandomNumberGenerator& rng,
+ const Botan::DL_Group& grp,
+ const Botan::BigInt& x_arg)
+{
+ impl = new Botan::DH_PrivateKey(rng, grp, x_arg);
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,27)
+ m_group = grp;
+ m_x = x_arg;
+ m_y = impl->get_y();
+#else
+ group = grp;
+ x = x_arg;
+ y = impl->get_y();
+#endif
+}
+
+BotanDH_PrivateKey::~BotanDH_PrivateKey()
+{
+ delete impl;
+}
+
+// Constructors
+BotanDHPrivateKey::BotanDHPrivateKey()
+{
+ dh = NULL;
+}
+
+BotanDHPrivateKey::BotanDHPrivateKey(const BotanDH_PrivateKey* inDH)
+{
+ dh = NULL;
+
+ setFromBotan(inDH);
+}
+
+// Destructor
+BotanDHPrivateKey::~BotanDHPrivateKey()
+{
+ delete dh;
+}
+
+// The type
+/*static*/ const char* BotanDHPrivateKey::type = "Botan DH Private Key";
+
+// Set from Botan representation
+void BotanDHPrivateKey::setFromBotan(const BotanDH_PrivateKey* inDH)
+{
+ ByteString inP = BotanUtil::bigInt2ByteString(inDH->impl->group_p());
+ setP(inP);
+ ByteString inG = BotanUtil::bigInt2ByteString(inDH->impl->group_g());
+ setG(inG);
+ ByteString inX = BotanUtil::bigInt2ByteString(inDH->impl->get_x());
+ setX(inX);
+}
+
+// Check if the key is of the given type
+bool BotanDHPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the DH private key components
+void BotanDHPrivateKey::setX(const ByteString& inX)
+{
+ DHPrivateKey::setX(inX);
+
+ if (dh)
+ {
+ delete dh;
+ dh = NULL;
+ }
+}
+
+// Setters for the DH public key components
+void BotanDHPrivateKey::setP(const ByteString& inP)
+{
+ DHPrivateKey::setP(inP);
+
+ if (dh)
+ {
+ delete dh;
+ dh = NULL;
+ }
+}
+
+void BotanDHPrivateKey::setG(const ByteString& inG)
+{
+ DHPrivateKey::setG(inG);
+
+ if (dh)
+ {
+ delete dh;
+ dh = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString BotanDHPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ createBotanKey();
+ if (dh == NULL) return der;
+ // Force PKCS3_DH_PARAMETERS for p, g and no q.
+ const size_t PKCS8_VERSION = 0;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+ const std::vector<Botan::byte> parameters = dh->impl->get_domain().DER_encode(Botan::DL_Group::PKCS3_DH_PARAMETERS);
+ const Botan::AlgorithmIdentifier alg_id(dh->impl->get_oid(), parameters);
+ const Botan::secure_vector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(dh->impl->private_key_bits(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ const std::vector<Botan::byte> parameters = dh->impl->get_domain().DER_encode(Botan::DL_Group::PKCS3_DH_PARAMETERS);
+ const Botan::AlgorithmIdentifier alg_id(dh->impl->get_oid(), parameters);
+ const Botan::secure_vector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(dh->impl->pkcs8_private_key(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#else
+ const Botan::MemoryVector<Botan::byte> parameters = dh->impl->get_domain().DER_encode(Botan::DL_Group::PKCS3_DH_PARAMETERS);
+ const Botan::AlgorithmIdentifier alg_id(dh->impl->get_oid(), parameters);
+ const Botan::SecureVector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(dh->impl->pkcs8_private_key(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#endif
+ der.resize(ber.size());
+ memcpy(&der[0], &ber[0], ber.size());
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool BotanDHPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
+ if (source.end_of_data()) return false;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> keydata;
+#else
+ Botan::SecureVector<Botan::byte> keydata;
+#endif
+ Botan::AlgorithmIdentifier alg_id;
+ BotanDH_PrivateKey* key = NULL;
+ try
+ {
+ Botan::BER_Decoder(source)
+ .start_cons(Botan::SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
+ .decode(alg_id)
+ .decode(keydata, Botan::OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+ if (keydata.empty())
+ throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
+ if (Botan::OIDS::lookup(alg_id.oid).compare("DH"))
+ {
+ ERROR_MSG("Decoded private key not DH");
+
+ return false;
+ }
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ key = new BotanDH_PrivateKey(alg_id, keydata, *rng->getRNG());
+ if (key == NULL) return false;
+
+ setFromBotan(key);
+
+ delete key;
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Decode failed on %s", e.what());
+
+ return false;
+ }
+
+ return true;
+}
+
+// Retrieve the Botan representation of the key
+BotanDH_PrivateKey* BotanDHPrivateKey::getBotanKey()
+{
+ if (!dh)
+ {
+ createBotanKey();
+ }
+
+ return dh;
+}
+
+// Create the Botan representation of the key
+void BotanDHPrivateKey::createBotanKey()
+{
+ // y is not needed
+ if (p.size() != 0 &&
+ g.size() != 0 &&
+ x.size() != 0)
+ {
+ if (dh)
+ {
+ delete dh;
+ dh = NULL;
+ }
+
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ dh = new BotanDH_PrivateKey(*rng->getRNG(),
+ Botan::DL_Group(BotanUtil::byteString2bigInt(p),
+ BotanUtil::byteString2bigInt(g)),
+ BotanUtil::byteString2bigInt(x));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.h
new file mode 100644
index 0000000..5991c21
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDHPrivateKey.h
+
+ Botan Diffie-Hellman private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDHPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANDHPRIVATEKEY_H
+
+#include "config.h"
+#include "DHPrivateKey.h"
+#include <botan/dh.h>
+#include <botan/version.h>
+
+// Derived from the DH_PrivateKey class
+class BotanDH_PrivateKey : public Botan::DH_PublicKey,
+ public virtual Botan::DL_Scheme_PrivateKey
+{
+public:
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> public_value() const;
+#else
+ Botan::MemoryVector<Botan::byte> public_value() const;
+#endif
+
+ // Constructors
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ BotanDH_PrivateKey(const Botan::AlgorithmIdentifier& alg_id,
+ const Botan::secure_vector<Botan::byte>& key_bits,
+ Botan::RandomNumberGenerator& rng);
+#else
+ BotanDH_PrivateKey(const Botan::AlgorithmIdentifier& alg_id,
+ const Botan::MemoryRegion<Botan::byte>& key_bits,
+ Botan::RandomNumberGenerator& rng);
+#endif
+
+ BotanDH_PrivateKey(Botan::RandomNumberGenerator& rng,
+ const Botan::DL_Group& grp,
+ const Botan::BigInt& x = 0);
+
+ ~BotanDH_PrivateKey();
+
+ Botan::DH_PrivateKey* impl;
+};
+
+class BotanDHPrivateKey : public DHPrivateKey
+{
+public:
+ // Constructors
+ BotanDHPrivateKey();
+
+ BotanDHPrivateKey(const BotanDH_PrivateKey* inDH);
+
+ // Destructor
+ virtual ~BotanDHPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the DH private key components
+ virtual void setX(const ByteString& inX);
+
+ // Setters for the DH public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setG(const ByteString& inG);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const BotanDH_PrivateKey* inDH);
+
+ // Retrieve the Botan representation of the key
+ BotanDH_PrivateKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ BotanDH_PrivateKey* dh;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANDHPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.cpp
new file mode 100644
index 0000000..16c4b12
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDHPublicKey.cpp
+
+ Botan Diffie-Hellman public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDHPublicKey.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanDHPublicKey::BotanDHPublicKey()
+{
+ dh = NULL;
+}
+
+BotanDHPublicKey::BotanDHPublicKey(const Botan::DH_PublicKey* inDH)
+{
+ dh = NULL;
+
+ setFromBotan(inDH);
+}
+
+// Destructor
+BotanDHPublicKey::~BotanDHPublicKey()
+{
+ delete dh;
+}
+
+// The type
+/*static*/ const char* BotanDHPublicKey::type = "Botan DH Public Key";
+
+// Set from Botan representation
+void BotanDHPublicKey::setFromBotan(const Botan::DH_PublicKey* inDH)
+{
+ ByteString inP = BotanUtil::bigInt2ByteString(inDH->group_p());
+ setP(inP);
+ ByteString inG = BotanUtil::bigInt2ByteString(inDH->group_g());
+ setG(inG);
+ ByteString inY = BotanUtil::bigInt2ByteString(inDH->get_y());
+ setY(inY);
+}
+
+// Check if the key is of the given type
+bool BotanDHPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the DH public key components
+void BotanDHPublicKey::setP(const ByteString& inP)
+{
+ DHPublicKey::setP(inP);
+
+ if (dh)
+ {
+ delete dh;
+ dh = NULL;
+ }
+}
+
+void BotanDHPublicKey::setG(const ByteString& inG)
+{
+ DHPublicKey::setG(inG);
+
+ if (dh)
+ {
+ delete dh;
+ dh = NULL;
+ }
+}
+
+void BotanDHPublicKey::setY(const ByteString& inY)
+{
+ DHPublicKey::setY(inY);
+
+ if (dh)
+ {
+ delete dh;
+ dh = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::DH_PublicKey* BotanDHPublicKey::getBotanKey()
+{
+ if (!dh)
+ {
+ createBotanKey();
+ }
+
+ return dh;
+}
+
+// Create the Botan representation of the key
+void BotanDHPublicKey::createBotanKey()
+{
+ // We actually do not need to check q, since it can be set zero
+ if (p.size() != 0 && y.size() != 0)
+ {
+ if (dh)
+ {
+ delete dh;
+ dh = NULL;
+ }
+
+ try
+ {
+ dh = new Botan::DH_PublicKey(Botan::DL_Group(BotanUtil::byteString2bigInt(p),
+ BotanUtil::byteString2bigInt(g)),
+ BotanUtil::byteString2bigInt(y));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.h
new file mode 100644
index 0000000..66e90c2
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDHPublicKey.h
+
+ Botan Diffie-Hellman public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDHPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANDHPUBLICKEY_H
+
+#include "config.h"
+#include "DHPublicKey.h"
+#include <botan/dh.h>
+
+class BotanDHPublicKey : public DHPublicKey
+{
+public:
+ // Constructors
+ BotanDHPublicKey();
+
+ BotanDHPublicKey(const Botan::DH_PublicKey* inDH);
+
+ // Destructor
+ virtual ~BotanDHPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the DH public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setG(const ByteString& inG);
+ virtual void setY(const ByteString& inY);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::DH_PublicKey* inDH);
+
+ // Retrieve the Botan representation of the key
+ Botan::DH_PublicKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::DH_PublicKey* dh;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANDHPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDSA.cpp b/SoftHSMv2/src/lib/crypto/BotanDSA.cpp
new file mode 100644
index 0000000..ab3aa01
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDSA.cpp
@@ -0,0 +1,760 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSA.cpp
+
+ Botan DSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDSA.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "DSAParameters.h"
+#include "BotanDSAKeyPair.h"
+#include "BotanUtil.h"
+#include <algorithm>
+#include <botan/dl_group.h>
+#include <botan/dsa.h>
+#include <botan/version.h>
+#include <iostream>
+
+// Constructor
+BotanDSA::BotanDSA()
+{
+ signer = NULL;
+ verifier = NULL;
+}
+
+// Destructor
+BotanDSA::~BotanDSA()
+{
+ delete signer;
+ delete verifier;
+}
+
+// Signing functions
+bool BotanDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ std::string emsa;
+
+ if (mechanism == AsymMech::DSA)
+ {
+ emsa = "Raw";
+ }
+ else
+ {
+ // Call default implementation
+ return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanDSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) privateKey;
+ Botan::DSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ return false;
+ }
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
+#else
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+#endif
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ return false;
+ }
+
+ // Perform the signature operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> signResult;
+#else
+ Botan::SecureVector<Botan::byte> signResult;
+#endif
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&signature[0], signResult.data(), signResult.size());
+#else
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+#endif
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+bool BotanDSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanDSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ std::string emsa;
+
+ switch (mechanism)
+ {
+ case AsymMech::DSA_SHA1:
+ emsa = "EMSA1(SHA-160)";
+ break;
+ case AsymMech::DSA_SHA224:
+ emsa = "EMSA1(SHA-224)";
+ break;
+ case AsymMech::DSA_SHA256:
+ emsa = "EMSA1(SHA-256)";
+ break;
+ case AsymMech::DSA_SHA384:
+ emsa = "EMSA1(SHA-384)";
+ break;
+ case AsymMech::DSA_SHA512:
+ emsa = "EMSA1(SHA-512)";
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) currentPrivateKey;
+ Botan::DSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
+#else
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+#endif
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanDSA::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ try
+ {
+ if (dataToSign.size() != 0)
+ {
+ signer->update(dataToSign.const_byte_str(),
+ dataToSign.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanDSA::signFinal(ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the signature operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> signResult;
+#else
+ Botan::SecureVector<Botan::byte> signResult;
+#endif
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->signature(*rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&signature[0], signResult.data(), signResult.size());
+#else
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+#endif
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool BotanDSA::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ std::string emsa;
+
+ if (mechanism == AsymMech::DSA)
+ {
+ emsa = "Raw";
+ }
+ else
+ {
+ // Call the generic function
+ return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen);
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanDSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanDSAPublicKey* pk = (BotanDSAPublicKey*) publicKey;
+ Botan::DSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->verify_message(originalData.const_byte_str(),
+ originalData.size(),
+ signature.const_byte_str(),
+ signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+bool BotanDSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanDSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ std::string emsa;
+
+ switch (mechanism)
+ {
+ case AsymMech::DSA_SHA1:
+ emsa = "EMSA1(SHA-160)";
+ break;
+ case AsymMech::DSA_SHA224:
+ emsa = "EMSA1(SHA-224)";
+ break;
+ case AsymMech::DSA_SHA256:
+ emsa = "EMSA1(SHA-256)";
+ break;
+ case AsymMech::DSA_SHA384:
+ emsa = "EMSA1(SHA-384)";
+ break;
+ case AsymMech::DSA_SHA512:
+ emsa = "EMSA1(SHA-512)";
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ BotanDSAPublicKey* pk = (BotanDSAPublicKey*) currentPublicKey;
+ Botan::DSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanDSA::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ try
+ {
+ if (originalData.size() != 0)
+ {
+ verifier->update(originalData.const_byte_str(),
+ originalData.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanDSA::verifyFinal(const ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->check_signature(signature.const_byte_str(), signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+// Encryption functions
+bool BotanDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("DSA does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool BotanDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("DSA does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool BotanDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(DSAParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for DSA key generation");
+
+ return false;
+ }
+
+ DSAParameters* params = (DSAParameters*) parameters;
+
+ // Generate the key-pair
+ Botan::DSA_PrivateKey* dsa = NULL;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ dsa = new Botan::DSA_PrivateKey(*rng->getRNG(),
+ Botan::DL_Group(BotanUtil::byteString2bigInt(params->getP()),
+ BotanUtil::byteString2bigInt(params->getQ()),
+ BotanUtil::byteString2bigInt(params->getG())));
+ }
+ catch (...)
+ {
+ ERROR_MSG("DSA key generation failed");
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanDSAKeyPair* kp = new BotanDSAKeyPair();
+
+ ((BotanDSAPublicKey*) kp->getPublicKey())->setFromBotan(dsa);
+ ((BotanDSAPrivateKey*) kp->getPrivateKey())->setFromBotan(dsa);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete dsa;
+
+ return true;
+}
+
+unsigned long BotanDSA::getMinKeySize()
+{
+ return 512;
+}
+
+unsigned long BotanDSA::getMaxKeySize()
+{
+ // Taken from OpenSSL
+ return 10000;
+}
+
+bool BotanDSA::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/)
+{
+ if ((ppParams == NULL) || (parameters == NULL))
+ {
+ return false;
+ }
+
+ size_t bitLen = (size_t) parameters;
+
+ if (bitLen < getMinKeySize() || bitLen > getMaxKeySize())
+ {
+ ERROR_MSG("This DSA key size is not supported");
+
+ return false;
+ }
+
+ Botan::DL_Group* group = NULL;
+ // Taken from OpenSSL
+ size_t qLen = bitLen >= 2048 ? 256 : 160;
+ try
+ {
+ BotanRNG* brng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ group = new Botan::DL_Group(*brng->getRNG(), Botan::DL_Group::Prime_Subgroup, bitLen, qLen);
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Failed to generate %d bit DSA parameters: %s", bitLen, e.what());
+
+ return false;
+ }
+
+ // Store the DSA parameters
+ DSAParameters* params = new DSAParameters();
+
+ ByteString p = BotanUtil::bigInt2ByteString(group->get_p());
+ params->setP(p);
+ ByteString q = BotanUtil::bigInt2ByteString(group->get_q());
+ params->setQ(q);
+ ByteString g = BotanUtil::bigInt2ByteString(group->get_g());
+ params->setG(g);
+
+ *ppParams = params;
+
+ delete group;
+
+ return true;
+}
+
+bool BotanDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanDSAKeyPair* kp = new BotanDSAKeyPair();
+
+ bool rv = true;
+
+ if (!((DSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((DSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanDSAPublicKey* pub = new BotanDSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanDSAPrivateKey* priv = new BotanDSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanDSA::newPublicKey()
+{
+ return (PublicKey*) new BotanDSAPublicKey();
+}
+
+PrivateKey* BotanDSA::newPrivateKey()
+{
+ return (PrivateKey*) new BotanDSAPrivateKey();
+}
+
+AsymmetricParameters* BotanDSA::newParameters()
+{
+ return (AsymmetricParameters*) new DSAParameters();
+}
+
+bool BotanDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ DSAParameters* params = new DSAParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDSA.h b/SoftHSMv2/src/lib/crypto/BotanDSA.h
new file mode 100644
index 0000000..dd10016
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDSA.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSA.h
+
+ Botan DSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDSA_H
+#define _SOFTHSM_V2_BOTANDSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanDSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanDSA();
+
+ // Destructor
+ virtual ~BotanDSA();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ Botan::PK_Signer* signer;
+ Botan::PK_Verifier* verifier;
+};
+
+#endif // !_SOFTHSM_V2_BOTANDSA_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.cpp
new file mode 100644
index 0000000..9d98125
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAKeyPair.cpp
+
+ Botan DSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDSAKeyPair.h"
+
+// Set the public key
+void BotanDSAKeyPair::setPublicKey(BotanDSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanDSAKeyPair::setPrivateKey(BotanDSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanDSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanDSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanDSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanDSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.h
new file mode 100644
index 0000000..beb07e1
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAKeyPair.h
+
+ Botan DSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDSAKEYPAIR_H
+#define _SOFTHSM_V2_BOTANDSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "BotanDSAPublicKey.h"
+#include "BotanDSAPrivateKey.h"
+
+class BotanDSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanDSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanDSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanDSAPublicKey pubKey;
+
+ // The private key
+ BotanDSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_BOTANDSAKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.cpp
new file mode 100644
index 0000000..a7f1c9b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAPrivateKey.cpp
+
+ Botan DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDSAPrivateKey.h"
+#include "BotanCryptoFactory.h"
+#include "BotanRNG.h"
+#include "BotanUtil.h"
+#include <string.h>
+#include <botan/pkcs8.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+#include <botan/version.h>
+
+// Constructors
+BotanDSAPrivateKey::BotanDSAPrivateKey()
+{
+ dsa = NULL;
+}
+
+BotanDSAPrivateKey::BotanDSAPrivateKey(const Botan::DSA_PrivateKey* inDSA)
+{
+ dsa = NULL;
+
+ setFromBotan(inDSA);
+}
+
+// Destructor
+BotanDSAPrivateKey::~BotanDSAPrivateKey()
+{
+ delete dsa;
+}
+
+// The type
+/*static*/ const char* BotanDSAPrivateKey::type = "Botan DSA Private Key";
+
+// Set from Botan representation
+void BotanDSAPrivateKey::setFromBotan(const Botan::DSA_PrivateKey* inDSA)
+{
+ ByteString inP = BotanUtil::bigInt2ByteString(inDSA->group_p());
+ setP(inP);
+ ByteString inQ = BotanUtil::bigInt2ByteString(inDSA->group_q());
+ setQ(inQ);
+ ByteString inG = BotanUtil::bigInt2ByteString(inDSA->group_g());
+ setG(inG);
+ ByteString inX = BotanUtil::bigInt2ByteString(inDSA->get_x());
+ setX(inX);
+}
+
+// Check if the key is of the given type
+bool BotanDSAPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the DSA private key components
+void BotanDSAPrivateKey::setX(const ByteString& inX)
+{
+ DSAPrivateKey::setX(inX);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+
+// Setters for the DSA domain parameters
+void BotanDSAPrivateKey::setP(const ByteString& inP)
+{
+ DSAPrivateKey::setP(inP);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPrivateKey::setQ(const ByteString& inQ)
+{
+ DSAPrivateKey::setQ(inQ);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPrivateKey::setG(const ByteString& inG)
+{
+ DSAPrivateKey::setG(inG);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString BotanDSAPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ createBotanKey();
+ if (dsa == NULL) return der;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ const Botan::secure_vector<Botan::byte> ber = Botan::PKCS8::BER_encode(*dsa);
+#else
+ const Botan::SecureVector<Botan::byte> ber = Botan::PKCS8::BER_encode(*dsa);
+#endif
+ der.resize(ber.size());
+ memcpy(&der[0], &ber[0], ber.size());
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool BotanDSAPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
+ if (source.end_of_data()) return false;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> keydata;
+#else
+ Botan::SecureVector<Botan::byte> keydata;
+#endif
+ Botan::AlgorithmIdentifier alg_id;
+ Botan::DSA_PrivateKey* key = NULL;
+ try
+ {
+
+ Botan::BER_Decoder(source)
+ .start_cons(Botan::SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
+ .decode(alg_id)
+ .decode(keydata, Botan::OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+ if (keydata.empty())
+ throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
+ if (Botan::OIDS::lookup(alg_id.oid).compare("DSA"))
+ {
+ ERROR_MSG("Decoded private key not DSA");
+
+ return false;
+ }
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34)
+ key = new Botan::DSA_PrivateKey(alg_id, keydata);
+#else
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ key = new Botan::DSA_PrivateKey(alg_id, keydata, *rng->getRNG());
+#endif
+ if (key == NULL) return false;
+
+ setFromBotan(key);
+
+ delete key;
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Decode failed on %s", e.what());
+
+ return false;
+ }
+
+ return true;
+}
+
+// Retrieve the Botan representation of the key
+Botan::DSA_PrivateKey* BotanDSAPrivateKey::getBotanKey()
+{
+ if (!dsa)
+ {
+ createBotanKey();
+ }
+
+ return dsa;
+}
+
+// Create the Botan representation of the key
+void BotanDSAPrivateKey::createBotanKey()
+{
+ // y is not needed
+ // Todo: Either q or x is needed. Both is not needed
+ if (p.size() != 0 &&
+ q.size() != 0 &&
+ g.size() != 0 &&
+ x.size() != 0)
+ {
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ dsa = new Botan::DSA_PrivateKey(*rng->getRNG(),
+ Botan::DL_Group(BotanUtil::byteString2bigInt(p),
+ BotanUtil::byteString2bigInt(q),
+ BotanUtil::byteString2bigInt(g)),
+ BotanUtil::byteString2bigInt(x));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan private key");
+ }
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.h
new file mode 100644
index 0000000..5594967
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAPrivateKey.h
+
+ Botan DSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDSAPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANDSAPRIVATEKEY_H
+
+#include "config.h"
+#include "DSAPrivateKey.h"
+#include <botan/dsa.h>
+
+class BotanDSAPrivateKey : public DSAPrivateKey
+{
+public:
+ // Constructors
+ BotanDSAPrivateKey();
+
+ BotanDSAPrivateKey(const Botan::DSA_PrivateKey* inDSA);
+
+ // Destructor
+ virtual ~BotanDSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the DSA private key components
+ virtual void setX(const ByteString& inX);
+
+ // Setters for the DSA domain parameters
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setG(const ByteString& inG);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::DSA_PrivateKey* inDSA);
+
+ // Retrieve the Botan representation of the key
+ Botan::DSA_PrivateKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::DSA_PrivateKey* dsa;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANDSAPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.cpp
new file mode 100644
index 0000000..a1593d6
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAPublicKey.cpp
+
+ Botan DSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanDSAPublicKey.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanDSAPublicKey::BotanDSAPublicKey()
+{
+ dsa = NULL;
+}
+
+BotanDSAPublicKey::BotanDSAPublicKey(const Botan::DSA_PublicKey* inDSA)
+{
+ dsa = NULL;
+
+ setFromBotan(inDSA);
+}
+
+// Destructor
+BotanDSAPublicKey::~BotanDSAPublicKey()
+{
+ delete dsa;
+}
+
+// The type
+/*static*/ const char* BotanDSAPublicKey::type = "Botan DSA Public Key";
+
+// Set from Botan representation
+void BotanDSAPublicKey::setFromBotan(const Botan::DSA_PublicKey* inDSA)
+{
+ ByteString inP = BotanUtil::bigInt2ByteString(inDSA->group_p());
+ setP(inP);
+ ByteString inQ = BotanUtil::bigInt2ByteString(inDSA->group_q());
+ setQ(inQ);
+ ByteString inG = BotanUtil::bigInt2ByteString(inDSA->group_g());
+ setG(inG);
+ ByteString inY = BotanUtil::bigInt2ByteString(inDSA->get_y());
+ setY(inY);
+}
+
+// Check if the key is of the given type
+bool BotanDSAPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the DSA public key components
+void BotanDSAPublicKey::setP(const ByteString& inP)
+{
+ DSAPublicKey::setP(inP);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPublicKey::setQ(const ByteString& inQ)
+{
+ DSAPublicKey::setQ(inQ);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPublicKey::setG(const ByteString& inG)
+{
+ DSAPublicKey::setG(inG);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+void BotanDSAPublicKey::setY(const ByteString& inY)
+{
+ DSAPublicKey::setY(inY);
+
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::DSA_PublicKey* BotanDSAPublicKey::getBotanKey()
+{
+ if (!dsa)
+ {
+ createBotanKey();
+ }
+
+ return dsa;
+}
+
+// Create the Botan representation of the key
+void BotanDSAPublicKey::createBotanKey()
+{
+ // We actually do not need to check q, since it can be set zero
+ if (p.size() != 0 &&
+ g.size() != 0 &&
+ y.size() != 0)
+ {
+ if (dsa)
+ {
+ delete dsa;
+ dsa = NULL;
+ }
+
+ try
+ {
+ dsa = new Botan::DSA_PublicKey(Botan::DL_Group(BotanUtil::byteString2bigInt(p),
+ BotanUtil::byteString2bigInt(q),
+ BotanUtil::byteString2bigInt(g)),
+ BotanUtil::byteString2bigInt(y));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.h
new file mode 100644
index 0000000..e4d683d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanDSAPublicKey.h
+
+ Botan DSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANDSAPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANDSAPUBLICKEY_H
+
+#include "config.h"
+#include "DSAPublicKey.h"
+#include <botan/dsa.h>
+
+class BotanDSAPublicKey : public DSAPublicKey
+{
+public:
+ // Constructors
+ BotanDSAPublicKey();
+
+ BotanDSAPublicKey(const Botan::DSA_PublicKey* inDSA);
+
+ // Destructor
+ virtual ~BotanDSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setG(const ByteString& inG);
+ virtual void setY(const ByteString& inY);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::DSA_PublicKey* inDSA);
+
+ // Retrieve the Botan representation of the key
+ Botan::DSA_PublicKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::DSA_PublicKey* dsa;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANDSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDH.cpp b/SoftHSMv2/src/lib/crypto/BotanECDH.cpp
new file mode 100644
index 0000000..2741734
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDH.cpp
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDH.cpp
+
+ Botan ECDH asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "BotanECDH.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "ECParameters.h"
+#include "BotanECDHKeyPair.h"
+#include "BotanUtil.h"
+#include <algorithm>
+#include <botan/dl_group.h>
+#include <botan/ecdh.h>
+#include <botan/pubkey.h>
+#include <botan/version.h>
+
+// Signing functions
+bool BotanECDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("ECDH does not support signing");
+
+ return false;
+}
+
+bool BotanECDH::signUpdate(const ByteString& /*dataToSign*/)
+{
+ ERROR_MSG("ECDH does not support signing");
+
+ return false;
+}
+
+bool BotanECDH::signFinal(ByteString& /*signature*/)
+{
+ ERROR_MSG("ECDH does not support signing");
+
+ return false;
+}
+
+// Verification functions
+bool BotanECDH::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("ECDH does not support verifying");
+
+ return false;
+}
+
+bool BotanECDH::verifyUpdate(const ByteString& /*originalData*/)
+{
+ ERROR_MSG("ECDH does not support verifying");
+
+ return false;
+}
+
+bool BotanECDH::verifyFinal(const ByteString& /*signature*/)
+{
+ ERROR_MSG("ECDH does not support verifying");
+
+ return false;
+}
+
+// Encryption functions
+bool BotanECDH::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("ECDH does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool BotanECDH::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("ECDH does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool BotanECDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(ECParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for ECDH key generation");
+
+ return false;
+ }
+
+ ECParameters* params = (ECParameters*) parameters;
+
+ // Generate the key-pair
+ Botan::ECDH_PrivateKey* eckp = NULL;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ eckp = new Botan::ECDH_PrivateKey(*rng->getRNG(), BotanUtil::byteString2ECGroup(params->getEC()));
+ }
+ catch (...)
+ {
+ ERROR_MSG("ECDH key generation failed");
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanECDHKeyPair* kp = new BotanECDHKeyPair();
+
+ ((BotanECDHPublicKey*) kp->getPublicKey())->setFromBotan(eckp);
+ ((BotanECDHPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete eckp;
+
+ return true;
+}
+
+bool BotanECDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
+{
+ // Check parameters
+ if ((ppSymmetricKey == NULL) ||
+ (publicKey == NULL) ||
+ (privateKey == NULL))
+ {
+ return false;
+ }
+
+ // Get keys
+ Botan::ECDH_PublicKey* pub = ((BotanECDHPublicKey*) publicKey)->getBotanKey();
+ Botan::ECDH_PrivateKey* priv = ((BotanECDHPrivateKey*) privateKey)->getBotanKey();
+ if (pub == NULL || priv == NULL)
+ {
+ ERROR_MSG("Failed to get Botan ECDH keys");
+
+ return false;
+ }
+
+ // Derive the secret
+ Botan::SymmetricKey sk;
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ Botan::PK_Key_Agreement ka(*priv, *rng->getRNG(), "Raw");
+#else
+ Botan::PK_Key_Agreement ka(*priv, "Raw");
+#endif
+ sk = ka.derive_key(0, pub->public_value());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Botan ECDH key agreement failed");
+
+ return false;
+ }
+
+ ByteString secret;
+
+ // We compensate that Botan removes leading zeros
+ int size = ((BotanECDHPublicKey *)publicKey)->getOrderLength();
+ int keySize = sk.length();
+ secret.wipe(size);
+ memcpy(&secret[0] + size - keySize, sk.begin(), keySize);
+
+ *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
+ if (*ppSymmetricKey == NULL)
+ {
+ ERROR_MSG("Can't create ECDH secret");
+
+ return false;
+ }
+ if (!(*ppSymmetricKey)->setKeyBits(secret))
+ {
+ delete *ppSymmetricKey;
+ *ppSymmetricKey = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+unsigned long BotanECDH::getMinKeySize()
+{
+ // Smallest EC group is secp112r1
+ return 112;
+}
+
+unsigned long BotanECDH::getMaxKeySize()
+{
+ // Biggest EC group is secp521r1
+ return 521;
+}
+
+bool BotanECDH::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanECDHKeyPair* kp = new BotanECDHKeyPair();
+
+ bool rv = true;
+
+ if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanECDH::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanECDHPublicKey* pub = new BotanECDHPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanECDH::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanECDHPrivateKey* priv = new BotanECDHPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanECDH::newPublicKey()
+{
+ return (PublicKey*) new BotanECDHPublicKey();
+}
+
+PrivateKey* BotanECDH::newPrivateKey()
+{
+ return (PrivateKey*) new BotanECDHPrivateKey();
+}
+
+AsymmetricParameters* BotanECDH::newParameters()
+{
+ return (AsymmetricParameters*) new ECParameters();
+}
+
+bool BotanECDH::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ECParameters* params = new ECParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDH.h b/SoftHSMv2/src/lib/crypto/BotanECDH.h
new file mode 100644
index 0000000..3fac507
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDH.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDH.h
+
+ Botan ECDH asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANECDH_H
+#define _SOFTHSM_V2_BOTANECDH_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanECDH : public AsymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~BotanECDH() { }
+
+ // Signing functions
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_BOTANECDH_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.cpp
new file mode 100644
index 0000000..74313d9
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDHKeyPair.cpp
+
+ Botan ECDH key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "BotanECDHKeyPair.h"
+
+// Set the public key
+void BotanECDHKeyPair::setPublicKey(BotanECDHPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanECDHKeyPair::setPrivateKey(BotanECDHPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanECDHKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanECDHKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanECDHKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanECDHKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.h
new file mode 100644
index 0000000..a9786b9
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDHKeyPair.h
+
+ Botan ECDH key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANECDHKEYPAIR_H
+#define _SOFTHSM_V2_BOTANECDHKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "BotanECDHPublicKey.h"
+#include "BotanECDHPrivateKey.h"
+
+class BotanECDHKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanECDHPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanECDHPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanECDHPublicKey pubKey;
+
+ // The private key
+ BotanECDHPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_BOTANECDHKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.cpp
new file mode 100644
index 0000000..043e6e1
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDHPrivateKey.cpp
+
+ Botan ECDH private key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "BotanECDHPrivateKey.h"
+#include "BotanCryptoFactory.h"
+#include "BotanRNG.h"
+#include "BotanUtil.h"
+#include <string.h>
+#include <botan/pkcs8.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/asn1_oid.h>
+#include <botan/oids.h>
+#include <botan/version.h>
+
+// Constructors
+BotanECDHPrivateKey::BotanECDHPrivateKey()
+{
+ eckey = NULL;
+}
+
+BotanECDHPrivateKey::BotanECDHPrivateKey(const Botan::ECDH_PrivateKey* inECKEY)
+{
+ eckey = NULL;
+
+ setFromBotan(inECKEY);
+}
+
+// Destructor
+BotanECDHPrivateKey::~BotanECDHPrivateKey()
+{
+ delete eckey;
+}
+
+// The type
+/*static*/ const char* BotanECDHPrivateKey::type = "Botan ECDH Private Key";
+
+// Get the base point order length
+unsigned long BotanECDHPrivateKey::getOrderLength() const
+{
+ try
+ {
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ return group.get_order().bytes();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Can't get EC group for order length");
+
+ return 0;
+ }
+}
+
+// Set from Botan representation
+void BotanECDHPrivateKey::setFromBotan(const Botan::ECDH_PrivateKey* inECKEY)
+{
+ ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain());
+ setEC(inEC);
+ ByteString inD = BotanUtil::bigInt2ByteString(inECKEY->private_value());
+ setD(inD);
+}
+
+// Check if the key is of the given type
+bool BotanECDHPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the ECDH private key components
+void BotanECDHPrivateKey::setD(const ByteString& inD)
+{
+ ECPrivateKey::setD(inD);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+// Setters for the ECDH public key components
+void BotanECDHPrivateKey::setEC(const ByteString& inEC)
+{
+ ECPrivateKey::setEC(inEC);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString BotanECDHPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ createBotanKey();
+ if (eckey == NULL) return der;
+ const size_t PKCS8_VERSION = 0;
+ // No OID for ECDH
+ const Botan::OID oid("1.2.840.10045.2.1");
+ // Force EC_DOMPAR_ENC_OID
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+ const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ const Botan::AlgorithmIdentifier alg_id(oid, parameters);
+ const Botan::secure_vector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(eckey->private_key_bits(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ const Botan::AlgorithmIdentifier alg_id(oid, parameters);
+ const Botan::secure_vector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#else
+ const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ const Botan::AlgorithmIdentifier alg_id(oid, parameters);
+ const Botan::SecureVector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#endif
+ der.resize(ber.size());
+ memcpy(&der[0], &ber[0], ber.size());
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool BotanECDHPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
+ if (source.end_of_data()) return false;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> keydata;
+#else
+ Botan::SecureVector<Botan::byte> keydata;
+#endif
+ Botan::AlgorithmIdentifier alg_id;
+ const Botan::OID oid("1.2.840.10045.2.1");
+ Botan::ECDH_PrivateKey* key = NULL;
+ try
+ {
+ Botan::BER_Decoder(source)
+ .start_cons(Botan::SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
+ .decode(alg_id)
+ .decode(keydata, Botan::OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+ if (keydata.empty())
+ throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
+ // Botan defines == but not != ?!
+ if (!(alg_id.oid == oid))
+ {
+ ERROR_MSG("Decoded private key not ECDH");
+
+ return false;
+ }
+ key = new Botan::ECDH_PrivateKey(alg_id, keydata);
+ if (key == NULL) return false;
+
+ setFromBotan(key);
+
+ delete key;
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Decode failed on %s", e.what());
+
+ return false;
+ }
+
+ return true;
+}
+
+// Retrieve the Botan representation of the key
+Botan::ECDH_PrivateKey* BotanECDHPrivateKey::getBotanKey()
+{
+ if (!eckey)
+ {
+ createBotanKey();
+ }
+
+ return eckey;
+}
+
+// Create the Botan representation of the key
+void BotanECDHPrivateKey::createBotanKey()
+{
+ if (ec.size() != 0 &&
+ d.size() != 0)
+ {
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ eckey = new Botan::ECDH_PrivateKey(*rng->getRNG(),
+ group,
+ BotanUtil::byteString2bigInt(d));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.h
new file mode 100644
index 0000000..d84e046
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDHPrivateKey.h
+
+ Botan ECDH private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANECDHPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANECDHPRIVATEKEY_H
+
+#include "config.h"
+#include "ECPrivateKey.h"
+#include <botan/ecdh.h>
+
+class BotanECDHPrivateKey : public ECPrivateKey
+{
+public:
+ // Constructors
+ BotanECDHPrivateKey();
+
+ BotanECDHPrivateKey(const Botan::ECDH_PrivateKey* inECKEY);
+
+ // Destructor
+ virtual ~BotanECDHPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the ECDH private key components
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the ECDH public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::ECDH_PrivateKey* inECKEY);
+
+ // Retrieve the Botan representation of the key
+ Botan::ECDH_PrivateKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::ECDH_PrivateKey* eckey;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANECDHPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.cpp
new file mode 100644
index 0000000..6201f18
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDHPublicKey.cpp
+
+ Botan ECDH public key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "BotanECDHPublicKey.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanECDHPublicKey::BotanECDHPublicKey()
+{
+ eckey = NULL;
+}
+
+BotanECDHPublicKey::BotanECDHPublicKey(const Botan::ECDH_PublicKey* inECKEY)
+{
+ eckey = NULL;
+
+ setFromBotan(inECKEY);
+}
+
+// Destructor
+BotanECDHPublicKey::~BotanECDHPublicKey()
+{
+ delete eckey;
+}
+
+// The type
+/*static*/ const char* BotanECDHPublicKey::type = "Botan ECDH Public Key";
+
+// Get the base point order length
+unsigned long BotanECDHPublicKey::getOrderLength() const
+{
+ try
+ {
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ return group.get_order().bytes();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Can't get EC group for order length");
+
+ return 0;
+ }
+}
+
+// Set from Botan representation
+void BotanECDHPublicKey::setFromBotan(const Botan::ECDH_PublicKey* inECKEY)
+{
+ ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain());
+ setEC(inEC);
+ ByteString inQ = BotanUtil::ecPoint2ByteString(inECKEY->public_point());
+ setQ(inQ);
+}
+
+// Check if the key is of the given type
+bool BotanECDHPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the ECDH public key components
+void BotanECDHPublicKey::setEC(const ByteString& inEC)
+{
+ ECPublicKey::setEC(inEC);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+void BotanECDHPublicKey::setQ(const ByteString& inQ)
+{
+ ECPublicKey::setQ(inQ);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::ECDH_PublicKey* BotanECDHPublicKey::getBotanKey()
+{
+ if (!eckey)
+ {
+ createBotanKey();
+ }
+
+ return eckey;
+}
+
+// Create the Botan representation of the key
+void BotanECDHPublicKey::createBotanKey()
+{
+ if (ec.size() != 0 &&
+ q.size() != 0)
+ {
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+
+ try
+ {
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ Botan::PointGFp point = BotanUtil::byteString2ECPoint(q, group);
+ eckey = new Botan::ECDH_PublicKey(group, point);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.h
new file mode 100644
index 0000000..0a10743
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDHPublicKey.h
+
+ Botan ECDH public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANECDHPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANECDHPUBLICKEY_H
+
+#include "config.h"
+#include "ECPublicKey.h"
+#include <botan/ecdh.h>
+
+class BotanECDHPublicKey : public ECPublicKey
+{
+public:
+ // Constructors
+ BotanECDHPublicKey();
+
+ BotanECDHPublicKey(const Botan::ECDH_PublicKey* inECKEY);
+
+ // Destructor
+ virtual ~BotanECDHPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the ECDH public key components
+ virtual void setEC(const ByteString& inEC);
+ virtual void setQ(const ByteString& inQ);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::ECDH_PublicKey* inECKEY);
+
+ // Retrieve the Botan representation of the key
+ Botan::ECDH_PublicKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::ECDH_PublicKey* eckey;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANECDHPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSA.cpp b/SoftHSMv2/src/lib/crypto/BotanECDSA.cpp
new file mode 100644
index 0000000..06b7a0f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDSA.cpp
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDSA.cpp
+
+ Botan ECDSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "BotanECDSA.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "ECParameters.h"
+#include "BotanECDSAKeyPair.h"
+#include "BotanUtil.h"
+#include <algorithm>
+#include <botan/ec_group.h>
+#include <botan/ecdsa.h>
+#include <botan/version.h>
+#include <iostream>
+
+// Constructor
+BotanECDSA::BotanECDSA()
+{
+ signer = NULL;
+ verifier = NULL;
+}
+
+// Destructor
+BotanECDSA::~BotanECDSA()
+{
+ delete signer;
+ delete verifier;
+}
+
+// Signing functions
+bool BotanECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ std::string emsa;
+
+ if (mechanism == AsymMech::ECDSA)
+ {
+ emsa = "Raw";
+ }
+ else
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanECDSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanECDSAPrivateKey* pk = (BotanECDSAPrivateKey*) privateKey;
+ Botan::ECDSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (botanKey == NULL)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ return false;
+ }
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
+#else
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+#endif
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ return false;
+ }
+
+ // Perform the signature operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> signResult;
+#else
+ Botan::SecureVector<Botan::byte> signResult;
+#endif
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&signature[0], signResult.data(), signResult.size());
+#else
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+#endif
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+// Signing functions
+bool BotanECDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("ECDSA does not support multi part signing");
+
+ return false;
+}
+
+bool BotanECDSA::signUpdate(const ByteString& /*dataToSign*/)
+{
+ ERROR_MSG("ECDSA does not support multi part signing");
+
+ return false;
+}
+
+bool BotanECDSA::signFinal(ByteString& /*signature*/)
+{
+ ERROR_MSG("ECDSA does not support multi part signing");
+
+ return false;
+}
+
+// Verification functions
+bool BotanECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ std::string emsa;
+
+ if (mechanism == AsymMech::ECDSA)
+ {
+ emsa = "Raw";
+ }
+ else
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanECDSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanECDSAPublicKey* pk = (BotanECDSAPublicKey*) publicKey;
+ Botan::ECDSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (botanKey == NULL)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->verify_message(originalData.const_byte_str(),
+ originalData.size(),
+ signature.const_byte_str(),
+ signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+// Verification functions
+bool BotanECDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("ECDSA does not support multi part verifying");
+
+ return false;
+}
+
+bool BotanECDSA::verifyUpdate(const ByteString& /*originalData*/)
+{
+ ERROR_MSG("ECDSA does not support multi part verifying");
+
+ return false;
+}
+
+bool BotanECDSA::verifyFinal(const ByteString& /*signature*/)
+{
+ ERROR_MSG("ECDSA does not support multi part verifying");
+
+ return false;
+}
+
+// Encryption functions
+bool BotanECDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("ECDSA does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool BotanECDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("ECDSA does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool BotanECDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(ECParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for ECDSA key generation");
+
+ return false;
+ }
+
+ ECParameters* params = (ECParameters*) parameters;
+
+ // Generate the key-pair
+ Botan::ECDSA_PrivateKey* eckp = NULL;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ eckp = new Botan::ECDSA_PrivateKey(*rng->getRNG(), BotanUtil::byteString2ECGroup(params->getEC()));
+ }
+ catch (...)
+ {
+ ERROR_MSG("ECDSA key generation failed");
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanECDSAKeyPair* kp = new BotanECDSAKeyPair();
+
+ ((BotanECDSAPublicKey*) kp->getPublicKey())->setFromBotan(eckp);
+ ((BotanECDSAPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete eckp;
+
+ return true;
+}
+
+unsigned long BotanECDSA::getMinKeySize()
+{
+ // Smallest EC group is secp112r1
+ return 112;
+}
+
+unsigned long BotanECDSA::getMaxKeySize()
+{
+ // Biggest EC group is secp521r1
+ return 521;
+}
+
+bool BotanECDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanECDSAKeyPair* kp = new BotanECDSAKeyPair();
+
+ bool rv = true;
+
+ if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanECDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanECDSAPublicKey* pub = new BotanECDSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanECDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanECDSAPrivateKey* priv = new BotanECDSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanECDSA::newPublicKey()
+{
+ return (PublicKey*) new BotanECDSAPublicKey();
+}
+
+PrivateKey* BotanECDSA::newPrivateKey()
+{
+ return (PrivateKey*) new BotanECDSAPrivateKey();
+}
+
+AsymmetricParameters* BotanECDSA::newParameters()
+{
+ return (AsymmetricParameters*) new ECParameters();
+}
+
+bool BotanECDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ECParameters* params = new ECParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSA.h b/SoftHSMv2/src/lib/crypto/BotanECDSA.h
new file mode 100644
index 0000000..826d318
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDSA.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDSA.h
+
+ Botan ECDSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANECDSA_H
+#define _SOFTHSM_V2_BOTANECDSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanECDSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanECDSA();
+
+ // Destructor
+ virtual ~BotanECDSA();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ Botan::PK_Signer* signer;
+ Botan::PK_Verifier* verifier;
+};
+
+#endif // !_SOFTHSM_V2_BOTANECDSA_H
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.cpp
new file mode 100644
index 0000000..ccc04d7
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDSAKeyPair.cpp
+
+ Botan ECDSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "BotanECDSAKeyPair.h"
+
+// Set the public key
+void BotanECDSAKeyPair::setPublicKey(BotanECDSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanECDSAKeyPair::setPrivateKey(BotanECDSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanECDSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanECDSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanECDSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanECDSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.h
new file mode 100644
index 0000000..960923d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDSAKeyPair.h
+
+ Botan ECDSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANECDSAKEYPAIR_H
+#define _SOFTHSM_V2_BOTANECDSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "BotanECDSAPublicKey.h"
+#include "BotanECDSAPrivateKey.h"
+
+class BotanECDSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanECDSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanECDSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanECDSAPublicKey pubKey;
+
+ // The private key
+ BotanECDSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_BOTANECDSAKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.cpp
new file mode 100644
index 0000000..a276cb0
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.cpp
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDSAPrivateKey.cpp
+
+ Botan ECDSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "BotanECDSAPrivateKey.h"
+#include "BotanCryptoFactory.h"
+#include "BotanRNG.h"
+#include "BotanUtil.h"
+#include <string.h>
+#include <botan/pkcs8.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/asn1_oid.h>
+#include <botan/oids.h>
+#include <botan/version.h>
+
+// Constructors
+BotanECDSAPrivateKey::BotanECDSAPrivateKey()
+{
+ eckey = NULL;
+}
+
+BotanECDSAPrivateKey::BotanECDSAPrivateKey(const Botan::ECDSA_PrivateKey* inECKEY)
+{
+ eckey = NULL;
+
+ setFromBotan(inECKEY);
+}
+
+// Destructor
+BotanECDSAPrivateKey::~BotanECDSAPrivateKey()
+{
+ delete eckey;
+}
+
+// The type
+/*static*/ const char* BotanECDSAPrivateKey::type = "Botan ECDSA Private Key";
+
+// Get the base point order length
+unsigned long BotanECDSAPrivateKey::getOrderLength() const
+{
+ try
+ {
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ return group.get_order().bytes();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Can't get EC group for order length");
+
+ return 0;
+ }
+}
+
+// Set from Botan representation
+void BotanECDSAPrivateKey::setFromBotan(const Botan::ECDSA_PrivateKey* inECKEY)
+{
+ ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain());
+ setEC(inEC);
+ ByteString inD = BotanUtil::bigInt2ByteString(inECKEY->private_value());
+ setD(inD);
+}
+
+// Check if the key is of the given type
+bool BotanECDSAPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the ECDSA private key components
+void BotanECDSAPrivateKey::setD(const ByteString& inD)
+{
+ ECPrivateKey::setD(inD);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+// Setters for the ECDSA public key components
+void BotanECDSAPrivateKey::setEC(const ByteString& inEC)
+{
+ ECPrivateKey::setEC(inEC);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString BotanECDSAPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ createBotanKey();
+ if (eckey == NULL) return der;
+ // Force EC_DOMPAR_ENC_OID
+ const size_t PKCS8_VERSION = 0;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+ const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
+ const Botan::secure_vector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(eckey->private_key_bits(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
+ const Botan::secure_vector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#else
+ const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters);
+ const Botan::SecureVector<Botan::byte> ber =
+ Botan::DER_Encoder()
+ .start_cons(Botan::SEQUENCE)
+ .encode(PKCS8_VERSION)
+ .encode(alg_id)
+ .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING)
+ .end_cons()
+ .get_contents();
+#endif
+ der.resize(ber.size());
+ memcpy(&der[0], &ber[0], ber.size());
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool BotanECDSAPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
+ if (source.end_of_data()) return false;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> keydata;
+#else
+ Botan::SecureVector<Botan::byte> keydata;
+#endif
+ Botan::AlgorithmIdentifier alg_id;
+ Botan::ECDSA_PrivateKey* key = NULL;
+ try
+ {
+ Botan::BER_Decoder(source)
+ .start_cons(Botan::SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
+ .decode(alg_id)
+ .decode(keydata, Botan::OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+ if (keydata.empty())
+ throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
+ if (Botan::OIDS::lookup(alg_id.oid).compare("ECDSA"))
+ {
+ ERROR_MSG("Decoded private key not ECDSA");
+
+ return false;
+ }
+ key = new Botan::ECDSA_PrivateKey(alg_id, keydata);
+ if (key == NULL) return false;
+
+ setFromBotan(key);
+
+ delete key;
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Decode failed on %s", e.what());
+
+ return false;
+ }
+
+ return true;
+}
+
+// Retrieve the Botan representation of the key
+Botan::ECDSA_PrivateKey* BotanECDSAPrivateKey::getBotanKey()
+{
+ if (!eckey)
+ {
+ createBotanKey();
+ }
+
+ return eckey;
+}
+
+// Create the Botan representation of the key
+void BotanECDSAPrivateKey::createBotanKey()
+{
+ if (ec.size() != 0 &&
+ d.size() != 0)
+ {
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ eckey = new Botan::ECDSA_PrivateKey(*rng->getRNG(),
+ group,
+ BotanUtil::byteString2bigInt(d));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.h
new file mode 100644
index 0000000..4477442
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDSAPrivateKey.h
+
+ Botan ECDSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANECDSAPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANECDSAPRIVATEKEY_H
+
+#include "config.h"
+#include "ECPrivateKey.h"
+#include <botan/ecdsa.h>
+
+class BotanECDSAPrivateKey : public ECPrivateKey
+{
+public:
+ // Constructors
+ BotanECDSAPrivateKey();
+
+ BotanECDSAPrivateKey(const Botan::ECDSA_PrivateKey* inECKEY);
+
+ // Destructor
+ virtual ~BotanECDSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the ECDSA private key components
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the ECDSA public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::ECDSA_PrivateKey* inECKEY);
+
+ // Retrieve the Botan representation of the key
+ Botan::ECDSA_PrivateKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::ECDSA_PrivateKey* eckey;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANECDSAPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.cpp
new file mode 100644
index 0000000..3409d88
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDSAPublicKey.cpp
+
+ Botan ECDSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "BotanECDSAPublicKey.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanECDSAPublicKey::BotanECDSAPublicKey()
+{
+ eckey = NULL;
+}
+
+BotanECDSAPublicKey::BotanECDSAPublicKey(const Botan::ECDSA_PublicKey* inECKEY)
+{
+ eckey = NULL;
+
+ setFromBotan(inECKEY);
+}
+
+// Destructor
+BotanECDSAPublicKey::~BotanECDSAPublicKey()
+{
+ delete eckey;
+}
+
+// The type
+/*static*/ const char* BotanECDSAPublicKey::type = "Botan ECDSA Public Key";
+
+// Get the base point order length
+unsigned long BotanECDSAPublicKey::getOrderLength() const
+{
+ try
+ {
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ return group.get_order().bytes();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Can't get EC group for order length");
+
+ return 0;
+ }
+}
+
+// Set from Botan representation
+void BotanECDSAPublicKey::setFromBotan(const Botan::ECDSA_PublicKey* inECKEY)
+{
+ ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain());
+ setEC(inEC);
+ ByteString inQ = BotanUtil::ecPoint2ByteString(inECKEY->public_point());
+ setQ(inQ);
+}
+
+// Check if the key is of the given type
+bool BotanECDSAPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the ECDSA public key components
+void BotanECDSAPublicKey::setEC(const ByteString& inEC)
+{
+ ECPublicKey::setEC(inEC);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+void BotanECDSAPublicKey::setQ(const ByteString& inQ)
+{
+ ECPublicKey::setQ(inQ);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::ECDSA_PublicKey* BotanECDSAPublicKey::getBotanKey()
+{
+ if (!eckey)
+ {
+ createBotanKey();
+ }
+
+ return eckey;
+}
+
+// Create the Botan representation of the key
+void BotanECDSAPublicKey::createBotanKey()
+{
+ if (ec.size() != 0 &&
+ q.size() != 0)
+ {
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+
+ try
+ {
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ Botan::PointGFp point = BotanUtil::byteString2ECPoint(q, group);
+ eckey = new Botan::ECDSA_PublicKey(group, point);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.h
new file mode 100644
index 0000000..6ad0720
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanECDSAPublicKey.h
+
+ Botan ECDSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANECDSAPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANECDSAPUBLICKEY_H
+
+#include "config.h"
+#include "ECPublicKey.h"
+#include <botan/ecdsa.h>
+
+class BotanECDSAPublicKey : public ECPublicKey
+{
+public:
+ // Constructors
+ BotanECDSAPublicKey();
+
+ BotanECDSAPublicKey(const Botan::ECDSA_PublicKey* inECKEY);
+
+ // Destructor
+ virtual ~BotanECDSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the ECDSA public key components
+ virtual void setEC(const ByteString& inEC);
+ virtual void setQ(const ByteString& inQ);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::ECDSA_PublicKey* inECKEY);
+
+ // Retrieve the Botan representation of the key
+ Botan::ECDSA_PublicKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::ECDSA_PublicKey* eckey;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANECDSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOST.cpp b/SoftHSMv2/src/lib/crypto/BotanGOST.cpp
new file mode 100644
index 0000000..ab02d54
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOST.cpp
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOST.cpp
+
+ Botan GOST R 34.10-2001 asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "log.h"
+#include "BotanGOST.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "ECParameters.h"
+#include "BotanGOSTKeyPair.h"
+#include "BotanUtil.h"
+#include <algorithm>
+#include <botan/ec_group.h>
+#include <botan/gost_3410.h>
+#include <botan/version.h>
+#include <iostream>
+
+// Constructor
+BotanGOST::BotanGOST()
+{
+ signer = NULL;
+ verifier = NULL;
+}
+
+// Destructor
+BotanGOST::~BotanGOST()
+{
+ delete signer;
+ delete verifier;
+}
+
+// Signing functions
+bool BotanGOST::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanGOSTPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ std::string emsa;
+
+ switch (mechanism)
+ {
+ case AsymMech::GOST:
+ emsa = "Raw";
+ break;
+ case AsymMech::GOST_GOST:
+ emsa = "EMSA1(GOST-34.11)";
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ BotanGOSTPrivateKey* pk = (BotanGOSTPrivateKey*) currentPrivateKey;
+ Botan::GOST_3410_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (botanKey == NULL)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
+#else
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+#endif
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanGOST::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ try
+ {
+ if (dataToSign.size() != 0)
+ {
+ signer->update(dataToSign.const_byte_str(),
+ dataToSign.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanGOST::signFinal(ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the signature operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> signResult;
+#else
+ Botan::SecureVector<Botan::byte> signResult;
+#endif
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->signature(*rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&signature[0], signResult.data(), signResult.size());
+#else
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+#endif
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool BotanGOST::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanGOSTPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ std::string emsa;
+
+ switch (mechanism)
+ {
+ case AsymMech::GOST:
+ emsa = "Raw";
+ break;
+ case AsymMech::GOST_GOST:
+ emsa = "EMSA1(GOST-34.11)";
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ BotanGOSTPublicKey* pk = (BotanGOSTPublicKey*) currentPublicKey;
+ Botan::GOST_3410_PublicKey* botanKey = pk->getBotanKey();
+
+ if (botanKey == NULL)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanGOST::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ try
+ {
+ if (originalData.size() != 0)
+ {
+ verifier->update(originalData.const_byte_str(),
+ originalData.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanGOST::verifyFinal(const ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->check_signature(signature.const_byte_str(), signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+// Encryption functions
+bool BotanGOST::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("GOST does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool BotanGOST::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("GOST does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool BotanGOST::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(ECParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for GOST key generation");
+
+ return false;
+ }
+
+ ECParameters* params = (ECParameters*) parameters;
+
+ // Generate the key-pair
+ Botan::GOST_3410_PrivateKey* eckp = NULL;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ eckp = new Botan::GOST_3410_PrivateKey(*rng->getRNG(), BotanUtil::byteString2ECGroup(params->getEC()));
+ }
+ catch (...)
+ {
+ ERROR_MSG("GOST key generation failed");
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanGOSTKeyPair* kp = new BotanGOSTKeyPair();
+
+ ((BotanGOSTPublicKey*) kp->getPublicKey())->setFromBotan(eckp);
+ ((BotanGOSTPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete eckp;
+
+ return true;
+}
+
+unsigned long BotanGOST::getMinKeySize()
+{
+ return 0;
+}
+
+unsigned long BotanGOST::getMaxKeySize()
+{
+ return 0;
+}
+
+bool BotanGOST::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanGOSTKeyPair* kp = new BotanGOSTKeyPair();
+
+ bool rv = true;
+
+ if (!((BotanGOSTPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((BotanGOSTPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanGOST::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanGOSTPublicKey* pub = new BotanGOSTPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanGOST::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanGOSTPrivateKey* priv = new BotanGOSTPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanGOST::newPublicKey()
+{
+ return (PublicKey*) new BotanGOSTPublicKey();
+}
+
+PrivateKey* BotanGOST::newPrivateKey()
+{
+ return (PrivateKey*) new BotanGOSTPrivateKey();
+}
+
+AsymmetricParameters* BotanGOST::newParameters()
+{
+ return (AsymmetricParameters*) new ECParameters();
+}
+
+bool BotanGOST::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ECParameters* params = new ECParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOST.h b/SoftHSMv2/src/lib/crypto/BotanGOST.h
new file mode 100644
index 0000000..a8085ab
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOST.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOST.h
+
+ Botan GOST R 34.10-2001 asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANGOST_H
+#define _SOFTHSM_V2_BOTANGOST_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanGOST : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanGOST();
+
+ // Destructor
+ virtual ~BotanGOST();
+
+ // Signing functions
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ Botan::PK_Signer* signer;
+ Botan::PK_Verifier* verifier;
+};
+
+#endif // !_SOFTHSM_V2_BOTANGOST_H
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.cpp
new file mode 100644
index 0000000..08c3de5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOSTKeyPair.cpp
+
+ Botan GOST R 34.10-2001 key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "log.h"
+#include "BotanGOSTKeyPair.h"
+
+// Set the public key
+void BotanGOSTKeyPair::setPublicKey(BotanGOSTPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanGOSTKeyPair::setPrivateKey(BotanGOSTPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanGOSTKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanGOSTKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanGOSTKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanGOSTKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.h
new file mode 100644
index 0000000..2ff1b95
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOSTKeyPair.h
+
+ Botan GOST R 34.10-2001 key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANGOSTKEYPAIR_H
+#define _SOFTHSM_V2_BOTANGOSTKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "BotanGOSTPublicKey.h"
+#include "BotanGOSTPrivateKey.h"
+
+class BotanGOSTKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanGOSTPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanGOSTPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanGOSTPublicKey pubKey;
+
+ // The private key
+ BotanGOSTPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_BOTANGOSTKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.cpp
new file mode 100644
index 0000000..890f135
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOSTPrivateKey.cpp
+
+ Botan GOST R 34.10-2001 private key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "log.h"
+#include "BotanGOSTPrivateKey.h"
+#include "BotanCryptoFactory.h"
+#include "BotanRNG.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanGOSTPrivateKey::BotanGOSTPrivateKey()
+{
+ eckey = NULL;
+}
+
+BotanGOSTPrivateKey::BotanGOSTPrivateKey(const Botan::GOST_3410_PrivateKey* inECKEY)
+{
+ BotanGOSTPrivateKey();
+
+ setFromBotan(inECKEY);
+}
+
+// Destructor
+BotanGOSTPrivateKey::~BotanGOSTPrivateKey()
+{
+ delete eckey;
+}
+
+// The type
+/*static*/ const char* BotanGOSTPrivateKey::type = "Botan GOST Private Key";
+
+// Get the base point order length
+unsigned long BotanGOSTPrivateKey::getOrderLength() const
+{
+ try
+ {
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ return group.get_order().bytes();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Can't get EC group for order length");
+
+ return 0;
+ }
+}
+
+// Get the output length
+unsigned long BotanGOSTPrivateKey::getOutputLength() const
+{
+ return getOrderLength() * 2;
+}
+
+// Set from Botan representation
+void BotanGOSTPrivateKey::setFromBotan(const Botan::GOST_3410_PrivateKey* inECKEY)
+{
+ ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain());
+ setEC(inEC);
+ ByteString inD = BotanUtil::bigInt2ByteStringPrefix(inECKEY->private_value(), 32);
+ setD(inD);
+}
+
+// Check if the key is of the given type
+bool BotanGOSTPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the GOST private key components
+void BotanGOSTPrivateKey::setD(const ByteString& inD)
+{
+ GOSTPrivateKey::setD(inD);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+
+// Setters for the GOST public key components
+void BotanGOSTPrivateKey::setEC(const ByteString& inEC)
+{
+ GOSTPrivateKey::setEC(inEC);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+// Serialisation
+ByteString BotanGOSTPrivateKey::serialise() const
+{
+ return ec.serialise() +
+ d.serialise();
+}
+
+bool BotanGOSTPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+ ByteString dD = ByteString::chainDeserialise(serialised);
+
+ if ((dEC.size() == 0) ||
+ (dD.size() == 0))
+ {
+ return false;
+ }
+
+ setEC(dEC);
+ setD(dD);
+
+ return true;
+}
+
+// Encode into PKCS#8 DER
+ByteString BotanGOSTPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ // TODO
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool BotanGOSTPrivateKey::PKCS8Decode(const ByteString& /*ber*/)
+{
+ return false;
+}
+
+// Retrieve the Botan representation of the key
+Botan::GOST_3410_PrivateKey* BotanGOSTPrivateKey::getBotanKey()
+{
+ if (!eckey)
+ {
+ createBotanKey();
+ }
+
+ return eckey;
+}
+
+// Create the Botan representation of the key
+void BotanGOSTPrivateKey::createBotanKey()
+{
+ if (ec.size() != 0 &&
+ d.size() != 0)
+ {
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ eckey = new Botan::GOST_3410_PrivateKey(*rng->getRNG(),
+ group,
+ BotanUtil::byteString2bigInt(d));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.h
new file mode 100644
index 0000000..cdc825b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOSTPrivateKey.h
+
+ Botan GOST R 34.10-2001 private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANGOSTPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANGOSTPRIVATEKEY_H
+
+#include "config.h"
+#include "GOSTPrivateKey.h"
+#include <botan/gost_3410.h>
+
+class BotanGOSTPrivateKey : public GOSTPrivateKey
+{
+public:
+ // Constructors
+ BotanGOSTPrivateKey();
+
+ BotanGOSTPrivateKey(const Botan::GOST_3410_PrivateKey* inECKEY);
+
+ // Destructor
+ virtual ~BotanGOSTPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the GOST private key components
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the GOST public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::GOST_3410_PrivateKey* inECKEY);
+
+ // Retrieve the Botan representation of the key
+ Botan::GOST_3410_PrivateKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::GOST_3410_PrivateKey* eckey;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANGOSTPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.cpp
new file mode 100644
index 0000000..cebce66
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOSTPublicKey.cpp
+
+ Botan GOST R 34.10-2001 public key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "log.h"
+#include "BotanGOSTPublicKey.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanGOSTPublicKey::BotanGOSTPublicKey()
+{
+ eckey = NULL;
+}
+
+BotanGOSTPublicKey::BotanGOSTPublicKey(const Botan::GOST_3410_PublicKey* inECKEY)
+{
+ BotanGOSTPublicKey();
+
+ setFromBotan(inECKEY);
+}
+
+// Destructor
+BotanGOSTPublicKey::~BotanGOSTPublicKey()
+{
+ delete eckey;
+}
+
+// The type
+/*static*/ const char* BotanGOSTPublicKey::type = "Botan GOST Public Key";
+
+// Get the base point order length
+unsigned long BotanGOSTPublicKey::getOrderLength() const
+{
+ try
+ {
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ return group.get_order().bytes();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Can't get EC group for order length");
+
+ return 0;
+ }
+}
+
+// Get the output length
+unsigned long BotanGOSTPublicKey::getOutputLength() const
+{
+ return getOrderLength() * 2;
+}
+
+// Set from Botan representation
+void BotanGOSTPublicKey::setFromBotan(const Botan::GOST_3410_PublicKey* inECKEY)
+{
+ ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain());
+ setEC(inEC);
+
+ ByteString inQ = BotanUtil::ecPoint2ByteString(inECKEY->public_point()).substr(3);
+
+ /* The points must be stored in little endian */
+ const size_t length = inQ.size() / 2;
+ for (size_t i = 0; i < (length / 2); i++)
+ {
+ std::swap(inQ[i], inQ[length-1-i]);
+ std::swap(inQ[length+i], inQ[2*length-1-i]);
+ }
+
+ setQ(inQ);
+}
+
+// Check if the key is of the given type
+bool BotanGOSTPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the GOST public key components
+void BotanGOSTPublicKey::setEC(const ByteString& inEC)
+{
+ GOSTPublicKey::setEC(inEC);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+void BotanGOSTPublicKey::setQ(const ByteString& inQ)
+{
+ GOSTPublicKey::setQ(inQ);
+
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+}
+
+// Serialisation
+ByteString BotanGOSTPublicKey::serialise() const
+{
+ return ec.serialise() +
+ q.serialise();
+}
+
+bool BotanGOSTPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+
+ if ((dEC.size() == 0) ||
+ (dQ.size() == 0))
+ {
+ return false;
+ }
+
+ setEC(dEC);
+ setQ(dQ);
+
+ return true;
+}
+
+// Retrieve the Botan representation of the key
+Botan::GOST_3410_PublicKey* BotanGOSTPublicKey::getBotanKey()
+{
+ if (!eckey)
+ {
+ createBotanKey();
+ }
+
+ return eckey;
+}
+
+// Create the Botan representation of the key
+void BotanGOSTPublicKey::createBotanKey()
+{
+ if (ec.size() != 0 &&
+ q.size() != 0)
+ {
+ if (eckey)
+ {
+ delete eckey;
+ eckey = NULL;
+ }
+
+ try
+ {
+ /* The points are stored in little endian */
+ ByteString bPoint = q;
+ const size_t length = bPoint.size() / 2;
+ for (size_t i = 0; i < (length / 2); i++)
+ {
+ std::swap(bPoint[i], bPoint[length-1-i]);
+ std::swap(bPoint[length+i], bPoint[2*length-1-i]);
+ }
+ ByteString p = "044104" + bPoint;
+
+ Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec);
+ Botan::PointGFp point = BotanUtil::byteString2ECPoint(p, group);
+ eckey = new Botan::GOST_3410_PublicKey(group, point);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.h
new file mode 100644
index 0000000..6d7e8fc
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOSTPublicKey.h
+
+ Botan GOST R 34.11-2001 public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANGOSTPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANGOSTPUBLICKEY_H
+
+#include "config.h"
+#include "GOSTPublicKey.h"
+#include <botan/gost_3410.h>
+
+class BotanGOSTPublicKey : public GOSTPublicKey
+{
+public:
+ // Constructors
+ BotanGOSTPublicKey();
+
+ BotanGOSTPublicKey(const Botan::GOST_3410_PublicKey* inECKEY);
+
+ // Destructor
+ virtual ~BotanGOSTPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the GOST public key components
+ virtual void setEC(const ByteString& inEC);
+ virtual void setQ(const ByteString& inQ);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::GOST_3410_PublicKey* inECKEY);
+
+ // Retrieve the Botan representation of the key
+ Botan::GOST_3410_PublicKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::GOST_3410_PublicKey* eckey;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANGOSTPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.cpp b/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.cpp
new file mode 100644
index 0000000..344cdcd
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOSTR3411.cpp
+
+ Botan GOST R 34.11-94 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "BotanGOSTR3411.h"
+#include <botan/gost_3411.h>
+
+int BotanGOSTR3411::getHashSize()
+{
+ return 32;
+}
+
+Botan::HashFunction* BotanGOSTR3411::getHash() const
+{
+ return new Botan::GOST_34_11();
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.h b/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.h
new file mode 100644
index 0000000..b0ee374
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanGOSTR3411.h
+
+ Botan GOST R 34.11-94 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANGOSTR3411_H
+#define _SOFTHSM_V2_BOTANGOSTR3411_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanGOSTR3411 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANGOSTR3411_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.cpp
new file mode 100644
index 0000000..9630dfc
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanHashAlgorithm.cpp
+
+ Base class for Botan hash algorithm classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/filters.h>
+
+// Base constructor
+BotanHashAlgorithm::BotanHashAlgorithm()
+{
+ hash = NULL;
+}
+
+// Destructor
+BotanHashAlgorithm::~BotanHashAlgorithm()
+{
+ delete hash;
+}
+
+// Hashing functions
+bool BotanHashAlgorithm::hashInit()
+{
+ if (!HashAlgorithm::hashInit())
+ {
+ return false;
+ }
+
+ // Initialize digesting
+ try
+ {
+ if (hash == NULL)
+ {
+ hash = getHash();
+ }
+ else
+ {
+ hash->clear();
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to initialize the digesting token");
+
+ ByteString dummy;
+ HashAlgorithm::hashFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanHashAlgorithm::hashUpdate(const ByteString& data)
+{
+ if (!HashAlgorithm::hashUpdate(data))
+ {
+ return false;
+ }
+
+ // Continue digesting
+ try
+ {
+ if (data.size() != 0)
+ {
+ hash->update(data.const_byte_str(), data.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to buffer data");
+
+ ByteString dummy;
+ HashAlgorithm::hashFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanHashAlgorithm::hashFinal(ByteString& hashedData)
+{
+ if (!HashAlgorithm::hashFinal(hashedData))
+ {
+ return false;
+ }
+
+ // Resize
+ hashedData.resize(hash->output_length());
+
+ // Read the digest
+ try
+ {
+ hash->final(&hashedData[0]);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to digest the data");
+
+ return false;
+ }
+
+ return true;
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.h b/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.h
new file mode 100644
index 0000000..dde82db
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanHashAlgorithm.h
+
+ Base class for Botan hash algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANHASHALGORITHM_H
+#define _SOFTHSM_V2_BOTANHASHALGORITHM_H
+
+#include "config.h"
+#include "HashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanHashAlgorithm : public HashAlgorithm
+{
+public:
+ // Base constructor
+ BotanHashAlgorithm();
+
+ // Destructor
+ virtual ~BotanHashAlgorithm();
+
+ // Hashing functions
+ virtual bool hashInit();
+ virtual bool hashUpdate(const ByteString& data);
+ virtual bool hashFinal(ByteString& hashedData);
+
+ virtual int getHashSize() = 0;
+protected:
+ virtual Botan::HashFunction* getHash() const = 0;
+
+private:
+ // Current hashing context
+ Botan::HashFunction *hash;
+};
+
+#endif // !_SOFTHSM_V2_BOTANHASHALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanMAC.cpp b/SoftHSMv2/src/lib/crypto/BotanMAC.cpp
new file mode 100644
index 0000000..b45f127
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanMAC.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanMAC.cpp
+
+ Botan MAC implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanMAC.h"
+
+std::string BotanHMACMD5::getAlgorithm() const
+{
+ return "HMAC(MD5)";
+}
+
+size_t BotanHMACMD5::getMacSize() const
+{
+ return 16;
+}
+
+std::string BotanHMACSHA1::getAlgorithm() const
+{
+ return "HMAC(SHA-1)";
+}
+
+size_t BotanHMACSHA1::getMacSize() const
+{
+ return 20;
+}
+
+std::string BotanHMACSHA224::getAlgorithm() const
+{
+ return "HMAC(SHA-224)";
+}
+
+size_t BotanHMACSHA224::getMacSize() const
+{
+ return 28;
+}
+
+std::string BotanHMACSHA256::getAlgorithm() const
+{
+ return "HMAC(SHA-256)";
+}
+
+size_t BotanHMACSHA256::getMacSize() const
+{
+ return 32;
+}
+
+std::string BotanHMACSHA384::getAlgorithm() const
+{
+ return "HMAC(SHA-384)";
+}
+
+size_t BotanHMACSHA384::getMacSize() const
+{
+ return 48;
+}
+
+std::string BotanHMACSHA512::getAlgorithm() const
+{
+ return "HMAC(SHA-512)";
+}
+
+size_t BotanHMACSHA512::getMacSize() const
+{
+ return 64;
+}
+
+#ifdef WITH_GOST
+std::string BotanHMACGOSTR3411::getAlgorithm() const
+{
+ return "HMAC(GOST-34.11)";
+}
+
+size_t BotanHMACGOSTR3411::getMacSize() const
+{
+ return 32;
+}
+#endif
+
+std::string BotanCMACDES::getAlgorithm() const
+{
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ ERROR_MSG("Only supporting 3DES");
+ return "";
+ case 112:
+ case 168:
+ return "CMAC(TripleDES)";
+ default:
+ break;
+ }
+
+ ERROR_MSG("Invalid DES bit len %i", currentKey->getBitLen());
+
+ return "";
+}
+
+size_t BotanCMACDES::getMacSize() const
+{
+ return 8;
+}
+
+std::string BotanCMACAES::getAlgorithm() const
+{
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return "CMAC(AES-128)";
+ case 192:
+ return "CMAC(AES-192)";
+ case 256:
+ return "CMAC(AES-256)";
+ default:
+ break;
+ }
+
+ ERROR_MSG("Invalid AES bit len %i", currentKey->getBitLen());
+
+ return "";
+}
+
+size_t BotanCMACAES::getMacSize() const
+{
+ return 16;
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanMAC.h b/SoftHSMv2/src/lib/crypto/BotanMAC.h
new file mode 100644
index 0000000..4db9aee
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanMAC.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanMAC.h
+
+ Botan MAC implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANMAC_H
+#define _SOFTHSM_V2_BOTANMAC_H
+
+#include "config.h"
+#include "BotanMacAlgorithm.h"
+#include <botan/hmac.h>
+#include <botan/hash.h>
+
+class BotanHMACMD5 : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+
+class BotanHMACSHA1 : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+
+class BotanHMACSHA224 : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+
+class BotanHMACSHA256 : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+
+class BotanHMACSHA384 : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+
+class BotanHMACSHA512 : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+
+#ifdef WITH_GOST
+class BotanHMACGOSTR3411 : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+#endif
+
+class BotanCMACDES : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+
+class BotanCMACAES : public BotanMacAlgorithm
+{
+protected:
+ virtual std::string getAlgorithm() const;
+ virtual size_t getMacSize() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANMAC_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanMD5.cpp b/SoftHSMv2/src/lib/crypto/BotanMD5.cpp
new file mode 100644
index 0000000..382f53d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanMD5.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanMD5.cpp
+
+ Botan MD5 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanMD5.h"
+#include <botan/md5.h>
+
+int BotanMD5::getHashSize()
+{
+ return 16;
+}
+
+Botan::HashFunction* BotanMD5::getHash() const
+{
+ return new Botan::MD5();
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanMD5.h b/SoftHSMv2/src/lib/crypto/BotanMD5.h
new file mode 100644
index 0000000..6542019
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanMD5.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanMD5.h
+
+ Botan MD5 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANMD5_H
+#define _SOFTHSM_V2_BOTANMD5_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanMD5 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANMD5_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.cpp
new file mode 100644
index 0000000..6c863f7
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.cpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// TODO: Store context in securely allocated memory
+
+/*****************************************************************************
+ BotanMacAlgorithm.cpp
+
+ Botan MAC algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanMacAlgorithm.h"
+#include "salloc.h"
+
+#include <botan/symkey.h>
+#include <botan/mac.h>
+#include <botan/botan.h>
+#include <botan/version.h>
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,26)
+#include <botan/lookup.h>
+#endif
+
+// Constructor
+BotanMacAlgorithm::BotanMacAlgorithm()
+{
+ mac = NULL;
+}
+
+// Destructor
+BotanMacAlgorithm::~BotanMacAlgorithm()
+{
+ delete mac;
+ mac = NULL;
+}
+
+// Signing functions
+bool BotanMacAlgorithm::signInit(const SymmetricKey* key)
+{
+ // Call the superclass initialiser
+ if (!MacAlgorithm::signInit(key))
+ {
+ return false;
+ }
+
+ // Determine the hash name
+ std::string macName = getAlgorithm();
+
+ if (macName == "")
+ {
+ ERROR_MSG("Invalid sign mac algorithm");
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the context
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,26)
+ mac = Botan::MessageAuthenticationCode::create(macName).release();
+#else
+ mac = Botan::get_mac(macName);
+#endif
+ mac->set_key(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+ }
+ catch (std::exception &e)
+ {
+ ERROR_MSG("Failed to create the sign mac token: %s", e.what());
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanMacAlgorithm::signUpdate(const ByteString& dataToSign)
+{
+ if (!MacAlgorithm::signUpdate(dataToSign))
+ {
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ try
+ {
+ if (dataToSign.size() != 0)
+ {
+ mac->update(dataToSign.const_byte_str(),
+ dataToSign.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to update the sign mac token");
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanMacAlgorithm::signFinal(ByteString& signature)
+{
+ if (!MacAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the signature operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> signResult;
+#else
+ Botan::SecureVector<Botan::byte> signResult;
+#endif
+ try
+ {
+ signResult = mac->final();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&signature[0], signResult.data(), signResult.size());
+#else
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+#endif
+
+ delete mac;
+ mac = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool BotanMacAlgorithm::verifyInit(const SymmetricKey* key)
+{
+ // Call the superclass initialiser
+ if (!MacAlgorithm::verifyInit(key))
+ {
+ return false;
+ }
+
+ // Determine the hash name
+ std::string macName = getAlgorithm();
+
+ if (macName == "")
+ {
+ ERROR_MSG("Invalid verify mac algorithm");
+
+ ByteString dummy;
+ MacAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the context
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,26)
+ mac = Botan::MessageAuthenticationCode::create(macName).release();
+#else
+ mac = Botan::get_mac(macName);
+#endif
+ mac->set_key(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+ }
+ catch (std::exception &e)
+ {
+ ERROR_MSG("Failed to create the verify mac token: %s", e.what());
+
+ ByteString dummy;
+ MacAlgorithm::verifyFinal(dummy);
+
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanMacAlgorithm::verifyUpdate(const ByteString& originalData)
+{
+ if (!MacAlgorithm::verifyUpdate(originalData))
+ {
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ try
+ {
+ if (originalData.size() != 0)
+ {
+ mac->update(originalData.const_byte_str(),
+ originalData.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to update the verify mac token");
+
+ ByteString dummy;
+ MacAlgorithm::verifyFinal(dummy);
+
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanMacAlgorithm::verifyFinal(ByteString& signature)
+{
+ if (!MacAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> macResult;
+#else
+ Botan::SecureVector<Botan::byte> macResult;
+#endif
+ try
+ {
+ macResult = mac->final();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to verify the data");
+
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ if (macResult.size() != signature.size())
+ {
+ ERROR_MSG("Bad verify result size");
+
+ delete mac;
+ mac = NULL;
+
+ return false;
+ }
+
+ delete mac;
+ mac = NULL;
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ return memcmp(&signature[0], macResult.data(), macResult.size()) == 0;
+#else
+ return memcmp(&signature[0], macResult.begin(), macResult.size()) == 0;
+#endif
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.h b/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.h
new file mode 100644
index 0000000..ac71009
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanMacAlgorithm.h
+
+ Botan MAC algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANMACALGORITHM_H
+#define _SOFTHSM_V2_BOTANMACALGORITHM_H
+
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "MacAlgorithm.h"
+#include <botan/mac.h>
+
+class BotanMacAlgorithm : public MacAlgorithm
+{
+public:
+ // Constructor
+ BotanMacAlgorithm();
+
+ // Destructor
+ virtual ~BotanMacAlgorithm();
+
+ // Signing functions
+ virtual bool signInit(const SymmetricKey* key);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(const SymmetricKey* key);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(ByteString& signature);
+
+ // Return the MAC size
+ virtual size_t getMacSize() const = 0;
+
+protected:
+ // Return the right algorithm for the operation
+ virtual std::string getAlgorithm() const = 0;
+
+private:
+ // The current context
+ Botan::MessageAuthenticationCode* mac;
+};
+
+#endif // !_SOFTHSM_V2_BOTANMACALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanRNG.cpp b/SoftHSMv2/src/lib/crypto/BotanRNG.cpp
new file mode 100644
index 0000000..fa6509d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRNG.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BOTANRNG.cpp
+
+ Botan random number generator class
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanRNG.h"
+
+#include <botan/version.h>
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+#include <botan/libstate.h>
+#else
+#include <botan/auto_rng.h>
+#endif
+
+// Base constructor
+BotanRNG::BotanRNG()
+{
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ rng = &Botan::global_state().global_rng();
+#else
+ rng = new Botan::AutoSeeded_RNG();
+#endif
+}
+
+// Destructor
+BotanRNG::~BotanRNG()
+{
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,14)
+ delete rng;
+#endif
+}
+
+// Generate random data
+bool BotanRNG::generateRandom(ByteString& data, const size_t len)
+{
+ data.wipe(len);
+
+ if (len > 0)
+ rng->randomize(&data[0], len);
+
+ return true;
+}
+
+// Seed the random pool
+void BotanRNG::seed(ByteString& seedData)
+{
+ rng->add_entropy(seedData.byte_str(), seedData.size());
+ // add_entropy will make sure the RNG is reseed so we do not need to call it.
+ // Made this change bacuase of API changes in Botan 1.11.31,
+ // but the statement above is also true for Botan 1.10.
+ // rng->reseed(seedData.size());
+}
+
+// Get the RNG
+Botan::RandomNumberGenerator* BotanRNG::getRNG()
+{
+ return rng;
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanRNG.h b/SoftHSMv2/src/lib/crypto/BotanRNG.h
new file mode 100644
index 0000000..f14b22e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRNG.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRNG.h
+
+ Botan random number generator class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRNG_H
+#define _SOFTHSM_V2_BOTANRNG_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "RNG.h"
+
+#include "botan/rng.h"
+
+class BotanRNG : public RNG
+{
+public:
+ // Base constructor
+ BotanRNG();
+
+ // Destructor
+ virtual ~BotanRNG();
+
+ // Generate random data
+ virtual bool generateRandom(ByteString& data, const size_t len);
+
+ // Seed the random pool
+ virtual void seed(ByteString& seedData);
+
+ // Get RNG
+ Botan::RandomNumberGenerator* getRNG();
+
+private:
+ // The RNG
+ Botan::RandomNumberGenerator* rng;
+};
+
+#endif // !_SOFTHSM_V2_BOTANRNG_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanRSA.cpp b/SoftHSMv2/src/lib/crypto/BotanRSA.cpp
new file mode 100644
index 0000000..2fbb4e2
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRSA.cpp
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSA.cpp
+
+ Botan RSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanRSA.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "RSAParameters.h"
+#include "BotanRSAKeyPair.h"
+#include <algorithm>
+#include <botan/rsa.h>
+#include <botan/version.h>
+#include <sstream>
+
+// Constructor
+BotanRSA::BotanRSA()
+{
+ signer = NULL;
+ verifier = NULL;
+}
+
+// Destructor
+BotanRSA::~BotanRSA()
+{
+ delete signer;
+ delete verifier;
+}
+
+// Signing functions
+bool BotanRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ std::string emsa = "";
+
+ switch (mechanism)
+ {
+ case AsymMech::RSA:
+ emsa = "Raw";
+ break;
+ case AsymMech::RSA_PKCS:
+ emsa = "EMSA3(Raw)";
+ break;
+#ifdef WITH_RAW_PSS
+ case AsymMech::RSA_PKCS_PSS:
+ emsa = getCipherRawPss(privateKey->getBitLength(), dataToSign.size(), param, paramLen);
+ if (emsa == "")
+ {
+ return false;
+ }
+ break;
+#endif
+ default:
+ // Call default implementation
+ return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey;
+ Botan::RSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ return false;
+ }
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
+#else
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+#endif
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ return false;
+ }
+
+ // Perform the signature operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> signResult;
+#else
+ Botan::SecureVector<Botan::byte> signResult;
+#endif
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Could not sign the data: %s", e.what());
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&signature[0], signResult.data(), signResult.size());
+#else
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+#endif
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+bool BotanRSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ std::string emsa;
+ std::ostringstream request;
+ size_t sLen;
+
+ switch (mechanism)
+ {
+ case AsymMech::RSA_MD5_PKCS:
+ emsa = "EMSA3(MD5)";
+ break;
+ case AsymMech::RSA_SHA1_PKCS:
+ emsa = "EMSA3(SHA-160)";
+ break;
+ case AsymMech::RSA_SHA224_PKCS:
+ emsa = "EMSA3(SHA-224)";
+ break;
+ case AsymMech::RSA_SHA256_PKCS:
+ emsa = "EMSA3(SHA-256)";
+ break;
+ case AsymMech::RSA_SHA384_PKCS:
+ emsa = "EMSA3(SHA-384)";
+ break;
+ case AsymMech::RSA_SHA512_PKCS:
+ emsa = "EMSA3(SHA-512)";
+ break;
+ case AsymMech::RSA_SHA1_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-20))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-160,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SHA224_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-28))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-224,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SHA256_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-32))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-256,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SHA384_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-48))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-384,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SHA512_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-64))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-512,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SSL:
+ emsa = "EMSA3(Parallel(MD5,SHA-160))";
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) currentPrivateKey;
+ Botan::RSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
+#else
+ signer = new Botan::PK_Signer(*botanKey, emsa);
+#endif
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanRSA::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ try
+ {
+ if (dataToSign.size() != 0)
+ {
+ signer->update(dataToSign.const_byte_str(),
+ dataToSign.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to signer token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanRSA::signFinal(ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the signature operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> signResult;
+#else
+ Botan::SecureVector<Botan::byte> signResult;
+#endif
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->signature(*rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&signature[0], signResult.data(), signResult.size());
+#else
+ memcpy(&signature[0], signResult.begin(), signResult.size());
+#endif
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool BotanRSA::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ std::string emsa = "";
+
+ switch (mechanism)
+ {
+ case AsymMech::RSA:
+ emsa = "Raw";
+ break;
+ case AsymMech::RSA_PKCS:
+ emsa = "EMSA3(Raw)";
+ break;
+#ifdef WITH_RAW_PSS
+ case AsymMech::RSA_PKCS_PSS:
+ emsa = getCipherRawPss(publicKey->getBitLength(), originalData.size(), param, paramLen);
+ if (emsa == "")
+ {
+ return false;
+ }
+ break;
+#endif
+ default:
+ // Call the generic function
+ return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen);
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey;
+ Botan::RSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->verify_message(originalData.const_byte_str(),
+ originalData.size(),
+ signature.const_byte_str(),
+ signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+bool BotanRSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ std::string emsa;
+ std::ostringstream request;
+ size_t sLen;
+
+ switch (mechanism)
+ {
+ case AsymMech::RSA_MD5_PKCS:
+ emsa = "EMSA3(MD5)";
+ break;
+ case AsymMech::RSA_SHA1_PKCS:
+ emsa = "EMSA3(SHA-160)";
+ break;
+ case AsymMech::RSA_SHA224_PKCS:
+ emsa = "EMSA3(SHA-224)";
+ break;
+ case AsymMech::RSA_SHA256_PKCS:
+ emsa = "EMSA3(SHA-256)";
+ break;
+ case AsymMech::RSA_SHA384_PKCS:
+ emsa = "EMSA3(SHA-384)";
+ break;
+ case AsymMech::RSA_SHA512_PKCS:
+ emsa = "EMSA3(SHA-512)";
+ break;
+ case AsymMech::RSA_SHA1_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-20))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-160,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SHA224_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-28))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-224,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SHA256_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-32))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-256,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SHA384_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-48))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-384,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SHA512_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-64))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ request << "EMSA4(SHA-512,MGF1," << sLen << ")";
+ emsa = request.str();
+ break;
+ case AsymMech::RSA_SSL:
+ emsa = "EMSA3(Parallel(MD5,SHA-160))";
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ BotanRSAPublicKey* pk = (BotanRSAPublicKey*) currentPublicKey;
+ Botan::RSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanRSA::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ try
+ {
+ if (originalData.size() != 0)
+ {
+ verifier->update(originalData.const_byte_str(),
+ originalData.size());
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not add data to the verifier token");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanRSA::verifyFinal(const ByteString& signature)
+{
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->check_signature(signature.const_byte_str(), signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+// Encryption functions
+bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data,
+ ByteString& encryptedData, const AsymMech::Type padding)
+{
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ std::string eme;
+
+ switch (padding)
+ {
+ case AsymMech::RSA_PKCS:
+ eme = "PKCS1v15";
+ break;
+ case AsymMech::RSA_PKCS_OAEP:
+ eme = "EME1(SHA-160)";
+ break;
+ case AsymMech::RSA:
+ eme = "Raw";
+ break;
+ default:
+ ERROR_MSG("Invalid padding mechanism supplied (%i)", padding);
+
+ return false;
+ }
+
+ BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey;
+ Botan::RSA_PublicKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ return false;
+ }
+
+ Botan::PK_Encryptor_EME* encryptor = NULL;
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ encryptor = new Botan::PK_Encryptor_EME(*botanKey, *rng->getRNG(), eme);
+#else
+ encryptor = new Botan::PK_Encryptor_EME(*botanKey, eme);
+#endif
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the encryptor token");
+
+ return false;
+ }
+
+ // Perform the encryption operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> encResult;
+#else
+ Botan::SecureVector<Botan::byte> encResult;
+#endif
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ encResult = encryptor->encrypt(data.const_byte_str(), data.size(), *rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not encrypt the data");
+
+ delete encryptor;
+
+ return false;
+ }
+
+ // Return the result
+ encryptedData.resize(encResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&encryptedData[0], encResult.data(), encResult.size());
+#else
+ memcpy(&encryptedData[0], encResult.begin(), encResult.size());
+#endif
+
+ delete encryptor;
+
+ return true;
+}
+
+// Decryption functions
+bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData,
+ ByteString& data, const AsymMech::Type padding)
+{
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ std::string eme;
+
+ switch (padding)
+ {
+ case AsymMech::RSA_PKCS:
+ eme = "PKCS1v15";
+ break;
+ case AsymMech::RSA_PKCS_OAEP:
+ eme = "EME1(SHA-160)";
+ break;
+ case AsymMech::RSA:
+ eme = "Raw";
+ break;
+ default:
+ ERROR_MSG("Invalid padding mechanism supplied (%i)", padding);
+
+ return false;
+ }
+
+ BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey;
+ Botan::RSA_PrivateKey* botanKey = pk->getBotanKey();
+
+ if (!botanKey)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ return false;
+ }
+
+ Botan::PK_Decryptor_EME* decryptor = NULL;
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33)
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ decryptor = new Botan::PK_Decryptor_EME(*botanKey, *rng->getRNG(), eme);
+#else
+ decryptor = new Botan::PK_Decryptor_EME(*botanKey, eme);
+#endif
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the decryptor token");
+
+ return false;
+ }
+
+ // Perform the decryption operation
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> decResult;
+#else
+ Botan::SecureVector<Botan::byte> decResult;
+#endif
+ try
+ {
+ decResult = decryptor->decrypt(encryptedData.const_byte_str(), encryptedData.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not decrypt the data");
+
+ delete decryptor;
+
+ return false;
+ }
+
+ // Return the result
+ if (padding == AsymMech::RSA)
+ {
+ // We compensate that Botan removes leading zeros
+ int modSize = pk->getN().size();
+ int decSize = decResult.size();
+ data.resize(modSize);
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&data[0] + modSize - decSize, decResult.data(), decSize);
+#else
+ memcpy(&data[0] + modSize - decSize, decResult.begin(), decSize);
+#endif
+ }
+ else
+ {
+ data.resize(decResult.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&data[0], decResult.data(), decResult.size());
+#else
+ memcpy(&data[0], decResult.begin(), decResult.size());
+#endif
+ }
+
+ delete decryptor;
+
+ return true;
+}
+
+// Key factory
+bool BotanRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(RSAParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for RSA key generation");
+
+ return false;
+ }
+
+ RSAParameters* params = (RSAParameters*) parameters;
+
+ if (params->getBitLength() < getMinKeySize() || params->getBitLength() > getMaxKeySize())
+ {
+ ERROR_MSG("This RSA key size (%lu) is not supported", params->getBitLength());
+
+ return false;
+ }
+
+ // Retrieve the desired public exponent
+ unsigned long e = params->getE().long_val();
+
+ // Check the public exponent
+ if ((e == 0) || (e % 2 != 1))
+ {
+ ERROR_MSG("Invalid RSA public exponent %d", e);
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanRSAKeyPair* kp = new BotanRSAKeyPair();
+
+ // Generate the key-pair
+ Botan::RSA_PrivateKey* rsa = NULL;
+ try {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ rsa = new Botan::RSA_PrivateKey(*rng->getRNG(), params->getBitLength(), e);
+ }
+ catch (std::exception& ex) {
+ ERROR_MSG("RSA key generation failed: %s", ex.what());
+
+ delete kp;
+
+ return false;
+ }
+
+ ((BotanRSAPublicKey*) kp->getPublicKey())->setFromBotan(rsa);
+ ((BotanRSAPrivateKey*) kp->getPrivateKey())->setFromBotan(rsa);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete rsa;
+
+ return true;
+}
+
+unsigned long BotanRSA::getMinKeySize()
+{
+ return 1024;
+}
+
+unsigned long BotanRSA::getMaxKeySize()
+{
+ return 4096;
+}
+
+bool BotanRSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanRSAKeyPair* kp = new BotanRSAKeyPair();
+
+ bool rv = true;
+
+ if (!((RSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((RSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanRSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanRSAPublicKey* pub = new BotanRSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanRSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanRSAPrivateKey* priv = new BotanRSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanRSA::newPublicKey()
+{
+ return (PublicKey*) new BotanRSAPublicKey();
+}
+
+PrivateKey* BotanRSA::newPrivateKey()
+{
+ return (PrivateKey*) new BotanRSAPrivateKey();
+}
+
+AsymmetricParameters* BotanRSA::newParameters()
+{
+ return (AsymmetricParameters*) new RSAParameters();
+}
+
+bool BotanRSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ RSAParameters* params = new RSAParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+
+#ifdef WITH_RAW_PSS
+std::string BotanRSA::getCipherRawPss(size_t bitLength, size_t dataSize, const void* param, const size_t paramLen)
+{
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS))
+ {
+ ERROR_MSG("Invalid parameters");
+ return "";
+ }
+
+ std::string hashStr = "";
+ size_t allowedLen = 0;
+ switch (((RSA_PKCS_PSS_PARAMS*) param)->hashAlg)
+ {
+ case HashAlgo::SHA1:
+ hashStr = "SHA-160";
+ allowedLen = 20;
+ break;
+ case HashAlgo::SHA224:
+ hashStr = "SHA-224";
+ allowedLen = 28;
+ break;
+ case HashAlgo::SHA256:
+ hashStr = "SHA-256";
+ allowedLen = 32;
+ break;
+ case HashAlgo::SHA384:
+ hashStr = "SHA-384";
+ allowedLen = 48;
+ break;
+ case HashAlgo::SHA512:
+ hashStr = "SHA-512";
+ allowedLen = 64;
+ break;
+ default:
+ ERROR_MSG("Invalid hash parameter");
+ return "";
+ }
+
+ if (dataSize != allowedLen)
+ {
+ ERROR_MSG("Data to sign does not match expected (%d) for RSA PSS", (int)allowedLen);
+ return "";
+ }
+
+ size_t sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((bitLength+6)/8-2-20))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, bitLength);
+ return "";
+ }
+
+ std::ostringstream request;
+ request << "PSSR_Raw(" << hashStr << ",MGF1," << sLen << ")";
+ return request.str();
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanRSA.h b/SoftHSMv2/src/lib/crypto/BotanRSA.h
new file mode 100644
index 0000000..f9b6554
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRSA.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSA.h
+
+ Botan RSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRSA_H
+#define _SOFTHSM_V2_BOTANRSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanRSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanRSA();
+
+ // Destructor
+ virtual ~BotanRSA();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ Botan::PK_Signer* signer;
+ Botan::PK_Verifier* verifier;
+
+#ifdef WITH_RAW_PSS
+ std::string getCipherRawPss(size_t bitLength, size_t dataSize, const void* param, const size_t paramLen);
+#endif
+};
+
+#endif // !_SOFTHSM_V2_BOTANRSA_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.cpp
new file mode 100644
index 0000000..76d9b5b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAKeyPair.cpp
+
+ Botan RSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanRSAKeyPair.h"
+
+// Set the public key
+void BotanRSAKeyPair::setPublicKey(BotanRSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanRSAKeyPair::setPrivateKey(BotanRSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanRSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanRSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanRSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanRSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.h
new file mode 100644
index 0000000..55f4955
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAKeyPair.h
+
+ Botan RSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRSAKEYPAIR_H
+#define _SOFTHSM_V2_BOTANRSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "BotanRSAPublicKey.h"
+#include "BotanRSAPrivateKey.h"
+
+class BotanRSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanRSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanRSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanRSAPublicKey pubKey;
+
+ // The private key
+ BotanRSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_BOTANRSAKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.cpp
new file mode 100644
index 0000000..f600230
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.cpp
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAPrivateKey.cpp
+
+ Botan RSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanRSAPrivateKey.h"
+#include "BotanUtil.h"
+#include "BotanRNG.h"
+#include "BotanCryptoFactory.h"
+#include <string.h>
+#include <botan/pkcs8.h>
+#include <botan/pkcs8.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/oids.h>
+#include <botan/version.h>
+
+// Constructors
+BotanRSAPrivateKey::BotanRSAPrivateKey()
+{
+ rsa = NULL;
+}
+
+BotanRSAPrivateKey::BotanRSAPrivateKey(const Botan::RSA_PrivateKey* inRSA)
+{
+ rsa = NULL;
+
+ setFromBotan(inRSA);
+}
+
+// Destructor
+BotanRSAPrivateKey::~BotanRSAPrivateKey()
+{
+ delete rsa;
+}
+
+// The type
+/*static*/ const char* BotanRSAPrivateKey::type = "Botan RSA Private Key";
+
+// Set from Botan representation
+void BotanRSAPrivateKey::setFromBotan(const Botan::RSA_PrivateKey* inRSA)
+{
+ ByteString inP = BotanUtil::bigInt2ByteString(inRSA->get_p());
+ setP(inP);
+ ByteString inQ = BotanUtil::bigInt2ByteString(inRSA->get_q());
+ setQ(inQ);
+ ByteString inDP1 = BotanUtil::bigInt2ByteString(inRSA->get_d1());
+ setDP1(inDP1);
+ ByteString inDQ1 = BotanUtil::bigInt2ByteString(inRSA->get_d2());
+ setDQ1(inDQ1);
+ ByteString inPQ = BotanUtil::bigInt2ByteString(inRSA->get_c());
+ setPQ(inPQ);
+ ByteString inD = BotanUtil::bigInt2ByteString(inRSA->get_d());
+ setD(inD);
+ ByteString inN = BotanUtil::bigInt2ByteString(inRSA->get_n());
+ setN(inN);
+ ByteString inE = BotanUtil::bigInt2ByteString(inRSA->get_e());
+ setE(inE);
+}
+
+// Check if the key is of the given type
+bool BotanRSAPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the RSA private key components
+void BotanRSAPrivateKey::setP(const ByteString& inP)
+{
+ RSAPrivateKey::setP(inP);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setQ(const ByteString& inQ)
+{
+ RSAPrivateKey::setQ(inQ);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setPQ(const ByteString& inPQ)
+{
+ RSAPrivateKey::setPQ(inPQ);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setDP1(const ByteString& inDP1)
+{
+ RSAPrivateKey::setDP1(inDP1);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setDQ1(const ByteString& inDQ1)
+{
+ RSAPrivateKey::setDQ1(inDQ1);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setD(const ByteString& inD)
+{
+ RSAPrivateKey::setD(inD);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+
+// Setters for the RSA public key components
+void BotanRSAPrivateKey::setN(const ByteString& inN)
+{
+ RSAPrivateKey::setN(inN);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPrivateKey::setE(const ByteString& inE)
+{
+ RSAPrivateKey::setE(inE);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString BotanRSAPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ createBotanKey();
+ if (rsa == NULL) return der;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ const Botan::secure_vector<Botan::byte> ber = Botan::PKCS8::BER_encode(*rsa);
+#else
+ const Botan::SecureVector<Botan::byte> ber = Botan::PKCS8::BER_encode(*rsa);
+#endif
+ der.resize(ber.size());
+ memcpy(&der[0], &ber[0], ber.size());
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool BotanRSAPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
+ if (source.end_of_data()) return false;
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> keydata;
+#else
+ Botan::SecureVector<Botan::byte> keydata;
+#endif
+ Botan::AlgorithmIdentifier alg_id;
+ Botan::RSA_PrivateKey* key = NULL;
+ try
+ {
+
+ Botan::BER_Decoder(source)
+ .start_cons(Botan::SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
+ .decode(alg_id)
+ .decode(keydata, Botan::OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+ if (keydata.empty())
+ throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
+ if (Botan::OIDS::lookup(alg_id.oid).compare("RSA"))
+ {
+ ERROR_MSG("Decoded private key not RSA");
+
+ return false;
+ }
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34)
+ key = new Botan::RSA_PrivateKey(alg_id, keydata);
+#else
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ key = new Botan::RSA_PrivateKey(alg_id, keydata, *rng->getRNG());
+#endif
+ if (key == NULL) return false;
+
+ setFromBotan(key);
+
+ delete key;
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Decode failed on %s", e.what());
+
+ return false;
+ }
+
+ return true;
+}
+
+// Retrieve the Botan representation of the key
+Botan::RSA_PrivateKey* BotanRSAPrivateKey::getBotanKey()
+{
+ if (!rsa)
+ {
+ createBotanKey();
+ }
+
+ return rsa;
+}
+
+// Create the Botan representation of the key
+void BotanRSAPrivateKey::createBotanKey()
+{
+ // d and n is not needed, they can be calculated
+ if (p.size() != 0 &&
+ q.size() != 0 &&
+ e.size() != 0)
+ {
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34)
+ rsa = new Botan::RSA_PrivateKey(
+ BotanUtil::byteString2bigInt(p),
+ BotanUtil::byteString2bigInt(q),
+ BotanUtil::byteString2bigInt(e),
+ BotanUtil::byteString2bigInt(d),
+ BotanUtil::byteString2bigInt(n));
+#else
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ rsa = new Botan::RSA_PrivateKey(*rng->getRNG(),
+ BotanUtil::byteString2bigInt(p),
+ BotanUtil::byteString2bigInt(q),
+ BotanUtil::byteString2bigInt(e),
+ BotanUtil::byteString2bigInt(d),
+ BotanUtil::byteString2bigInt(n));
+#endif
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan private key");
+ }
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.h
new file mode 100644
index 0000000..7664a86
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAPrivateKey.h
+
+ Botan RSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRSAPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANRSAPRIVATEKEY_H
+
+#include "config.h"
+#include "RSAPrivateKey.h"
+#include <botan/rsa.h>
+
+class BotanRSAPrivateKey : public RSAPrivateKey
+{
+public:
+ // Constructors
+ BotanRSAPrivateKey();
+
+ BotanRSAPrivateKey(const Botan::RSA_PrivateKey* inRSA);
+
+ // Destructor
+ virtual ~BotanRSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the RSA private key components
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setPQ(const ByteString& inPQ);
+ virtual void setDP1(const ByteString& inDP1);
+ virtual void setDQ1(const ByteString& inDQ1);
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& inN);
+ virtual void setE(const ByteString& inE);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::RSA_PrivateKey* inRSA);
+
+ // Retrieve the Botan representation of the key
+ Botan::RSA_PrivateKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::RSA_PrivateKey* rsa;
+
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSAPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.cpp
new file mode 100644
index 0000000..63bc82c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAPublicKey.cpp
+
+ Botan RSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "BotanRSAPublicKey.h"
+#include "BotanUtil.h"
+#include <string.h>
+
+// Constructors
+BotanRSAPublicKey::BotanRSAPublicKey()
+{
+ rsa = NULL;
+}
+
+BotanRSAPublicKey::BotanRSAPublicKey(const Botan::RSA_PublicKey* inRSA)
+{
+ rsa = NULL;
+
+ setFromBotan(inRSA);
+}
+
+// Destructor
+BotanRSAPublicKey::~BotanRSAPublicKey()
+{
+ delete rsa;
+}
+
+// The type
+/*static*/ const char* BotanRSAPublicKey::type = "Botan RSA Public Key";
+
+// Check if the key is of the given type
+bool BotanRSAPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Set from OpenSSL representation
+void BotanRSAPublicKey::setFromBotan(const Botan::RSA_PublicKey* inRSA)
+{
+ ByteString inN = BotanUtil::bigInt2ByteString(inRSA->get_n());
+ setN(inN);
+ ByteString inE = BotanUtil::bigInt2ByteString(inRSA->get_e());
+ setE(inE);
+}
+
+// Setters for the RSA public key components
+void BotanRSAPublicKey::setN(const ByteString& inN)
+{
+ RSAPublicKey::setN(inN);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+void BotanRSAPublicKey::setE(const ByteString& inE)
+{
+ RSAPublicKey::setE(inE);
+
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::RSA_PublicKey* BotanRSAPublicKey::getBotanKey()
+{
+ if (!rsa)
+ {
+ createBotanKey();
+ }
+
+ return rsa;
+}
+
+// Create the Botan representation of the key
+void BotanRSAPublicKey::createBotanKey()
+{
+ if (n.size() != 0 && e.size() != 0)
+ {
+ if (rsa)
+ {
+ delete rsa;
+ rsa = NULL;
+ }
+
+ try
+ {
+ rsa = new Botan::RSA_PublicKey(BotanUtil::byteString2bigInt(n),
+ BotanUtil::byteString2bigInt(e));
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.h
new file mode 100644
index 0000000..a0c0026
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanRSAPublicKey.h
+
+ Botan RSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANRSAPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANRSAPUBLICKEY_H
+
+#include "config.h"
+#include "RSAPublicKey.h"
+#include <botan/rsa.h>
+
+class BotanRSAPublicKey : public RSAPublicKey
+{
+public:
+ // Constructors
+ BotanRSAPublicKey();
+
+ BotanRSAPublicKey(const Botan::RSA_PublicKey* inRSA);
+
+ // Destructor
+ virtual ~BotanRSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& inN);
+ virtual void setE(const ByteString& inE);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::RSA_PublicKey* inRSA);
+
+ // Retrieve the Botan representation of the key
+ Botan::RSA_PublicKey* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::RSA_PublicKey* rsa;
+
+ void createBotanKey();
+};
+
+#endif // !_SOFTHSM_V2_BOTANRSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA1.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA1.cpp
new file mode 100644
index 0000000..35846ec
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA1.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA1.cpp
+
+ Botan SHA1 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA1.h"
+#include <botan/sha160.h>
+
+int BotanSHA1::getHashSize()
+{
+ return 20;
+}
+
+Botan::HashFunction* BotanSHA1::getHash() const
+{
+ return new Botan::SHA_160();
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA1.h b/SoftHSMv2/src/lib/crypto/BotanSHA1.h
new file mode 100644
index 0000000..ca336b0
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA1.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA1.h
+
+ Botan SHA1 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA1_H
+#define _SOFTHSM_V2_BOTANSHA1_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA1 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA1_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA224.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA224.cpp
new file mode 100644
index 0000000..f1d2268
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA224.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA224.cpp
+
+ Botan SHA224 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA224.h"
+#include <botan/sha2_32.h>
+
+int BotanSHA224::getHashSize()
+{
+ return 28;
+}
+
+Botan::HashFunction* BotanSHA224::getHash() const
+{
+ return new Botan::SHA_224();
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA224.h b/SoftHSMv2/src/lib/crypto/BotanSHA224.h
new file mode 100644
index 0000000..61fe16c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA224.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA224.h
+
+ Botan SHA224 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA224_H
+#define _SOFTHSM_V2_BOTANSHA224_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA224 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA224_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA256.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA256.cpp
new file mode 100644
index 0000000..878dece
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA256.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA256.cpp
+
+ Botan SHA256 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA256.h"
+#include <botan/sha2_32.h>
+
+int BotanSHA256::getHashSize()
+{
+ return 32;
+}
+
+Botan::HashFunction* BotanSHA256::getHash() const
+{
+ return new Botan::SHA_256();
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA256.h b/SoftHSMv2/src/lib/crypto/BotanSHA256.h
new file mode 100644
index 0000000..5561f3c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA256.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA256.h
+
+ Botan SHA256 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA256_H
+#define _SOFTHSM_V2_BOTANSHA256_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA256 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA256_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA384.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA384.cpp
new file mode 100644
index 0000000..b7a1e09
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA384.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA384.cpp
+
+ Botan SHA384 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA384.h"
+#include <botan/sha2_64.h>
+
+int BotanSHA384::getHashSize()
+{
+ return 48;
+}
+
+Botan::HashFunction* BotanSHA384::getHash() const
+{
+ return new Botan::SHA_384();
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA384.h b/SoftHSMv2/src/lib/crypto/BotanSHA384.h
new file mode 100644
index 0000000..5cf5d98
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA384.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA384.h
+
+ Botan SHA384 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA384_H
+#define _SOFTHSM_V2_BOTANSHA384_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA384 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA384_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA512.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA512.cpp
new file mode 100644
index 0000000..b7aa459
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA512.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA512.cpp
+
+ Botan SHA512 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSHA512.h"
+#include <botan/sha2_64.h>
+
+int BotanSHA512::getHashSize()
+{
+ return 64;
+}
+
+Botan::HashFunction* BotanSHA512::getHash() const
+{
+ return new Botan::SHA_512();
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA512.h b/SoftHSMv2/src/lib/crypto/BotanSHA512.h
new file mode 100644
index 0000000..d72416e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSHA512.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSHA512.h
+
+ Botan SHA512 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSHA512_H
+#define _SOFTHSM_V2_BOTANSHA512_H
+
+#include "config.h"
+#include "BotanHashAlgorithm.h"
+#include <botan/hash.h>
+
+class BotanSHA512 : public BotanHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual Botan::HashFunction* getHash() const;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSHA512_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.cpp
new file mode 100644
index 0000000..3f13892
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.cpp
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// TODO: Store context in securely allocated memory
+
+/*****************************************************************************
+ BotanSymmetricAlgorithm.cpp
+
+ Botan symmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanSymmetricAlgorithm.h"
+#include "BotanUtil.h"
+#include "salloc.h"
+#include <iostream>
+
+#include <botan/symkey.h>
+#include <botan/botan.h>
+#include <botan/version.h>
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,14)
+#include <botan/key_filt.h>
+#endif
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+#include "Botan_ecb.h"
+#include <botan/cipher_filter.h>
+#endif
+
+#ifdef WITH_AES_GCM
+#include <botan/aead.h>
+#endif
+
+// Constructor
+BotanSymmetricAlgorithm::BotanSymmetricAlgorithm()
+{
+ cryption = NULL;
+ maximumBytes = Botan::BigInt(1);
+ maximumBytes.flip_sign();
+ counterBytes = Botan::BigInt(0);
+}
+
+// Destructor
+BotanSymmetricAlgorithm::~BotanSymmetricAlgorithm()
+{
+ delete cryption;
+ cryption = NULL;
+}
+
+// Encryption functions
+bool BotanSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode:CBC */, const ByteString& IV /* = ByteString()*/, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& aad /* = ByteString() */, size_t tagBytes /* = 0 */)
+{
+ // Call the superclass initialiser
+ if (!SymmetricAlgorithm::encryptInit(key, mode, IV, padding, counterBits, aad, tagBytes))
+ {
+ return false;
+ }
+
+ // Check the IV
+ if (mode != SymMode::GCM && (IV.size() > 0) && (IV.size() != getBlockSize()))
+ {
+ ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ ByteString iv;
+
+ if (IV.size() > 0)
+ {
+ iv = IV;
+ }
+ else
+ {
+ iv.wipe(getBlockSize());
+ }
+
+ // Check the counter bits
+ if (counterBits > 0)
+ {
+ Botan::BigInt counter = BotanUtil::byteString2bigInt(iv);
+ counter.mask_bits(counterBits);
+
+ // Reverse the bits
+ while (counterBits > 0)
+ {
+ counterBits--;
+ if (counter.get_bit(counterBits))
+ {
+ counter.clear_bit(counterBits);
+ }
+ else
+ {
+ counter.set_bit(counterBits);
+ }
+ }
+
+ // Set the maximum bytes
+ maximumBytes = (counter + 1) * getBlockSize();
+ counterBytes = Botan::BigInt(0);
+ }
+ else
+ {
+ maximumBytes = Botan::BigInt(1);
+ maximumBytes.flip_sign();
+ }
+
+ // Determine the cipher
+ std::string cipherName = getCipher();
+
+ if (cipherName == "")
+ {
+ ERROR_MSG("Invalid encryption cipher");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the context
+ try
+ {
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+ if (mode == SymMode::ECB)
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+ // ECB cipher mode was dropped in Botan 2.0
+ const std::vector<std::string> algo_parts = Botan::split_on(cipherName, '/');
+ const std::string cipher_name = algo_parts[0];
+ Botan::BlockCipherModePaddingMethod* pad;
+ if (algo_parts.size() == 3 && algo_parts[2] == "PKCS7")
+ {
+ pad = new Botan::PKCS7_Padding();
+ }
+ else
+ {
+ pad = new Botan::Null_Padding();
+ }
+ std::unique_ptr<Botan::BlockCipher> bc(Botan::BlockCipher::create(cipher_name));
+ Botan::Keyed_Filter* cipher = new Botan::Cipher_Mode_Filter(new Botan::ECB_Encryption(bc.release(),pad));
+ cipher->set_key(botanKey);
+ cryption = new Botan::Pipe(cipher);
+#else
+ cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, Botan::ENCRYPTION));
+#endif
+ }
+#ifdef WITH_AES_GCM
+ else if (mode == SymMode::GCM)
+ {
+ Botan::AEAD_Mode* aead = Botan::get_aead(cipherName, Botan::ENCRYPTION);
+ aead->set_key(botanKey);
+ aead->set_associated_data(aad.const_byte_str(), aad.size());
+
+ Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size());
+ Botan::Keyed_Filter* filter = new Botan::Cipher_Mode_Filter(aead);
+ filter->set_iv(botanIV);
+ cryption = new Botan::Pipe(filter);
+ }
+#endif
+ else
+ {
+ Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size());
+ cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, botanIV, Botan::ENCRYPTION));
+ }
+ cryption->start_msg();
+ }
+ catch (std::exception &e)
+ {
+ ERROR_MSG("Failed to create the encryption token: %s", e.what());
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanSymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& encryptedData)
+{
+ if (!SymmetricAlgorithm::encryptUpdate(data, encryptedData))
+ {
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Write data
+ try
+ {
+ if (data.size() > 0)
+ cryption->write(data.const_byte_str(), data.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to write to the encryption token");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Count number of bytes written
+ if (maximumBytes.is_positive())
+ {
+ counterBytes += data.size();
+ }
+
+ // Read data
+ int bytesRead = 0;
+ try
+ {
+ size_t outLen = cryption->remaining();
+ encryptedData.resize(outLen);
+ if (outLen > 0)
+ bytesRead = cryption->read(&encryptedData[0], outLen);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to encrypt the data");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Resize the output block
+ encryptedData.resize(bytesRead);
+ currentBufferSize -= bytesRead;
+
+ return true;
+}
+
+bool BotanSymmetricAlgorithm::encryptFinal(ByteString& encryptedData)
+{
+ if (!SymmetricAlgorithm::encryptFinal(encryptedData))
+ {
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Read data
+ int bytesRead = 0;
+ try
+ {
+ cryption->end_msg();
+ size_t outLen = cryption->remaining();
+ encryptedData.resize(outLen);
+ if (outLen > 0)
+ bytesRead = cryption->read(&encryptedData[0], outLen);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to encrypt the data");
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Clean up
+ delete cryption;
+ cryption = NULL;
+
+ // Resize the output block
+ encryptedData.resize(bytesRead);
+
+ return true;
+}
+
+// Decryption functions
+bool BotanSymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& IV /* = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& aad /* = ByteString() */, size_t tagBytes /* = 0 */)
+{
+ // Call the superclass initialiser
+ if (!SymmetricAlgorithm::decryptInit(key, mode, IV, padding, counterBits, aad, tagBytes))
+ {
+ return false;
+ }
+
+ // Check the IV
+ if (mode != SymMode::GCM && (IV.size() > 0) && (IV.size() != getBlockSize()))
+ {
+ ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ ByteString iv;
+
+ if (IV.size() > 0)
+ {
+ iv = IV;
+ }
+ else
+ {
+ iv.wipe(getBlockSize());
+ }
+
+ // Check the counter bits
+ if (counterBits > 0)
+ {
+ Botan::BigInt counter = BotanUtil::byteString2bigInt(iv);
+ counter.mask_bits(counterBits);
+
+ // Reverse the bits
+ while (counterBits > 0)
+ {
+ counterBits--;
+ if (counter.get_bit(counterBits))
+ {
+ counter.clear_bit(counterBits);
+ }
+ else
+ {
+ counter.set_bit(counterBits);
+ }
+ }
+
+ // Set the maximum bytes
+ maximumBytes = (counter + 1) * getBlockSize();
+ counterBytes = Botan::BigInt(0);
+ }
+ else
+ {
+ maximumBytes = Botan::BigInt(1);
+ maximumBytes.flip_sign();
+ }
+
+ // Determine the cipher class
+ std::string cipherName = getCipher();
+
+ if (cipherName == "")
+ {
+ ERROR_MSG("Invalid decryption cipher");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the context
+ try
+ {
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+ if (mode == SymMode::ECB)
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+ // ECB cipher mode was dropped in Botan 2.0
+ const std::vector<std::string> algo_parts = Botan::split_on(cipherName, '/');
+ const std::string cipher_name = algo_parts[0];
+ Botan::BlockCipherModePaddingMethod* pad;
+ if (algo_parts.size() == 3 && algo_parts[2] == "PKCS7")
+ {
+ pad = new Botan::PKCS7_Padding();
+ }
+ else
+ {
+ pad = new Botan::Null_Padding();
+ }
+ std::unique_ptr<Botan::BlockCipher> bc(Botan::BlockCipher::create(cipher_name));
+ Botan::Keyed_Filter* cipher = new Botan::Cipher_Mode_Filter(new Botan::ECB_Decryption(bc.release(),pad));
+ cipher->set_key(botanKey);
+ cryption = new Botan::Pipe(cipher);
+#else
+ cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, Botan::DECRYPTION));
+#endif
+ }
+#ifdef WITH_AES_GCM
+ else if (mode == SymMode::GCM)
+ {
+ Botan::AEAD_Mode* aead = Botan::get_aead(cipherName, Botan::DECRYPTION);
+ aead->set_key(botanKey);
+ aead->set_associated_data(aad.const_byte_str(), aad.size());
+
+ Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size());
+ Botan::Keyed_Filter* filter = new Botan::Cipher_Mode_Filter(aead);
+ filter->set_iv(botanIV);
+ cryption = new Botan::Pipe(filter);
+ }
+#endif
+ else
+ {
+ Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size());
+ cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, botanIV, Botan::DECRYPTION));
+ }
+ cryption->start_msg();
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to create the decryption token");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ return true;
+}
+
+bool BotanSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& data)
+{
+ if (!SymmetricAlgorithm::decryptUpdate(encryptedData, data))
+ {
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // AEAD ciphers should not return decrypted data until final is called
+ if (currentCipherMode == SymMode::GCM)
+ {
+ data.resize(0);
+ return true;
+ }
+
+ // Write data
+ try
+ {
+ if (encryptedData.size() > 0)
+ cryption->write(encryptedData.const_byte_str(), encryptedData.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to write to the decryption token");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Count number of bytes written
+ if (maximumBytes.is_positive())
+ {
+ counterBytes += encryptedData.size();
+ }
+
+ // Read data
+ int bytesRead = 0;
+ try
+ {
+ size_t outLen = cryption->remaining();
+ data.resize(outLen);
+ if (outLen > 0)
+ bytesRead = cryption->read(&data[0], outLen);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to decrypt the data");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Resize the output block
+ data.resize(bytesRead);
+ currentBufferSize -= bytesRead;
+
+ return true;
+}
+
+bool BotanSymmetricAlgorithm::decryptFinal(ByteString& data)
+{
+ SymMode::Type mode = currentCipherMode;
+ ByteString aeadBuffer = currentAEADBuffer;
+
+ if (!SymmetricAlgorithm::decryptFinal(data))
+ {
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ if (mode == SymMode::GCM)
+ {
+ // Write data
+ try
+ {
+ if (aeadBuffer.size() > 0)
+ cryption->write(aeadBuffer.const_byte_str(), aeadBuffer.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to write to the decryption token");
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+ }
+
+ // Read data
+ int bytesRead = 0;
+ try
+ {
+ cryption->end_msg();
+ size_t outLen = cryption->remaining();
+ data.resize(outLen);
+ if (outLen > 0)
+ bytesRead = cryption->read(&data[0], outLen);
+ }
+ catch (std::exception &e)
+ {
+ ERROR_MSG("Failed to decrypt the data: %s", e.what());
+
+ delete cryption;
+ cryption = NULL;
+
+ return false;
+ }
+
+ // Clean up
+ delete cryption;
+ cryption = NULL;
+
+ // Resize the output block
+ data.resize(bytesRead);
+
+ return true;
+}
+
+// Check if more bytes of data can be encrypted
+bool BotanSymmetricAlgorithm::checkMaximumBytes(unsigned long bytes)
+{
+ if (maximumBytes.is_negative()) return true;
+
+ if (maximumBytes.cmp(counterBytes + bytes) >= 0) return true;
+
+ return false;
+}
diff --git a/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.h
new file mode 100644
index 0000000..3031094
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanSymmetricAlgorithm.h
+
+ Botan symmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H
+#define _SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H
+
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "SymmetricAlgorithm.h"
+
+#include <botan/pipe.h>
+#include <botan/bigint.h>
+
+class BotanSymmetricAlgorithm : public SymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanSymmetricAlgorithm();
+
+ // Destructor
+ virtual ~BotanSymmetricAlgorithm();
+
+ // Encryption functions
+ virtual bool encryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0);
+ virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData);
+ virtual bool encryptFinal(ByteString& encryptedData);
+
+ // Decryption functions
+ virtual bool decryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0);
+ virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data);
+ virtual bool decryptFinal(ByteString& data);
+
+ // Return the block size
+ virtual size_t getBlockSize() const = 0;
+
+ // Check if more bytes of data can be encrypted
+ virtual bool checkMaximumBytes(unsigned long bytes);
+
+protected:
+ // Return the right cipher for the operation
+ virtual std::string getCipher() const = 0;
+
+private:
+ // The current context
+ Botan::Pipe* cryption;
+
+ // The maximum bytes to encrypt/decrypt
+ Botan::BigInt maximumBytes;
+ Botan::BigInt counterBytes;
+};
+
+#endif // !_SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanUtil.cpp b/SoftHSMv2/src/lib/crypto/BotanUtil.cpp
new file mode 100644
index 0000000..e5da460
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanUtil.cpp
@@ -0,0 +1,146 @@
+ /*
+ * Copyright (c) .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanUtil.h
+
+ Botan convenience functions
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanUtil.h"
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/asn1_obj.h>
+#include <botan/version.h>
+
+// Convert a Botan BigInt to a ByteString
+ByteString BotanUtil::bigInt2ByteString(const Botan::BigInt& bigInt)
+{
+ ByteString rv;
+
+ rv.resize(bigInt.bytes());
+ bigInt.binary_encode(&rv[0]);
+
+ return rv;
+}
+
+// Used when extracting little-endian data
+ByteString BotanUtil::bigInt2ByteStringPrefix(const Botan::BigInt& bigInt, size_t size)
+{
+ ByteString rv;
+
+ if (size > bigInt.bytes())
+ {
+ size_t diff = size - bigInt.bytes();
+ rv.resize(size);
+
+ memset(&rv[0], '\0', diff);
+
+ bigInt.binary_encode(&rv[0] + diff);
+ }
+ else
+ {
+ rv.resize(bigInt.bytes());
+ bigInt.binary_encode(&rv[0]);
+ }
+
+ return rv;
+}
+
+// Convert a ByteString to an Botan BigInt
+Botan::BigInt BotanUtil::byteString2bigInt(const ByteString& byteString)
+{
+ return Botan::BigInt(byteString.const_byte_str(), byteString.size());
+}
+
+#if defined(WITH_ECC) || defined(WITH_GOST)
+// Convert a Botan EC group to a ByteString
+ByteString BotanUtil::ecGroup2ByteString(const Botan::EC_Group& ecGroup)
+{
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> der = ecGroup.DER_encode(Botan::EC_DOMPAR_ENC_OID);
+#else
+ Botan::SecureVector<Botan::byte> der = ecGroup.DER_encode(Botan::EC_DOMPAR_ENC_OID);
+#endif
+ return ByteString(&der[0], der.size());
+}
+
+// Convert a ByteString to a Botan EC group
+Botan::EC_Group BotanUtil::byteString2ECGroup(const ByteString& byteString)
+{
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> der(byteString.size());
+ memcpy(&der[0], byteString.const_byte_str(), byteString.size());
+ return Botan::EC_Group(der);
+#else
+ return Botan::EC_Group(Botan::MemoryVector<Botan::byte>(byteString.const_byte_str(), byteString.size()));
+#endif
+}
+
+// Convert a Botan EC point to a ByteString
+ByteString BotanUtil::ecPoint2ByteString(const Botan::PointGFp& ecPoint)
+{
+ ByteString point;
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> repr = Botan::EC2OSP(ecPoint, Botan::PointGFp::UNCOMPRESSED);
+ Botan::secure_vector<Botan::byte> der;
+#else
+ Botan::SecureVector<Botan::byte> repr = Botan::EC2OSP(ecPoint, Botan::PointGFp::UNCOMPRESSED);
+ Botan::SecureVector<Botan::byte> der;
+#endif
+
+
+ der = Botan::DER_Encoder()
+ .encode(repr, Botan::OCTET_STRING)
+ .get_contents();
+ point.resize(der.size());
+ memcpy(&point[0], &der[0], der.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Can't convert from EC point");
+ }
+ return point;
+}
+
+// Convert a ByteString to a Botan EC point
+Botan::PointGFp BotanUtil::byteString2ECPoint(const ByteString& byteString, const Botan::EC_Group& ecGroup)
+{
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> repr;
+#else
+ Botan::SecureVector<Botan::byte> repr;
+#endif
+ Botan::BER_Decoder(byteString.const_byte_str(), byteString.size())
+ .decode(repr, Botan::OCTET_STRING)
+ .verify_end();
+ return Botan::OS2ECP(&repr[0], repr.size(), ecGroup.get_curve());
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanUtil.h b/SoftHSMv2/src/lib/crypto/BotanUtil.h
new file mode 100644
index 0000000..67f6ca6
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanUtil.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanUtil.h
+
+ Botan convenience functions
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANUTIL_H
+#define _SOFTHSM_V2_BOTANUTIL_H
+
+#include "config.h"
+#include "ByteString.h"
+#include <botan/bigint.h>
+#if defined(WITH_ECC) || defined(WITH_GOST)
+#include <botan/ec_group.h>
+#endif
+
+namespace BotanUtil
+{
+ // Convert a Botan BigInt to a ByteString
+ ByteString bigInt2ByteString(const Botan::BigInt& bigInt);
+ ByteString bigInt2ByteStringPrefix(const Botan::BigInt& bigInt, size_t size);
+
+ // Convert a ByteString to a Botan BigInt
+ Botan::BigInt byteString2bigInt(const ByteString& byteString);
+
+#if defined(WITH_ECC) || defined(WITH_GOST)
+ // Convert a Botan EC group to a ByteString
+ ByteString ecGroup2ByteString(const Botan::EC_Group& ecGroup);
+
+ // Convert a ByteString to a Botan EC group
+ Botan::EC_Group byteString2ECGroup(const ByteString& byteString);
+
+ // Convert a Botan EC point to a ByteString
+ ByteString ecPoint2ByteString(const Botan::PointGFp& ecPoint);
+
+ // Convert a ByteString to a Botan EC point in the given EC group
+ Botan::PointGFp byteString2ECPoint(const ByteString& byteString, const Botan::EC_Group& ecGroup);
+#endif
+}
+
+#endif // !_SOFTHSM_V2_BOTANUTIL_H
+
diff --git a/SoftHSMv2/src/lib/crypto/Botan_ecb.cpp b/SoftHSMv2/src/lib/crypto/Botan_ecb.cpp
new file mode 100644
index 0000000..f27276e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/Botan_ecb.cpp
@@ -0,0 +1,153 @@
+/*
+* ECB Mode
+* (C) 1999-2009,2013 Jack Lloyd
+* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/version.h>
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+// ECB cipher mode was dropped in Botan 2.0.0
+// so including this code in SoftHSM for continued support
+// for e.g. CKA_VALUE_CHECK
+
+#include "Botan_ecb.h"
+#include "Botan_rounding.h"
+
+namespace Botan {
+
+ECB_Mode::ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
+ m_cipher(cipher),
+ m_padding(padding)
+ {
+ if(!m_padding->valid_blocksize(cipher->block_size()))
+ throw Invalid_Argument("Padding " + m_padding->name() +
+ " cannot be used with " +
+ cipher->name() + "/ECB");
+ }
+
+void ECB_Mode::clear()
+ {
+ m_cipher->clear();
+ }
+
+void ECB_Mode::reset()
+ {
+ // no msg state here
+ return;
+ }
+
+std::string ECB_Mode::name() const
+ {
+ return cipher().name() + "/ECB/" + padding().name();
+ }
+
+size_t ECB_Mode::update_granularity() const
+ {
+ return cipher().parallel_bytes();
+ }
+
+Key_Length_Specification ECB_Mode::key_spec() const
+ {
+ return cipher().key_spec();
+ }
+
+size_t ECB_Mode::default_nonce_length() const
+ {
+ return 0;
+ }
+
+bool ECB_Mode::valid_nonce_length(size_t n) const
+ {
+ return (n == 0);
+ }
+
+void ECB_Mode::key_schedule(const byte key[], size_t length)
+ {
+ m_cipher->set_key(key, length);
+ }
+
+void ECB_Mode::start_msg(const byte[], size_t nonce_len)
+ {
+ if(nonce_len != 0)
+ throw Invalid_IV_Length(name(), nonce_len);
+ }
+
+size_t ECB_Encryption::minimum_final_size() const
+ {
+ return 0;
+ }
+
+size_t ECB_Encryption::output_length(size_t input_length) const
+ {
+ if(input_length == 0)
+ return cipher().block_size();
+ else
+ return round_up(input_length, cipher().block_size());
+ }
+
+size_t ECB_Encryption::process(uint8_t buf[], size_t sz)
+ {
+ const size_t BS = cipher().block_size();
+ BOTAN_ASSERT(sz % BS == 0, "ECB input is full blocks");
+ const size_t blocks = sz / BS;
+ cipher().encrypt_n(buf, buf, blocks);
+ return sz;
+ }
+
+void ECB_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
+ {
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+
+ const size_t BS = cipher().block_size();
+
+ const size_t bytes_in_final_block = sz % BS;
+
+ padding().add_padding(buffer, bytes_in_final_block, BS);
+
+ if(buffer.size() % BS)
+ throw Exception("Did not pad to full block size in " + name());
+
+ update(buffer, offset);
+ }
+
+size_t ECB_Decryption::output_length(size_t input_length) const
+ {
+ return input_length;
+ }
+
+size_t ECB_Decryption::minimum_final_size() const
+ {
+ return cipher().block_size();
+ }
+
+size_t ECB_Decryption::process(uint8_t buf[], size_t sz)
+ {
+ const size_t BS = cipher().block_size();
+ BOTAN_ASSERT(sz % BS == 0, "Input is full blocks");
+ size_t blocks = sz / BS;
+ cipher().decrypt_n(buf, buf, blocks);
+ return sz;
+ }
+
+void ECB_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
+ {
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+
+ const size_t BS = cipher().block_size();
+
+ if(sz == 0 || sz % BS)
+ throw Decoding_Error(name() + ": Ciphertext not a multiple of block size");
+
+ update(buffer, offset);
+
+ const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS);
+ buffer.resize(buffer.size() - pad_bytes); // remove padding
+ }
+
+}
+
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/Botan_ecb.h b/SoftHSMv2/src/lib/crypto/Botan_ecb.h
new file mode 100644
index 0000000..1712083
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/Botan_ecb.h
@@ -0,0 +1,107 @@
+/*
+* ECB Mode
+* (C) 1999-2009,2013 Jack Lloyd
+* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_MODE_ECB_H__
+#define BOTAN_MODE_ECB_H__
+
+#include <botan/version.h>
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+// ECB cipher mode was dropped in Botan 2.0.0
+// so including this code in SoftHSM for continued support
+// for e.g. CKA_VALUE_CHECK
+
+#include <botan/cipher_mode.h>
+#include <botan/block_cipher.h>
+#include <botan/mode_pad.h>
+
+namespace Botan {
+
+/**
+* ECB mode
+*/
+class BOTAN_DLL ECB_Mode : public Cipher_Mode
+ {
+ public:
+ std::string name() const override;
+
+ size_t update_granularity() const override;
+
+ Key_Length_Specification key_spec() const override;
+
+ size_t default_nonce_length() const override;
+
+ bool valid_nonce_length(size_t n) const override;
+
+ void clear() override;
+
+ void reset() override;
+
+ protected:
+ ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding);
+
+ const BlockCipher& cipher() const { return *m_cipher; }
+
+ const BlockCipherModePaddingMethod& padding() const { return *m_padding; }
+
+ private:
+ void start_msg(const byte nonce[], size_t nonce_len) override;
+ void key_schedule(const byte key[], size_t length) override;
+
+ std::unique_ptr<BlockCipher> m_cipher;
+ std::unique_ptr<BlockCipherModePaddingMethod> m_padding;
+ };
+
+/**
+* ECB Encryption
+*/
+class BOTAN_DLL ECB_Encryption final : public ECB_Mode
+ {
+ public:
+ /**
+ * @param cipher block cipher to use
+ * @param padding padding method to use
+ */
+ ECB_Encryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
+ ECB_Mode(cipher, padding) {}
+
+ size_t process(uint8_t buf[], size_t size) override;
+
+ void finish(secure_vector<byte>& final_block, size_t offset = 0) override;
+
+ size_t output_length(size_t input_length) const override;
+
+ size_t minimum_final_size() const override;
+ };
+
+/**
+* ECB Decryption
+*/
+class BOTAN_DLL ECB_Decryption final : public ECB_Mode
+ {
+ public:
+ /**
+ * @param cipher block cipher to use
+ * @param padding padding method to use
+ */
+ ECB_Decryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
+ ECB_Mode(cipher, padding) {}
+
+ size_t process(uint8_t buf[], size_t size) override;
+
+ void finish(secure_vector<byte>& final_block, size_t offset = 0) override;
+
+ size_t output_length(size_t input_length) const override;
+
+ size_t minimum_final_size() const override;
+ };
+
+}
+
+#endif
+
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/Botan_rounding.h b/SoftHSMv2/src/lib/crypto/Botan_rounding.h
new file mode 100644
index 0000000..fbad3ae
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/Botan_rounding.h
@@ -0,0 +1,68 @@
+/*
+* Integer Rounding Functions
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ROUNDING_H__
+#define BOTAN_ROUNDING_H__
+
+#include <botan/version.h>
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)
+// ECB cipher mode was dropped in Botan 2.0.0
+// so including this code in SoftHSM for continued support
+// for e.g. CKA_VALUE_CHECK
+
+#include <botan/types.h>
+#include <botan/assert.h>
+
+namespace Botan {
+
+/**
+* Round up
+* @param n a non-negative integer
+* @param align_to the alignment boundary
+* @return n rounded up to a multiple of align_to
+*/
+inline size_t round_up(size_t n, size_t align_to)
+ {
+ BOTAN_ASSERT(align_to != 0, "align_to must not be 0");
+
+ if(n % align_to)
+ n += align_to - (n % align_to);
+ return n;
+ }
+
+/**
+* Round down
+* @param n an integer
+* @param align_to the alignment boundary
+* @return n rounded down to a multiple of align_to
+*/
+template<typename T>
+inline T round_down(T n, T align_to)
+ {
+ if(align_to == 0)
+ return n;
+
+ return (n - (n % align_to));
+ }
+
+/**
+* Clamp
+*/
+inline size_t clamp(size_t n, size_t lower_bound, size_t upper_bound)
+ {
+ if(n < lower_bound)
+ return lower_bound;
+ if(n > upper_bound)
+ return upper_bound;
+ return n;
+ }
+
+}
+
+#endif
+
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/CryptoFactory.cpp b/SoftHSMv2/src/lib/crypto/CryptoFactory.cpp
new file mode 100644
index 0000000..c676676
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/CryptoFactory.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ CryptoFactory.cpp
+
+ This class is a factory for all cryptographic algorithm implementations. It
+ is an abstract base class for a factory that produces cryptographic library
+ specific implementations of cryptographic algorithms.
+ *****************************************************************************/
+
+#include "config.h"
+#include "CryptoFactory.h"
+
+#if defined(WITH_OPENSSL)
+
+#include "OSSLCryptoFactory.h"
+
+// Return the one-and-only instance
+CryptoFactory* CryptoFactory::i()
+{
+ return OSSLCryptoFactory::i();
+}
+
+// This will destroy the one-and-only instance.
+void CryptoFactory::reset()
+{
+ OSSLCryptoFactory::reset();
+}
+
+#elif defined(WITH_BOTAN)
+
+#include "BotanCryptoFactory.h"
+
+// Return the one-and-only instance
+CryptoFactory* CryptoFactory::i()
+{
+ return BotanCryptoFactory::i();
+}
+
+// This will destroy the one-and-only instance.
+void CryptoFactory::reset()
+{
+ BotanCryptoFactory::reset();
+}
+
+#else
+
+#error "You must configure a cryptographic library to use"
+
+#endif
+
+// Recycle a symmetric algorithm instance -- override this function in the derived
+// class if you need to perform specific clean-up
+void CryptoFactory::recycleSymmetricAlgorithm(SymmetricAlgorithm* toRecycle)
+{
+ delete toRecycle;
+}
+
+// Recycle an asymmetric algorithm instance -- override this function in the derived
+// class if you need to perform specific clean-up
+void CryptoFactory::recycleAsymmetricAlgorithm(AsymmetricAlgorithm* toRecycle)
+{
+ delete toRecycle;
+}
+
+// Recycle a hash algorithm instance -- override this function in the derived
+// class if you need to perform specific clean-up
+void CryptoFactory::recycleHashAlgorithm(HashAlgorithm* toRecycle)
+{
+ delete toRecycle;
+}
+
+// Recycle a MAC algorithm instance -- override this function in the derived
+// class if you need to perform specific clean-up
+void CryptoFactory::recycleMacAlgorithm(MacAlgorithm* toRecycle)
+{
+ delete toRecycle;
+}
diff --git a/SoftHSMv2/src/lib/crypto/CryptoFactory.h b/SoftHSMv2/src/lib/crypto/CryptoFactory.h
new file mode 100644
index 0000000..761e473
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/CryptoFactory.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ CryptoFactory.h
+
+ This class is a factory for all cryptographic algorithm implementations. It
+ is an abstract base class for a factory that produces cryptographic library
+ specific implementations of cryptographic algorithms.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_CRYPTOFACTORY_H
+#define _SOFTHSM_V2_CRYPTOFACTORY_H
+
+#include "config.h"
+#include "SymmetricAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include "MacAlgorithm.h"
+#include "RNG.h"
+
+class CryptoFactory
+{
+public:
+ // Return the one-and-only instance
+ static CryptoFactory* i();
+
+ // This will destroy the one-and-only instance.
+ static void reset();
+
+#ifdef WITH_FIPS
+ // Return the FIPS 140-2 selftest status
+ virtual bool getFipsSelfTestStatus() const = 0;
+#endif
+
+ // Create a concrete instance of a symmetric algorithm
+ virtual SymmetricAlgorithm* getSymmetricAlgorithm(SymAlgo::Type algorithm) = 0;
+
+ // Recycle a symmetric algorithm instance -- override this function in the derived
+ // class if you need to perform specific clean-up
+ virtual void recycleSymmetricAlgorithm(SymmetricAlgorithm* toRecycle);
+
+ // Create a concrete instance of an asymmetric algorithm
+ virtual AsymmetricAlgorithm* getAsymmetricAlgorithm(AsymAlgo::Type algorithm) = 0;
+
+ // Recycle an asymmetric algorithm instance -- override this function in the derived
+ // class if you need to perform specific clean-up
+ virtual void recycleAsymmetricAlgorithm(AsymmetricAlgorithm* toRecycle);
+
+ // Create a concrete instance of a hash algorithm
+ virtual HashAlgorithm* getHashAlgorithm(HashAlgo::Type algorithm) = 0;
+
+ // Recycle a hash algorithm instance -- override this function in the derived
+ // class if you need to perform specific clean-up
+ virtual void recycleHashAlgorithm(HashAlgorithm* toRecycle);
+
+ // Create a concrete instance of a MAC algorithm
+ virtual MacAlgorithm* getMacAlgorithm(MacAlgo::Type algorithm) = 0;
+
+ // Recycle a MAC algorithm instance -- override this function in the derived
+ // class if you need to perform specific clean-up
+ virtual void recycleMacAlgorithm(MacAlgorithm* toRecycle);
+
+ // Get the global RNG (may be an unique RNG per thread)
+ virtual RNG* getRNG(RNGImpl::Type name = RNGImpl::Default) = 0;
+
+ // Destructor
+ virtual ~CryptoFactory() { }
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_CRYPTOFACTORY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/DESKey.cpp b/SoftHSMv2/src/lib/crypto/DESKey.cpp
new file mode 100644
index 0000000..1d5f9bc
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DESKey.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DESKey.cpp
+
+ DES key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include "DESKey.h"
+#include "CryptoFactory.h"
+
+// Set the key
+bool DESKey::setKeyBits(const ByteString& keybits)
+{
+ if (bitLen > 0)
+ {
+ // Check if the correct input data is supplied
+ size_t expectedLen = 0;
+
+ switch(bitLen)
+ {
+ case 56:
+ expectedLen = 8;
+ break;
+ case 112:
+ expectedLen = 16;
+ break;
+ case 168:
+ expectedLen = 24;
+ break;
+ };
+
+ // Check the length
+ if (keybits.size() != expectedLen)
+ {
+ return false;
+ }
+ }
+
+ keyData = keybits;
+
+ return true;
+}
+
+// Get key check value
+ByteString DESKey::getKeyCheckValue() const
+{
+ SymAlgo::Type algo = SymAlgo::Unknown;
+ ByteString iv;
+ ByteString data;
+ ByteString encryptedData;
+ ByteString encryptedFinal;
+
+
+ switch (this->getBitLen())
+ {
+ case 56:
+ algo = SymAlgo::DES;
+ break;
+ case 112:
+ case 168:
+ algo = SymAlgo::DES3;
+ break;
+ default:
+ return encryptedData;
+ }
+
+ SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
+ if (cipher == NULL) return encryptedData;
+
+ // Single block of null (0x00) bytes
+ data.resize(cipher->getBlockSize());
+ memset(&data[0], 0, data.size());
+
+ if (!cipher->encryptInit(this, SymMode::ECB, iv, false) ||
+ !cipher->encryptUpdate(data, encryptedData) ||
+ !cipher->encryptFinal(encryptedFinal))
+ {
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+ return encryptedData;
+ }
+ CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
+
+ encryptedData += encryptedFinal;
+ encryptedData.resize(3);
+
+ return encryptedData;
+}
diff --git a/SoftHSMv2/src/lib/crypto/DESKey.h b/SoftHSMv2/src/lib/crypto/DESKey.h
new file mode 100644
index 0000000..895e4fa
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DESKey.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DESKey.h
+
+ Base class for symmetric key classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DESKEY_H
+#define _SOFTHSM_V2_DESKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include "SymmetricKey.h"
+
+class DESKey : public SymmetricKey
+{
+public:
+ // Base constructor
+ DESKey(size_t inBitLen = 0) : SymmetricKey(inBitLen) { }
+
+ // Set the key
+ virtual bool setKeyBits(const ByteString& keybits);
+
+ // Get the key check value
+ virtual ByteString getKeyCheckValue() const;
+};
+
+#endif // !_SOFTHSM_V2_DESKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/DHParameters.cpp b/SoftHSMv2/src/lib/crypto/DHParameters.cpp
new file mode 100644
index 0000000..919901b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DHParameters.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DHParameters.cpp
+
+ Diffie-Hellman parameters (only used for key generation)
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DHParameters.h"
+#include <string.h>
+
+// The type
+/*static*/ const char* DHParameters::type = "Generic DH parameters";
+
+// Set the public prime p
+void DHParameters::setP(const ByteString& inP)
+{
+ p = inP;
+}
+
+// Set the generator g
+void DHParameters::setG(const ByteString& inG)
+{
+ g = inG;
+}
+
+// Set the optional bit length
+void DHParameters::setXBitLength(const size_t inBitLen)
+{
+ bitLen = inBitLen;
+}
+
+
+// Get the public prime p
+const ByteString& DHParameters::getP() const
+{
+ return p;
+}
+
+// Get the generator g
+const ByteString& DHParameters::getG() const
+{
+ return g;
+}
+
+// Get the optional bit length
+size_t DHParameters::getXBitLength() const
+{
+ return bitLen;
+}
+
+// Are the parameters of the given type?
+bool DHParameters::areOfType(const char* inType)
+{
+ return (strcmp(type, inType) == 0);
+}
+
+// Serialisation
+ByteString DHParameters::serialise() const
+{
+ ByteString len(bitLen);
+
+ return p.serialise() + g.serialise() + len.serialise();
+}
+
+bool DHParameters::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+ ByteString dLen = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dG.size() == 0) ||
+ (dLen.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setG(dG);
+ setXBitLength(dLen.long_val());
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/DHParameters.h b/SoftHSMv2/src/lib/crypto/DHParameters.h
new file mode 100644
index 0000000..e0c963f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DHParameters.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DHParameters.h
+
+ Diffie-Hellman parameters (only used for key generation)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DHPARAMETERS_H
+#define _SOFTHSM_V2_DHPARAMETERS_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "AsymmetricParameters.h"
+
+class DHParameters : public AsymmetricParameters
+{
+public:
+ // Base constructors
+ DHParameters() : bitLen(0) { }
+
+ // The type
+ static const char* type;
+
+ // Set the public prime p
+ void setP(const ByteString& inP);
+
+ // Set the generator g
+ void setG(const ByteString& inG);
+
+ // Set the optional bit length
+ void setXBitLength(const size_t inBitLen);
+
+ // Get the public prime p
+ const ByteString& getP() const;
+
+ // Get the generator g
+ const ByteString& getG() const;
+
+ // Get the optional bit length
+ size_t getXBitLength() const;
+
+ // Are the parameters of the given type?
+ virtual bool areOfType(const char* inType);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+private:
+ ByteString p;
+ ByteString g;
+ size_t bitLen;
+};
+
+#endif // !_SOFTHSM_V2_DHPARAMETERS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/DHPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/DHPrivateKey.cpp
new file mode 100644
index 0000000..41103f1
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DHPrivateKey.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DHPrivateKey.cpp
+
+ Diffie-Hellman private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DHPrivateKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* DHPrivateKey::type = "Abstract DH private key";
+
+// Check if the key is of the given type
+bool DHPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long DHPrivateKey::getBitLength() const
+{
+ return getP().bits();
+}
+
+// Get the output length
+unsigned long DHPrivateKey::getOutputLength() const
+{
+ return getP().size();
+}
+
+// Setters for the DH private key components
+void DHPrivateKey::setX(const ByteString& inX)
+{
+ x = inX;
+}
+
+// Setters for the DH public key components
+void DHPrivateKey::setP(const ByteString& inP)
+{
+ p = inP;
+}
+
+void DHPrivateKey::setG(const ByteString& inG)
+{
+ g = inG;
+}
+
+// Getters for the DH private key components
+const ByteString& DHPrivateKey::getX() const
+{
+ return x;
+}
+
+// Getters for the DH public key components
+const ByteString& DHPrivateKey::getP() const
+{
+ return p;
+}
+
+const ByteString& DHPrivateKey::getG() const
+{
+ return g;
+}
+
+// Serialisation
+ByteString DHPrivateKey::serialise() const
+{
+ return p.serialise() +
+ g.serialise() +
+ x.serialise();
+}
+
+bool DHPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+ ByteString dX = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dG.size() == 0) ||
+ (dX.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setG(dG);
+ setX(dX);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/DHPrivateKey.h b/SoftHSMv2/src/lib/crypto/DHPrivateKey.h
new file mode 100644
index 0000000..2c625da
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DHPrivateKey.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DHPrivateKey.h
+
+ Diffie-Hellman private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DHPRIVATEKEY_H
+#define _SOFTHSM_V2_DHPRIVATEKEY_H
+
+#include "config.h"
+#include "PrivateKey.h"
+
+class DHPrivateKey : public PrivateKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the DH private key components
+ virtual void setX(const ByteString& inX);
+
+ // Setters for the DH public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setG(const ByteString& inG);
+
+ // Getters for the DH private key components
+ virtual const ByteString& getX() const;
+
+ // Getters for the DH public key components
+ virtual const ByteString& getP() const;
+ virtual const ByteString& getG() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Private components
+ ByteString x;
+
+ // Public components
+ ByteString p,g;
+};
+
+#endif // !_SOFTHSM_V2_DHPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/DHPublicKey.cpp b/SoftHSMv2/src/lib/crypto/DHPublicKey.cpp
new file mode 100644
index 0000000..17e041d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DHPublicKey.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DHPublicKey.cpp
+
+ Diffie-Hellman public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DHPublicKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* DHPublicKey::type = "Abstract DH public key";
+
+// Check if the key is of the given type
+bool DHPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long DHPublicKey::getBitLength() const
+{
+ return getP().bits();
+}
+
+// Get the output length
+unsigned long DHPublicKey::getOutputLength() const
+{
+ return getP().size();
+}
+
+// Setters for the DH public key components
+void DHPublicKey::setP(const ByteString& inP)
+{
+ p = inP;
+}
+
+void DHPublicKey::setG(const ByteString& inG)
+{
+ g = inG;
+}
+
+void DHPublicKey::setY(const ByteString& inY)
+{
+ y = inY;
+}
+
+// Getters for the DH public key components
+const ByteString& DHPublicKey::getP() const
+{
+ return p;
+}
+
+const ByteString& DHPublicKey::getG() const
+{
+ return g;
+}
+
+const ByteString& DHPublicKey::getY() const
+{
+ return y;
+}
+
+// Serialisation
+ByteString DHPublicKey::serialise() const
+{
+ return p.serialise() +
+ g.serialise() +
+ y.serialise();
+}
+
+bool DHPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+ ByteString dY = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dG.size() == 0) ||
+ (dY.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setG(dG);
+ setY(dY);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/DHPublicKey.h b/SoftHSMv2/src/lib/crypto/DHPublicKey.h
new file mode 100644
index 0000000..a070eb8
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DHPublicKey.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DHPublicKey.h
+
+ Diffie-Hellman public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DHPUBLICKEY_H
+#define _SOFTHSM_V2_DHPUBLICKEY_H
+
+#include "config.h"
+#include "PublicKey.h"
+
+class DHPublicKey : public PublicKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the DH public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setG(const ByteString& inG);
+ virtual void setY(const ByteString& inY);
+
+ // Getters for the DH public key components
+ virtual const ByteString& getP() const;
+ virtual const ByteString& getG() const;
+ virtual const ByteString& getY() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Public components
+ ByteString p,g,y;
+};
+
+#endif // !_SOFTHSM_V2_DHPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/DSAParameters.cpp b/SoftHSMv2/src/lib/crypto/DSAParameters.cpp
new file mode 100644
index 0000000..79ef671
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DSAParameters.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAParameters.cpp
+
+ DSA parameters (only used for key generation)
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DSAParameters.h"
+#include <string.h>
+
+// The type
+/*static*/ const char* DSAParameters::type = "Generic DSA parameters";
+
+// Set the public prime p
+void DSAParameters::setP(const ByteString& inP)
+{
+ p = inP;
+}
+
+// Set the public subprime q
+void DSAParameters::setQ(const ByteString& inQ)
+{
+ q = inQ;
+}
+
+// Set the generator g
+void DSAParameters::setG(const ByteString& inG)
+{
+ g = inG;
+}
+
+// Get the public prime p
+const ByteString& DSAParameters::getP() const
+{
+ return p;
+}
+
+// Get the public subprime q
+const ByteString& DSAParameters::getQ() const
+{
+ return q;
+}
+
+// Get the generator g
+const ByteString& DSAParameters::getG() const
+{
+ return g;
+}
+
+// Are the parameters of the given type?
+bool DSAParameters::areOfType(const char* inType)
+{
+ return (strcmp(type, inType) == 0);
+}
+
+// Serialisation
+ByteString DSAParameters::serialise() const
+{
+ return p.serialise() + q.serialise() + g.serialise();
+}
+
+bool DSAParameters::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dQ.size() == 0) ||
+ (dG.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setQ(dQ);
+ setG(dG);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/DSAParameters.h b/SoftHSMv2/src/lib/crypto/DSAParameters.h
new file mode 100644
index 0000000..978bc09
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DSAParameters.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAParameters.h
+
+ DSA parameters (only used for key generation)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DSAPARAMETERS_H
+#define _SOFTHSM_V2_DSAPARAMETERS_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "AsymmetricParameters.h"
+
+class DSAParameters : public AsymmetricParameters
+{
+public:
+ // The type
+ static const char* type;
+
+ // Set the public prime p
+ void setP(const ByteString& inP);
+
+ // Set the public subprime q
+ void setQ(const ByteString& inQ);
+
+ // Set the generator g
+ void setG(const ByteString& inG);
+
+ // Get the public prime p
+ const ByteString& getP() const;
+
+ // Get the public subprime q
+ const ByteString& getQ() const;
+
+ // Get the generator g
+ const ByteString& getG() const;
+
+ // Are the parameters of the given type?
+ virtual bool areOfType(const char* inType);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+private:
+ ByteString p;
+ ByteString q;
+ ByteString g;
+};
+
+#endif // !_SOFTHSM_V2_DSAPARAMETERS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/DSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/DSAPrivateKey.cpp
new file mode 100644
index 0000000..1bdfd2d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DSAPrivateKey.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAPrivateKey.cpp
+
+ DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DSAPrivateKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* DSAPrivateKey::type = "Abstract DSA private key";
+
+// Check if the key is of the given type
+bool DSAPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long DSAPrivateKey::getBitLength() const
+{
+ return getP().bits();
+}
+
+// Get the output length
+unsigned long DSAPrivateKey::getOutputLength() const
+{
+ return getQ().size() * 2;
+}
+
+// Setters for the DSA private key components
+void DSAPrivateKey::setX(const ByteString& inX)
+{
+ x = inX;
+}
+
+// Setters for the DSA domain parameters
+void DSAPrivateKey::setP(const ByteString& inP)
+{
+ p = inP;
+}
+
+void DSAPrivateKey::setQ(const ByteString& inQ)
+{
+ q = inQ;
+}
+
+void DSAPrivateKey::setG(const ByteString& inG)
+{
+ g = inG;
+}
+
+// Getters for the DSA private key components
+const ByteString& DSAPrivateKey::getX() const
+{
+ return x;
+}
+
+// Getters for the DSA domain parameters
+const ByteString& DSAPrivateKey::getP() const
+{
+ return p;
+}
+
+const ByteString& DSAPrivateKey::getQ() const
+{
+ return q;
+}
+
+const ByteString& DSAPrivateKey::getG() const
+{
+ return g;
+}
+
+// Serialisation
+ByteString DSAPrivateKey::serialise() const
+{
+ return p.serialise() +
+ q.serialise() +
+ g.serialise() +
+ x.serialise();
+}
+
+bool DSAPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+ ByteString dX = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dQ.size() == 0) ||
+ (dG.size() == 0) ||
+ (dX.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setQ(dQ);
+ setG(dG);
+ setX(dX);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/DSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/DSAPrivateKey.h
new file mode 100644
index 0000000..3b2070f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DSAPrivateKey.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAPrivateKey.h
+
+ DSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DSAPRIVATEKEY_H
+#define _SOFTHSM_V2_DSAPRIVATEKEY_H
+
+#include "config.h"
+#include "PrivateKey.h"
+
+class DSAPrivateKey : public PrivateKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the DSA private key components
+ virtual void setX(const ByteString& inX);
+
+ // Setters for the DSA domain parameters
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setG(const ByteString& inG);
+
+ // Getters for the DSA private key components
+ virtual const ByteString& getX() const;
+
+ // Getters for the DSA domain parameters
+ virtual const ByteString& getP() const;
+ virtual const ByteString& getQ() const;
+ virtual const ByteString& getG() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Private components
+ ByteString x;
+
+ // Domain parameters
+ ByteString p,q,g;
+};
+
+#endif // !_SOFTHSM_V2_DSAPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/DSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/DSAPublicKey.cpp
new file mode 100644
index 0000000..4439bdd
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DSAPublicKey.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAPublicKey.cpp
+
+ DSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "DSAPublicKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* DSAPublicKey::type = "Abstract DSA public key";
+
+// Check if the key is of the given type
+bool DSAPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long DSAPublicKey::getBitLength() const
+{
+ return getP().bits();
+}
+
+// Get the output length
+unsigned long DSAPublicKey::getOutputLength() const
+{
+ return getQ().size() * 2;
+}
+
+// Setters for the DSA public key components
+void DSAPublicKey::setP(const ByteString& inP)
+{
+ p = inP;
+}
+
+void DSAPublicKey::setQ(const ByteString& inQ)
+{
+ q = inQ;
+}
+
+void DSAPublicKey::setG(const ByteString& inG)
+{
+ g = inG;
+}
+
+void DSAPublicKey::setY(const ByteString& inY)
+{
+ y = inY;
+}
+
+// Getters for the DSA public key components
+const ByteString& DSAPublicKey::getP() const
+{
+ return p;
+}
+
+const ByteString& DSAPublicKey::getQ() const
+{
+ return q;
+}
+
+const ByteString& DSAPublicKey::getG() const
+{
+ return g;
+}
+
+const ByteString& DSAPublicKey::getY() const
+{
+ return y;
+}
+
+// Serialisation
+ByteString DSAPublicKey::serialise() const
+{
+ return p.serialise() +
+ q.serialise() +
+ g.serialise() +
+ y.serialise();
+}
+
+bool DSAPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+ ByteString dG = ByteString::chainDeserialise(serialised);
+ ByteString dY = ByteString::chainDeserialise(serialised);
+
+ if ((dP.size() == 0) ||
+ (dQ.size() == 0) ||
+ (dG.size() == 0) ||
+ (dY.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setQ(dQ);
+ setG(dG);
+ setY(dY);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/DSAPublicKey.h b/SoftHSMv2/src/lib/crypto/DSAPublicKey.h
new file mode 100644
index 0000000..6d41e5d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DSAPublicKey.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSAPublicKey.h
+
+ DSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DSAPUBLICKEY_H
+#define _SOFTHSM_V2_DSAPUBLICKEY_H
+
+#include "config.h"
+#include "PublicKey.h"
+
+class DSAPublicKey : public PublicKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setG(const ByteString& inG);
+ virtual void setY(const ByteString& inY);
+
+ // Getters for the DSA public key components
+ virtual const ByteString& getP() const;
+ virtual const ByteString& getQ() const;
+ virtual const ByteString& getG() const;
+ virtual const ByteString& getY() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Public components
+ ByteString p,q,g,y;
+};
+
+#endif // !_SOFTHSM_V2_DSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/ECParameters.cpp b/SoftHSMv2/src/lib/crypto/ECParameters.cpp
new file mode 100644
index 0000000..c4a6cfa
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/ECParameters.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECParameters.cpp
+
+ Elliptic Curve parameters (only used for key generation)
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "ECParameters.h"
+#include <string.h>
+
+// The type
+/*static*/ const char* ECParameters::type = "Generic EC parameters";
+
+// Set the curve OID ec
+void ECParameters::setEC(const ByteString& inEC)
+{
+ ec = inEC;
+}
+
+// Get the curve OID ec
+const ByteString& ECParameters::getEC() const
+{
+ return ec;
+}
+
+// Are the parameters of the given type?
+bool ECParameters::areOfType(const char* inType)
+{
+ return (strcmp(type, inType) == 0);
+}
+
+// Serialisation
+ByteString ECParameters::serialise() const
+{
+ return ec.serialise();
+}
+
+bool ECParameters::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+
+ if (dEC.size() == 0)
+ {
+ return false;
+ }
+
+ setEC(dEC);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/ECParameters.h b/SoftHSMv2/src/lib/crypto/ECParameters.h
new file mode 100644
index 0000000..76ca3e8
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/ECParameters.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECParameters.h
+
+ Elliptic Curve parameters (only used for key generation)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ECPARAMETERS_H
+#define _SOFTHSM_V2_ECPARAMETERS_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "AsymmetricParameters.h"
+
+class ECParameters : public AsymmetricParameters
+{
+public:
+ // The type
+ static const char* type;
+
+ // Set the curve OID ec
+ void setEC(const ByteString& inEC);
+
+ // Get the curve OID ec
+ const ByteString& getEC() const;
+
+ // Are the parameters of the given type?
+ virtual bool areOfType(const char* inType);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+private:
+ ByteString ec;
+};
+
+#endif // !_SOFTHSM_V2_ECPARAMETERS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/ECPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/ECPrivateKey.cpp
new file mode 100644
index 0000000..f132f2e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/ECPrivateKey.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECPrivateKey.cpp
+
+ Elliptic Curve private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "ECPrivateKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* ECPrivateKey::type = "Abstract EC private key";
+
+// Check if the key is of the given type
+bool ECPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long ECPrivateKey::getBitLength() const
+{
+ return getD().bits();
+}
+
+// Get the output length
+unsigned long ECPrivateKey::getOutputLength() const
+{
+ return getOrderLength() * 2;
+}
+
+// Setters for the EC private key components
+void ECPrivateKey::setD(const ByteString& inD)
+{
+ d = inD;
+}
+
+// Setters for the EC public key components
+void ECPrivateKey::setEC(const ByteString& inEC)
+{
+ ec = inEC;
+}
+
+// Getters for the EC private key components
+const ByteString& ECPrivateKey::getD() const
+{
+ return d;
+}
+
+// Getters for the EC public key components
+const ByteString& ECPrivateKey::getEC() const
+{
+ return ec;
+}
+
+// Serialisation
+ByteString ECPrivateKey::serialise() const
+{
+ return ec.serialise() +
+ d.serialise();
+}
+
+bool ECPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+ ByteString dD = ByteString::chainDeserialise(serialised);
+
+ if ((dEC.size() == 0) ||
+ (dD.size() == 0))
+ {
+ return false;
+ }
+
+ setEC(dEC);
+ setD(dD);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/ECPrivateKey.h b/SoftHSMv2/src/lib/crypto/ECPrivateKey.h
new file mode 100644
index 0000000..0814181
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/ECPrivateKey.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECPrivateKey.h
+
+ Elliptic Curve private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ECPRIVATEKEY_H
+#define _SOFTHSM_V2_ECPRIVATEKEY_H
+
+#include "config.h"
+#include "PrivateKey.h"
+
+class ECPrivateKey : public PrivateKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const = 0;
+
+ // Setters for the EC private key components
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the EC public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Getters for the EC private key components
+ virtual const ByteString& getD() const;
+
+ // Getters for the EC public key components
+ virtual const ByteString& getEC() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Private components
+ ByteString d;
+
+ // Public components
+ ByteString ec;
+};
+
+#endif // !_SOFTHSM_V2_ECPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/ECPublicKey.cpp b/SoftHSMv2/src/lib/crypto/ECPublicKey.cpp
new file mode 100644
index 0000000..a92d137
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/ECPublicKey.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECPublicKey.cpp
+
+ Elliptic Curve public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "ECPublicKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* ECPublicKey::type = "Abstract EC public key";
+
+// Check if the key is of the given type
+bool ECPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long ECPublicKey::getBitLength() const
+{
+ return getQ().size() * 8;
+}
+
+// Get the output length
+unsigned long ECPublicKey::getOutputLength() const
+{
+ return getOrderLength() * 2;
+}
+
+// Setters for the EC public key components
+void ECPublicKey::setEC(const ByteString& inEC)
+{
+ ec = inEC;
+}
+
+void ECPublicKey::setQ(const ByteString& inQ)
+{
+ q = inQ;
+}
+
+// Getters for the EC public key components
+const ByteString& ECPublicKey::getEC() const
+{
+ return ec;
+}
+
+const ByteString& ECPublicKey::getQ() const
+{
+ return q;
+}
+
+// Serialisation
+ByteString ECPublicKey::serialise() const
+{
+ return ec.serialise() +
+ q.serialise();
+}
+
+bool ECPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+
+ if ((dEC.size() == 0) ||
+ (dQ.size() == 0))
+ {
+ return false;
+ }
+
+ setEC(dEC);
+ setQ(dQ);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/ECPublicKey.h b/SoftHSMv2/src/lib/crypto/ECPublicKey.h
new file mode 100644
index 0000000..ce6cf63
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/ECPublicKey.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECPublicKey.h
+
+ Elliptic Curve public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ECPUBLICKEY_H
+#define _SOFTHSM_V2_ECPUBLICKEY_H
+
+#include "config.h"
+#include "PublicKey.h"
+
+class ECPublicKey : public PublicKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const = 0;
+
+ // Setters for the EC public key components
+ virtual void setEC(const ByteString& inEc);
+ virtual void setQ(const ByteString& inQ);
+
+ // Getters for the EC public key components
+ virtual const ByteString& getEC() const;
+ virtual const ByteString& getQ() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Public components
+ ByteString ec,q;
+};
+
+#endif // !_SOFTHSM_V2_ECPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.cpp
new file mode 100644
index 0000000..9d23855
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ GOSTPrivateKey.cpp
+
+ GOST R 34.10-2001 private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "GOSTPrivateKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* GOSTPrivateKey::type = "Abstract GOST private key";
+
+// Check if the key is of the given type
+bool GOSTPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long GOSTPrivateKey::getBitLength() const
+{
+ return getD().bits();
+}
+
+// Setters for the GOST private key components
+void GOSTPrivateKey::setD(const ByteString& inD)
+{
+ d = inD;
+}
+
+// Setters for the GOST public key components
+void GOSTPrivateKey::setEC(const ByteString& inEC)
+{
+ ec = inEC;
+}
+
+// Getters for the GOST private key components
+const ByteString& GOSTPrivateKey::getD() const
+{
+ return d;
+}
+
+// Getters for the GOST public key components
+const ByteString& GOSTPrivateKey::getEC() const
+{
+ return ec;
+}
diff --git a/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.h b/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.h
new file mode 100644
index 0000000..929ddb1
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ GOSTPrivateKey.h
+
+ GOST R 34.10-2001 private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_GOSTPRIVATEKEY_H
+#define _SOFTHSM_V2_GOSTPRIVATEKEY_H
+
+#include "config.h"
+#include "PrivateKey.h"
+
+class GOSTPrivateKey : public PrivateKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const = 0;
+
+ // Setters for the GOST private key components
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the GOST public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Getters for the GOST private key components
+ virtual const ByteString& getD() const;
+
+ // Getters for the GOST public key components
+ virtual const ByteString& getEC() const;
+
+ // Serialisation
+ virtual ByteString serialise() const = 0;
+ virtual bool deserialise(ByteString& serialised) = 0;
+
+protected:
+ // Private components
+ ByteString d;
+
+ // Public components
+ ByteString ec;
+};
+
+#endif // !_SOFTHSM_V2_GOSTPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/GOSTPublicKey.cpp b/SoftHSMv2/src/lib/crypto/GOSTPublicKey.cpp
new file mode 100644
index 0000000..ad94068
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/GOSTPublicKey.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ GOSTPublicKey.cpp
+
+ GOST R 34.10-2001 public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "GOSTPublicKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* GOSTPublicKey::type = "Abstract GOST public key";
+
+// Check if the key is of the given type
+bool GOSTPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long GOSTPublicKey::getBitLength() const
+{
+ return getQ().size() * 8;
+}
+
+// Setters for the GOST public key components
+void GOSTPublicKey::setQ(const ByteString& inQ)
+{
+ q = inQ;
+}
+
+// Setters for the GOST public key components
+void GOSTPublicKey::setEC(const ByteString& inEC)
+{
+ ec = inEC;
+}
+
+// Getters for the GOST public key components
+const ByteString& GOSTPublicKey::getQ() const
+{
+ return q;
+}
+
+// Getters for the GOST public key components
+const ByteString& GOSTPublicKey::getEC() const
+{
+ return ec;
+}
diff --git a/SoftHSMv2/src/lib/crypto/GOSTPublicKey.h b/SoftHSMv2/src/lib/crypto/GOSTPublicKey.h
new file mode 100644
index 0000000..28de7b8
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/GOSTPublicKey.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ GOSTPublicKey.h
+
+ GOST R 34.10-2001 public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_GOSTPUBLICKEY_H
+#define _SOFTHSM_V2_GOSTPUBLICKEY_H
+
+#include "config.h"
+#include "PublicKey.h"
+
+class GOSTPublicKey : public PublicKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const = 0;
+
+ // Setters for the GOST public key components
+ virtual void setQ(const ByteString& inQ);
+ virtual void setEC(const ByteString& inEC);
+
+ // Getters for the GOST public key components
+ virtual const ByteString& getQ() const;
+ virtual const ByteString& getEC() const;
+
+ // Serialisation
+ virtual ByteString serialise() const = 0;
+ virtual bool deserialise(ByteString& serialised) = 0;
+
+protected:
+ // Public components
+ ByteString q, ec;
+};
+
+#endif // !_SOFTHSM_V2_GOSTPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/HashAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/HashAlgorithm.cpp
new file mode 100644
index 0000000..934a64c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/HashAlgorithm.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HashAlgorithm.cpp
+
+ Base class for hash algorithm classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "HashAlgorithm.h"
+
+// Base constructor
+HashAlgorithm::HashAlgorithm()
+{
+ currentOperation = NONE;
+}
+
+// Hashing functions
+bool HashAlgorithm::hashInit()
+{
+ if (currentOperation != NONE)
+ {
+ return false;
+ }
+
+ currentOperation = HASHING;
+
+ return true;
+}
+
+bool HashAlgorithm::hashUpdate(const ByteString& /*data*/)
+{
+ if (currentOperation != HASHING)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool HashAlgorithm::hashFinal(ByteString& /*hashedData*/)
+{
+ if (currentOperation != HASHING)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/HashAlgorithm.h b/SoftHSMv2/src/lib/crypto/HashAlgorithm.h
new file mode 100644
index 0000000..ca2ae08
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/HashAlgorithm.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HashAlgorithm.h
+
+ Base class for hash algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HASHALGORITHM_H
+#define _SOFTHSM_V2_HASHALGORITHM_H
+
+#include "config.h"
+#include "ByteString.h"
+
+struct HashAlgo
+{
+ enum Type
+ {
+ Unknown,
+ MD5,
+ SHA1,
+ SHA224,
+ SHA256,
+ SHA384,
+ SHA512,
+ GOST
+ };
+};
+
+class HashAlgorithm
+{
+public:
+ // Base constructors
+ HashAlgorithm();
+
+ // Destructor
+ virtual ~HashAlgorithm() { }
+
+ // Hashing functions
+ virtual bool hashInit();
+ virtual bool hashUpdate(const ByteString& data);
+ virtual bool hashFinal(ByteString& hashedData);
+
+ virtual int getHashSize() = 0;
+protected:
+ // The current operation
+ enum
+ {
+ NONE,
+ HASHING
+ }
+ currentOperation;
+};
+
+#endif // !_SOFTHSM_V2_HASHALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/MacAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/MacAlgorithm.cpp
new file mode 100644
index 0000000..e100dc1
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/MacAlgorithm.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ MacAlgorithm.cpp
+
+ Base class for MAC algorithm classes
+ *****************************************************************************/
+
+#include "MacAlgorithm.h"
+#include <algorithm>
+#include <string.h>
+
+MacAlgorithm::MacAlgorithm()
+{
+ currentOperation = NONE;
+ currentKey = NULL;
+}
+
+bool MacAlgorithm::signInit(const SymmetricKey* key)
+{
+ if ((key == NULL) || (currentOperation != NONE))
+ {
+ return false;
+ }
+
+ currentKey = key;
+ currentOperation = SIGN;
+
+ return true;
+}
+
+bool MacAlgorithm::signUpdate(const ByteString& /*dataToSign*/)
+{
+ if (currentOperation != SIGN)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool MacAlgorithm::signFinal(ByteString& /*signature*/)
+{
+ if (currentOperation != SIGN)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+ currentKey = NULL;
+
+ return true;
+}
+
+bool MacAlgorithm::verifyInit(const SymmetricKey* key)
+{
+ if ((key == NULL) || (currentOperation != NONE))
+ {
+ return false;
+ }
+
+ currentOperation = VERIFY;
+ currentKey = key;
+
+ return true;
+}
+
+bool MacAlgorithm::verifyUpdate(const ByteString& /*originalData*/)
+{
+ if (currentOperation != VERIFY)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool MacAlgorithm::verifyFinal(ByteString& /*signature*/)
+{
+ if (currentOperation != VERIFY)
+ {
+ return false;
+ }
+
+ currentOperation = NONE;
+ currentKey = NULL;
+
+ return true;
+}
+
+unsigned long MacAlgorithm::getMinKeySize()
+{
+ return 0;
+}
+
+unsigned long MacAlgorithm::getMaxKeySize()
+{
+ return 0;
+}
+
+void MacAlgorithm::recycleKey(SymmetricKey* toRecycle)
+{
+ delete toRecycle;
+}
diff --git a/SoftHSMv2/src/lib/crypto/MacAlgorithm.h b/SoftHSMv2/src/lib/crypto/MacAlgorithm.h
new file mode 100644
index 0000000..e9b22b0
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/MacAlgorithm.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ MacAlgorithm.h
+
+ Base class for MAC algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_MACALGORITHM_H
+#define _SOFTHSM_V2_MACALGORITHM_H
+
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "RNG.h"
+
+struct MacAlgo
+{
+ enum Type
+ {
+ Unknown,
+ HMAC_MD5,
+ HMAC_SHA1,
+ HMAC_SHA224,
+ HMAC_SHA256,
+ HMAC_SHA384,
+ HMAC_SHA512,
+ HMAC_GOST,
+ CMAC_DES,
+ CMAC_AES
+ };
+};
+
+class MacAlgorithm
+{
+public:
+ // Base constructors
+ MacAlgorithm();
+
+ // Destructor
+ virtual ~MacAlgorithm() { }
+
+ // Signing functions
+ virtual bool signInit(const SymmetricKey* key);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(const SymmetricKey* key);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(ByteString& signature);
+
+ // Key
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual void recycleKey(SymmetricKey* toRecycle);
+
+ // Return the MAC size
+ virtual size_t getMacSize() const = 0;
+
+protected:
+ // The current key
+ const SymmetricKey* currentKey;
+
+private:
+ // The current operation
+ enum
+ {
+ NONE,
+ SIGN,
+ VERIFY
+ }
+ currentOperation;
+};
+
+#endif // !_SOFTHSM_V2_MACALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/Makefile.am b/SoftHSMv2/src/lib/crypto/Makefile.am
new file mode 100644
index 0000000..f65e0a4
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/Makefile.am
@@ -0,0 +1,126 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../pkcs11 \
+ @CRYPTO_INCLUDES@
+
+noinst_LTLIBRARIES = libsofthsm_crypto.la
+libsofthsm_crypto_la_SOURCES = AESKey.cpp \
+ AsymmetricAlgorithm.cpp \
+ AsymmetricKeyPair.cpp \
+ CryptoFactory.cpp \
+ DESKey.cpp \
+ DHParameters.cpp \
+ DHPublicKey.cpp \
+ DHPrivateKey.cpp \
+ DSAParameters.cpp \
+ DSAPublicKey.cpp \
+ DSAPrivateKey.cpp \
+ ECParameters.cpp \
+ ECPublicKey.cpp \
+ ECPrivateKey.cpp \
+ GOSTPublicKey.cpp \
+ GOSTPrivateKey.cpp \
+ HashAlgorithm.cpp \
+ MacAlgorithm.cpp \
+ RSAParameters.cpp \
+ RSAPrivateKey.cpp \
+ RSAPublicKey.cpp \
+ SymmetricAlgorithm.cpp \
+ SymmetricKey.cpp
+libsofthsm_crypto_la_LIBADD = @CRYPTO_LIBS@
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h $(srcdir)/*.cpp
+
+# Compile with support of OpenSSL
+if WITH_OPENSSL
+libsofthsm_crypto_la_SOURCES += OSSLAES.cpp \
+ OSSLComp.cpp \
+ OSSLCryptoFactory.cpp \
+ OSSLDES.cpp \
+ OSSLDH.cpp \
+ OSSLDHKeyPair.cpp \
+ OSSLDHPrivateKey.cpp \
+ OSSLDHPublicKey.cpp \
+ OSSLDSA.cpp \
+ OSSLDSAKeyPair.cpp \
+ OSSLDSAPrivateKey.cpp \
+ OSSLDSAPublicKey.cpp \
+ OSSLECDH.cpp \
+ OSSLECDSA.cpp \
+ OSSLECKeyPair.cpp \
+ OSSLECPrivateKey.cpp \
+ OSSLECPublicKey.cpp \
+ OSSLEVPHashAlgorithm.cpp \
+ OSSLEVPMacAlgorithm.cpp \
+ OSSLEVPCMacAlgorithm.cpp \
+ OSSLEVPSymmetricAlgorithm.cpp \
+ OSSLGOST.cpp \
+ OSSLGOSTKeyPair.cpp \
+ OSSLGOSTPrivateKey.cpp \
+ OSSLGOSTPublicKey.cpp \
+ OSSLGOSTR3411.cpp \
+ OSSLCMAC.cpp \
+ OSSLHMAC.cpp \
+ OSSLMD5.cpp \
+ OSSLRNG.cpp \
+ OSSLRSA.cpp \
+ OSSLRSAKeyPair.cpp \
+ OSSLRSAPrivateKey.cpp \
+ OSSLRSAPublicKey.cpp \
+ OSSLSHA1.cpp \
+ OSSLSHA224.cpp \
+ OSSLSHA256.cpp \
+ OSSLSHA384.cpp \
+ OSSLSHA512.cpp \
+ OSSLUtil.cpp
+endif
+
+# Compile with support of Botan
+if WITH_BOTAN
+libsofthsm_crypto_la_SOURCES += BotanAES.cpp \
+ BotanCryptoFactory.cpp \
+ BotanDES.cpp \
+ BotanDH.cpp \
+ BotanDHKeyPair.cpp \
+ BotanDHPrivateKey.cpp \
+ BotanDHPublicKey.cpp \
+ BotanDSA.cpp \
+ BotanDSAKeyPair.cpp \
+ BotanDSAPrivateKey.cpp \
+ BotanDSAPublicKey.cpp \
+ BotanECDH.cpp \
+ BotanECDHKeyPair.cpp \
+ BotanECDHPrivateKey.cpp \
+ BotanECDHPublicKey.cpp \
+ BotanECDSA.cpp \
+ BotanECDSAKeyPair.cpp \
+ BotanECDSAPrivateKey.cpp \
+ BotanECDSAPublicKey.cpp \
+ BotanGOST.cpp \
+ BotanGOSTKeyPair.cpp \
+ BotanGOSTPrivateKey.cpp \
+ BotanGOSTPublicKey.cpp \
+ BotanGOSTR3411.cpp \
+ BotanHashAlgorithm.cpp \
+ BotanMAC.cpp \
+ BotanMacAlgorithm.cpp \
+ BotanMD5.cpp \
+ BotanRNG.cpp \
+ BotanRSA.cpp \
+ BotanRSAKeyPair.cpp \
+ BotanRSAPrivateKey.cpp \
+ BotanRSAPublicKey.cpp \
+ BotanSHA1.cpp \
+ BotanSHA224.cpp \
+ BotanSHA256.cpp \
+ BotanSHA384.cpp \
+ BotanSHA512.cpp \
+ BotanSymmetricAlgorithm.cpp \
+ BotanUtil.cpp \
+ Botan_ecb.cpp
+endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLAES.cpp b/SoftHSMv2/src/lib/crypto/OSSLAES.cpp
new file mode 100644
index 0000000..fd92a3e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLAES.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLAES.cpp
+
+ OpenSSL AES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLAES.h"
+#include <algorithm>
+#include <openssl/aes.h>
+#include "salloc.h"
+
+// Wrap/Unwrap keys
+#ifdef HAVE_AES_KEY_WRAP
+bool OSSLAES::wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out)
+{
+ // RFC 3394 input length checks do not apply to RFC 5649 mode with padding
+ if (mode == SymWrap::AES_KEYWRAP && !checkLength(in.size(), 16, "wrap"))
+ return false;
+
+ return wrapUnwrapKey(key, mode, in, out, 1);
+}
+#else
+bool OSSLAES::wrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/)
+{
+ return false;
+}
+#endif
+
+#ifdef HAVE_AES_KEY_WRAP
+bool OSSLAES::unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out)
+{
+ // RFC 3394 algorithm produce at least 3 blocks of data
+ if ((mode == SymWrap::AES_KEYWRAP && !checkLength(in.size(), 24, "unwrap")) ||
+ // RFC 5649 algorithm produce at least 2 blocks of data
+ (mode == SymWrap::AES_KEYWRAP_PAD && !checkLength(in.size(), 16, "unwrap")))
+ return false;
+ return wrapUnwrapKey(key, mode, in, out, 0);
+}
+#else
+bool OSSLAES::unwrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/)
+{
+ return false;
+}
+#endif
+
+#ifdef HAVE_AES_KEY_WRAP
+// RFC 3394 wrapping and all unwrapping algorithms require aligned blocks
+bool OSSLAES::checkLength(const int insize, const int minsize, const char * const operation) const
+{
+ if (insize < minsize)
+ {
+ ERROR_MSG("key data to %s too small", operation);
+ return false;
+ }
+ if ((insize % 8) != 0)
+ {
+ ERROR_MSG("key data to %s not aligned", operation);
+ return false;
+ }
+ return true;
+}
+
+const EVP_CIPHER* OSSLAES::getWrapCipher(const SymWrap::Type mode, const SymmetricKey* key) const
+{
+ if (key == NULL)
+ return NULL;
+
+ // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys
+ if ((key->getBitLen() != 128) &&
+ (key->getBitLen() != 192) &&
+ (key->getBitLen() != 256))
+ {
+ ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen());
+
+ return NULL;
+ }
+
+#ifdef HAVE_AES_KEY_WRAP
+ // Determine the un/wrapping mode
+ if (mode == SymWrap::AES_KEYWRAP)
+ {
+ // RFC 3394 AES key wrap
+ switch(key->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_wrap();
+ case 192:
+ return EVP_aes_192_wrap();
+ case 256:
+ return EVP_aes_256_wrap();
+ };
+ }
+#endif
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ if (mode == SymWrap::AES_KEYWRAP_PAD)
+ {
+ // RFC 5649 AES key wrap with pad
+ switch(key->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_wrap_pad();
+ case 192:
+ return EVP_aes_192_wrap_pad();
+ case 256:
+ return EVP_aes_256_wrap_pad();
+ };
+ }
+#endif
+
+ ERROR_MSG("unknown AES key wrap mode %i", mode);
+ return NULL;
+}
+
+// EVP wrapping/unwrapping
+// wrap = 1 -> wrapping
+// wrap = 0 -> unwrapping
+bool OSSLAES::wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out, const int wrap) const
+{
+ const char *prefix = "";
+ if (wrap == 0)
+ prefix = "un";
+
+ // Determine the cipher method
+ const EVP_CIPHER* cipher = getWrapCipher(mode, key);
+ if (cipher == NULL)
+ {
+ ERROR_MSG("Failed to get EVP %swrap cipher", prefix);
+ return false;
+ }
+
+ // Allocate the EVP context
+ EVP_CIPHER_CTX* pWrapCTX = EVP_CIPHER_CTX_new();
+ if (pWrapCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX");
+ return false;
+ }
+ EVP_CIPHER_CTX_set_flags(pWrapCTX, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+
+ int rv = EVP_CipherInit_ex(pWrapCTX, cipher, NULL, (unsigned char*) key->getKeyBits().const_byte_str(), NULL, wrap);
+ if (rv)
+ // Padding is handled by cipher mode separately
+ rv = EVP_CIPHER_CTX_set_padding(pWrapCTX, 0);
+ if (!rv)
+ {
+ ERROR_MSG("Failed to initialise EVP cipher %swrap operation", prefix);
+
+ EVP_CIPHER_CTX_free(pWrapCTX);
+ return false;
+ }
+
+ // 1 input byte could be expanded to two AES blocks
+ out.resize(in.size() + 2 * EVP_CIPHER_CTX_block_size(pWrapCTX) - 1);
+ int outLen = 0;
+ int curBlockLen = 0;
+ rv = EVP_CipherUpdate(pWrapCTX, &out[0], &curBlockLen, in.const_byte_str(), in.size());
+ if (rv == 1) {
+ outLen = curBlockLen;
+ rv = EVP_CipherFinal_ex(pWrapCTX, &out[0] + outLen, &curBlockLen);
+ }
+ if (rv != 1)
+ {
+ ERROR_MSG("Failed EVP %swrap operation", prefix);
+
+ EVP_CIPHER_CTX_free(pWrapCTX);
+ return false;
+ }
+ EVP_CIPHER_CTX_free(pWrapCTX);
+ outLen += curBlockLen;
+ out.resize(outLen);
+ return true;
+}
+#endif
+
+const EVP_CIPHER* OSSLAES::getCipher() const
+{
+ if (currentKey == NULL) return NULL;
+
+ // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys
+ if ((currentKey->getBitLen() != 128) &&
+ (currentKey->getBitLen() != 192) &&
+ (currentKey->getBitLen() != 256))
+ {
+ ERROR_MSG("Invalid AES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return NULL;
+ }
+
+ // Determine the cipher mode
+ if (currentCipherMode == SymMode::CBC)
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_cbc();
+ case 192:
+ return EVP_aes_192_cbc();
+ case 256:
+ return EVP_aes_256_cbc();
+ };
+ }
+ else if (currentCipherMode == SymMode::ECB)
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_ecb();
+ case 192:
+ return EVP_aes_192_ecb();
+ case 256:
+ return EVP_aes_256_ecb();
+ };
+ }
+ else if (currentCipherMode == SymMode::CTR)
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_ctr();
+ case 192:
+ return EVP_aes_192_ctr();
+ case 256:
+ return EVP_aes_256_ctr();
+ };
+ }
+ else if (currentCipherMode == SymMode::GCM)
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_gcm();
+ case 192:
+ return EVP_aes_192_gcm();
+ case 256:
+ return EVP_aes_256_gcm();
+ };
+ }
+
+ ERROR_MSG("Invalid AES cipher mode %i", currentCipherMode);
+
+ return NULL;
+}
+
+size_t OSSLAES::getBlockSize() const
+{
+ // The block size is 128 bits
+ return 128 >> 3;
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLAES.h b/SoftHSMv2/src/lib/crypto/OSSLAES.h
new file mode 100644
index 0000000..6310f31
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLAES.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLAES.h
+
+ OpenSSL AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLAES_H
+#define _SOFTHSM_V2_OSSLAES_H
+
+#include <openssl/evp.h>
+#include <string>
+#include "config.h"
+#include "OSSLEVPSymmetricAlgorithm.h"
+
+class OSSLAES : public OSSLEVPSymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~OSSLAES() { }
+
+ // Wrap/Unwrap keys
+ virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out);
+
+ virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out);
+
+ // Return the block size
+ virtual size_t getBlockSize() const;
+
+protected:
+ // Return the right EVP cipher for the operation
+ virtual const EVP_CIPHER* getCipher() const;
+ const EVP_CIPHER* getWrapCipher(const SymWrap::Type mode, const SymmetricKey* key) const;
+ bool wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out, const int wrap) const;
+ bool checkLength(const int insize, const int minsize, const char * const operation) const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLAES_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLCMAC.cpp b/SoftHSMv2/src/lib/crypto/OSSLCMAC.cpp
new file mode 100644
index 0000000..554c308
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLCMAC.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLHMAC.cpp
+
+ OpenSSL HMAC implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLCMAC.h"
+
+const EVP_CIPHER* OSSLCMACDES::getEVPCipher() const
+{
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ ERROR_MSG("Only supporting 3DES");
+ return NULL;
+ case 112:
+ return EVP_des_ede_cbc();
+ case 168:
+ return EVP_des_ede3_cbc();
+ default:
+ break;
+ };
+
+ ERROR_MSG("Invalid DES bit len %i", currentKey->getBitLen());
+
+ return NULL;
+}
+
+size_t OSSLCMACDES::getMacSize() const
+{
+ return 8;
+}
+
+const EVP_CIPHER* OSSLCMACAES::getEVPCipher() const
+{
+ switch(currentKey->getBitLen())
+ {
+ case 128:
+ return EVP_aes_128_cbc();
+ case 192:
+ return EVP_aes_192_cbc();
+ case 256:
+ return EVP_aes_256_cbc();
+ default:
+ break;
+ };
+
+ ERROR_MSG("Invalid AES bit len %i", currentKey->getBitLen());
+
+ return NULL;
+}
+
+size_t OSSLCMACAES::getMacSize() const
+{
+ return 16;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLCMAC.h b/SoftHSMv2/src/lib/crypto/OSSLCMAC.h
new file mode 100644
index 0000000..8d15e7c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLCMAC.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLCMAC.h
+
+ OpenSSL CMAC implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLCMAC_H
+#define _SOFTHSM_V2_OSSLCMAC_H
+
+#include "config.h"
+#include "OSSLEVPCMacAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLCMACDES : public OSSLEVPCMacAlgorithm
+{
+protected:
+ virtual const EVP_CIPHER* getEVPCipher() const;
+ virtual size_t getMacSize() const;
+};
+
+class OSSLCMACAES : public OSSLEVPCMacAlgorithm
+{
+protected:
+ virtual const EVP_CIPHER* getEVPCipher() const;
+ virtual size_t getMacSize() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLHMAC_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLComp.cpp b/SoftHSMv2/src/lib/crypto/OSSLComp.cpp
new file mode 100644
index 0000000..ede710b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLComp.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2016 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLUtil.cpp
+
+ Adding OpenSSL forward-compatible code as suggested by OpenSSL
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLComp.h"
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#ifdef WITH_ECC
+#include <openssl/ecdsa.h>
+#endif
+#include <openssl/rsa.h>
+
+#include <string.h>
+
+// EVP digest routines
+EVP_MD_CTX *EVP_MD_CTX_new(void)
+{
+ EVP_MD_CTX *ctx = (EVP_MD_CTX*)OPENSSL_malloc(sizeof *ctx);
+
+ if (ctx)
+ EVP_MD_CTX_init(ctx);
+
+ return ctx;
+}
+
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+ if (ctx)
+ {
+ EVP_MD_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+
+// HMAC routines
+HMAC_CTX *HMAC_CTX_new(void)
+{
+ HMAC_CTX *ctx = (HMAC_CTX*)OPENSSL_malloc(sizeof(*ctx));
+ if (ctx == NULL) return NULL;
+
+ HMAC_CTX_init(ctx);
+
+ return ctx;
+}
+
+void HMAC_CTX_free(HMAC_CTX *ctx)
+{
+ if (ctx == NULL) return;
+
+ HMAC_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+
+// DH routines
+void DH_get0_pqg(const DH *dh,
+ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+ if (p != NULL)
+ *p = dh->p;
+ if (q != NULL)
+ *q = dh->q;
+ if (g != NULL)
+ *g = dh->g;
+}
+
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+ /* If the fields p and g in d are NULL, the corresponding input
+ * parameters MUST be non-NULL. q may remain NULL.
+ */
+ if ((dh->p == NULL && p == NULL)
+ || (dh->g == NULL && g == NULL))
+ return 0;
+
+ if (p != NULL)
+ {
+ BN_free(dh->p);
+ dh->p = p;
+ }
+ if (q != NULL)
+ {
+ BN_free(dh->q);
+ dh->q = q;
+ }
+ if (g != NULL)
+ {
+ BN_free(dh->g);
+ dh->g = g;
+ }
+
+ if (q != NULL)
+ {
+ dh->length = BN_num_bits(q);
+ }
+
+ return 1;
+}
+
+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+ if (pub_key != NULL)
+ *pub_key = dh->pub_key;
+ if (priv_key != NULL)
+ *priv_key = dh->priv_key;
+}
+
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+ /* If the field pub_key in dh is NULL, the corresponding input
+ * parameters MUST be non-NULL. The priv_key field may
+ * be left NULL.
+ */
+ if (dh->pub_key == NULL && pub_key == NULL)
+ return 0;
+
+ if (pub_key != NULL)
+ {
+ BN_free(dh->pub_key);
+ dh->pub_key = pub_key;
+ }
+ if (priv_key != NULL)
+ {
+ BN_free(dh->priv_key);
+ dh->priv_key = priv_key;
+ }
+
+ return 1;
+}
+
+long DH_get_length(const DH *dh)
+{
+ return dh->length;
+}
+
+int DH_set_length(DH *dh, long length)
+{
+ dh->length = length;
+
+ return 1;
+}
+
+// DSA routines
+void DSA_get0_pqg(const DSA *d,
+ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+ if (p != NULL)
+ *p = d->p;
+ if (q != NULL)
+ *q = d->q;
+ if (g != NULL)
+ *g = d->g;
+}
+
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+ /* If the fields p, q and g in d are NULL, the corresponding input
+ * parameters MUST be non-NULL.
+ */
+ if ((d->p == NULL && p == NULL)
+ || (d->q == NULL && q == NULL)
+ || (d->g == NULL && g == NULL))
+ return 0;
+
+ if (p != NULL)
+ {
+ BN_free(d->p);
+ d->p = p;
+ }
+ if (q != NULL)
+ {
+ BN_free(d->q);
+ d->q = q;
+ }
+ if (g != NULL)
+ {
+ BN_free(d->g);
+ d->g = g;
+ }
+
+ return 1;
+}
+
+void DSA_get0_key(const DSA *d,
+ const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+ if (pub_key != NULL)
+ *pub_key = d->pub_key;
+ if (priv_key != NULL)
+ *priv_key = d->priv_key;
+}
+
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+ /* If the field pub_key in d is NULL, the corresponding input
+ * parameters MUST be non-NULL. The priv_key field may
+ * be left NULL.
+ */
+ if (d->pub_key == NULL && pub_key == NULL)
+ return 0;
+
+ if (pub_key != NULL)
+ {
+ BN_free(d->pub_key);
+ d->pub_key = pub_key;
+ }
+ if (priv_key != NULL)
+ {
+ BN_free(d->priv_key);
+ d->priv_key = priv_key;
+ }
+
+ return 1;
+}
+
+// DSA_SIG routines
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+ if (pr != NULL)
+ *pr = sig->r;
+ if (ps != NULL)
+ *ps = sig->s;
+}
+
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+ if (r == NULL || s == NULL)
+ return 0;
+ BN_clear_free(sig->r);
+ BN_clear_free(sig->s);
+ sig->r = r;
+ sig->s = s;
+ return 1;
+}
+
+// ECDSA_SIG routines
+#ifdef WITH_ECC
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+ if (pr != NULL)
+ *pr = sig->r;
+ if (ps != NULL)
+ *ps = sig->s;
+}
+
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+ if (r == NULL || s == NULL)
+ return 0;
+ BN_clear_free(sig->r);
+ BN_clear_free(sig->s);
+ sig->r = r;
+ sig->s = s;
+
+ return 1;
+}
+#endif
+
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+{
+ /* If the fields n and e in r are NULL, the corresponding input
+ * parameters MUST be non-NULL for n and e. d may be
+ * left NULL (in case only the public key is used).
+ */
+ if ((r->n == NULL && n == NULL)
+ || (r->e == NULL && e == NULL))
+ return 0;
+
+ if (n != NULL)
+ {
+ BN_free(r->n);
+ r->n = n;
+ }
+ if (e != NULL)
+ {
+ BN_free(r->e);
+ r->e = e;
+ }
+ if (d != NULL)
+ {
+ BN_free(r->d);
+ r->d = d;
+ }
+
+ return 1;
+}
+
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
+{
+ /* If the fields p and q in r are NULL, the corresponding input
+ * parameters MUST be non-NULL.
+ */
+ if ((r->p == NULL && p == NULL)
+ || (r->q == NULL && q == NULL))
+ return 0;
+
+ if (p != NULL)
+ {
+ BN_free(r->p);
+ r->p = p;
+ }
+ if (q != NULL)
+ {
+ BN_free(r->q);
+ r->q = q;
+ }
+
+ return 1;
+}
+
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
+{
+ /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
+ * parameters MUST be non-NULL.
+ */
+ if ((r->dmp1 == NULL && dmp1 == NULL)
+ || (r->dmq1 == NULL && dmq1 == NULL)
+ || (r->iqmp == NULL && iqmp == NULL))
+ return 0;
+
+ if (dmp1 != NULL)
+ {
+ BN_free(r->dmp1);
+ r->dmp1 = dmp1;
+ }
+ if (dmq1 != NULL)
+ {
+ BN_free(r->dmq1);
+ r->dmq1 = dmq1;
+ }
+ if (iqmp != NULL)
+ {
+ BN_free(r->iqmp);
+ r->iqmp = iqmp;
+ }
+
+ return 1;
+}
+
+void RSA_get0_key(const RSA *r,
+ const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+{
+ if (n != NULL)
+ *n = r->n;
+ if (e != NULL)
+ *e = r->e;
+ if (d != NULL)
+ *d = r->d;
+}
+
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
+{
+ if (p != NULL)
+ *p = r->p;
+ if (q != NULL)
+ *q = r->q;
+}
+
+void RSA_get0_crt_params(const RSA *r,
+ const BIGNUM **dmp1, const BIGNUM **dmq1,
+ const BIGNUM **iqmp)
+{
+ if (dmp1 != NULL)
+ *dmp1 = r->dmp1;
+ if (dmq1 != NULL)
+ *dmq1 = r->dmq1;
+ if (iqmp != NULL)
+ *iqmp = r->iqmp;
+}
+
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLComp.h b/SoftHSMv2/src/lib/crypto/OSSLComp.h
new file mode 100644
index 0000000..4bced32
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLComp.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLComp.h
+
+ Adding OpenSSL forward-compatible code as suggested by OpenSSL
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLCOMP_H
+#define _SOFTHSM_V2_OSSLCOMP_H
+
+#include "config.h"
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#ifdef WITH_ECC
+#include <openssl/ecdsa.h>
+#endif
+#include <openssl/rsa.h>
+
+// EVP digest routines
+EVP_MD_CTX *EVP_MD_CTX_new(void);
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
+
+// HMAC routines
+HMAC_CTX *HMAC_CTX_new(void);
+void HMAC_CTX_free(HMAC_CTX *ctx);
+
+// DH routines
+void DH_get0_pqg(const DH *dh,
+ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
+long DH_get_length(const DH *dh);
+int DH_set_length(DH *dh, long length);
+
+// DSA routines
+void DSA_get0_pqg(const DSA *d,
+ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+void DSA_get0_key(const DSA *d,
+ const BIGNUM **pub_key, const BIGNUM **priv_key);
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
+
+// DSA_SIG routines
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+
+// ECDSA_SIG routines
+#ifdef WITH_ECC
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+#endif
+
+// RSA routines
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
+void RSA_get0_key(const RSA *r,
+ const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
+void RSA_get0_crt_params(const RSA *r,
+ const BIGNUM **dmp1, const BIGNUM **dmq1,
+ const BIGNUM **iqmp);
+
+#endif
+
+#endif // !_SOFTHSM_V2_OSSLCOMP_H
diff --git a/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp
new file mode 100644
index 0000000..ad27482
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLCryptoFactory.cpp
+
+ This is an OpenSSL based cryptographic algorithm factory
+ *****************************************************************************/
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "OSSLCryptoFactory.h"
+#include "OSSLRNG.h"
+#include "OSSLAES.h"
+#include "OSSLDES.h"
+#include "OSSLMD5.h"
+#include "OSSLSHA1.h"
+#include "OSSLSHA224.h"
+#include "OSSLSHA256.h"
+#include "OSSLSHA384.h"
+#include "OSSLSHA512.h"
+#include "OSSLCMAC.h"
+#include "OSSLHMAC.h"
+#include "OSSLRSA.h"
+#include "OSSLDSA.h"
+#include "OSSLDH.h"
+#ifdef WITH_ECC
+#include "OSSLECDH.h"
+#include "OSSLECDSA.h"
+#endif
+#ifdef WITH_GOST
+#include "OSSLGOSTR3411.h"
+#include "OSSLGOST.h"
+#endif
+
+#include <algorithm>
+#include <string.h>
+#include <openssl/opensslv.h>
+#include <openssl/ssl.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#ifdef WITH_GOST
+#include <openssl/objects.h>
+#endif
+
+#ifdef WITH_FIPS
+// Initialise the FIPS 140-2 selftest status
+bool OSSLCryptoFactory::FipsSelfTestStatus = false;
+#endif
+
+static unsigned nlocks;
+static Mutex** locks;
+
+// Mutex callback
+void lock_callback(int mode, int n, const char* file, int line)
+{
+ if ((unsigned) n >= nlocks)
+ {
+ ERROR_MSG("out of range [0..%u[ lock %d at %s:%d",
+ nlocks, n, file, line);
+
+ return;
+ }
+
+ Mutex* mtx = locks[(unsigned) n];
+
+ if (mode & CRYPTO_LOCK)
+ {
+ mtx->lock();
+ }
+ else
+ {
+ mtx->unlock();
+ }
+}
+
+// Constructor
+OSSLCryptoFactory::OSSLCryptoFactory()
+{
+ // Multi-thread support
+ nlocks = CRYPTO_num_locks();
+ locks = new Mutex*[nlocks];
+ for (unsigned i = 0; i < nlocks; i++)
+ {
+ locks[i] = MutexFactory::i()->getMutex();
+ }
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ setLockingCallback = false;
+ if (CRYPTO_get_locking_callback() == NULL)
+ {
+ CRYPTO_set_locking_callback(lock_callback);
+ setLockingCallback = true;
+ }
+#endif
+
+#ifdef WITH_FIPS
+ // Already in FIPS mode on reenter (avoiding selftests)
+ if (!FIPS_mode())
+ {
+ FipsSelfTestStatus = false;
+ if (!FIPS_mode_set(1))
+ {
+ ERROR_MSG("can't enter into FIPS mode");
+ return;
+ }
+ } else {
+ // Undo RAND_cleanup()
+ RAND_init_fips();
+ }
+ FipsSelfTestStatus = true;
+#endif
+
+ // Initialise OpenSSL
+ OpenSSL_add_all_algorithms();
+
+ // Initialise the one-and-only RNG
+ rng = new OSSLRNG();
+
+#ifdef WITH_GOST
+ // Load engines
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ ENGINE_load_builtin_engines();
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN |
+ OPENSSL_INIT_LOAD_CONFIG, NULL);
+#endif
+
+ // Initialise the GOST engine
+ eg = ENGINE_by_id("gost");
+ if (eg == NULL)
+ {
+ ERROR_MSG("can't get the GOST engine");
+ return;
+ }
+ if (ENGINE_init(eg) <= 0)
+ {
+ ENGINE_free(eg);
+ eg = NULL;
+ ERROR_MSG("can't initialize the GOST engine");
+ return;
+ }
+ // better than digest_gost
+ EVP_GOST_34_11 = ENGINE_get_digest(eg, NID_id_GostR3411_94);
+ if (EVP_GOST_34_11 == NULL)
+ {
+ ERROR_MSG("can't get the GOST digest");
+ goto err;
+ }
+ // from the openssl.cnf
+ if (ENGINE_register_pkey_asn1_meths(eg) <= 0)
+ {
+ ERROR_MSG("can't register ASN.1 for the GOST engine");
+ goto err;
+ }
+ if (ENGINE_ctrl_cmd_string(eg,
+ "CRYPT_PARAMS",
+ "id-Gost28147-89-CryptoPro-A-ParamSet",
+ 0) <= 0)
+ {
+ ERROR_MSG("can't set params of the GOST engine");
+ goto err;
+ }
+ return;
+
+err:
+ ENGINE_finish(eg);
+ ENGINE_free(eg);
+ eg = NULL;
+ return;
+#endif
+}
+
+// Destructor
+OSSLCryptoFactory::~OSSLCryptoFactory()
+{
+#ifdef WITH_GOST
+ // Finish the GOST engine
+ if (eg != NULL)
+ {
+ ENGINE_finish(eg);
+ ENGINE_free(eg);
+ eg = NULL;
+ }
+#endif
+
+ // Destroy the one-and-only RNG
+ delete rng;
+
+ // Recycle locks
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ if (setLockingCallback)
+ {
+ CRYPTO_set_locking_callback(NULL);
+ }
+#endif
+ for (unsigned i = 0; i < nlocks; i++)
+ {
+ MutexFactory::i()->recycleMutex(locks[i]);
+ }
+ delete[] locks;
+}
+
+// Return the one-and-only instance
+OSSLCryptoFactory* OSSLCryptoFactory::i()
+{
+ if (!instance.get())
+ {
+ instance.reset(new OSSLCryptoFactory());
+ }
+
+ return instance.get();
+}
+
+// This will destroy the one-and-only instance.
+void OSSLCryptoFactory::reset()
+{
+ instance.reset();
+}
+
+#ifdef WITH_FIPS
+bool OSSLCryptoFactory::getFipsSelfTestStatus() const
+{
+ return FipsSelfTestStatus;
+}
+#endif
+
+// Create a concrete instance of a symmetric algorithm
+SymmetricAlgorithm* OSSLCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm)
+{
+ switch (algorithm)
+ {
+ case SymAlgo::AES:
+ return new OSSLAES();
+ case SymAlgo::DES:
+ case SymAlgo::DES3:
+ return new OSSLDES();
+ default:
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%i'", algorithm);
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Create a concrete instance of an asymmetric algorithm
+AsymmetricAlgorithm* OSSLCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm)
+{
+ switch (algorithm)
+ {
+ case AsymAlgo::RSA:
+ return new OSSLRSA();
+ case AsymAlgo::DSA:
+ return new OSSLDSA();
+ case AsymAlgo::DH:
+ return new OSSLDH();
+#ifdef WITH_ECC
+ case AsymAlgo::ECDH:
+ return new OSSLECDH();
+ case AsymAlgo::ECDSA:
+ return new OSSLECDSA();
+#endif
+#ifdef WITH_GOST
+ case AsymAlgo::GOST:
+ return new OSSLGOST();
+#endif
+ default:
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%i'", algorithm);
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Create a concrete instance of a hash algorithm
+HashAlgorithm* OSSLCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm)
+{
+ switch (algorithm)
+ {
+ case HashAlgo::MD5:
+ return new OSSLMD5();
+ case HashAlgo::SHA1:
+ return new OSSLSHA1();
+ case HashAlgo::SHA224:
+ return new OSSLSHA224();
+ case HashAlgo::SHA256:
+ return new OSSLSHA256();
+ case HashAlgo::SHA384:
+ return new OSSLSHA384();
+ case HashAlgo::SHA512:
+ return new OSSLSHA512();
+#ifdef WITH_GOST
+ case HashAlgo::GOST:
+ return new OSSLGOSTR3411();
+#endif
+ default:
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%i'", algorithm);
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Create a concrete instance of a MAC algorithm
+MacAlgorithm* OSSLCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm)
+{
+ switch (algorithm)
+ {
+ case MacAlgo::HMAC_MD5:
+ return new OSSLHMACMD5();
+ case MacAlgo::HMAC_SHA1:
+ return new OSSLHMACSHA1();
+ case MacAlgo::HMAC_SHA224:
+ return new OSSLHMACSHA224();
+ case MacAlgo::HMAC_SHA256:
+ return new OSSLHMACSHA256();
+ case MacAlgo::HMAC_SHA384:
+ return new OSSLHMACSHA384();
+ case MacAlgo::HMAC_SHA512:
+ return new OSSLHMACSHA512();
+#ifdef WITH_GOST
+ case MacAlgo::HMAC_GOST:
+ return new OSSLHMACGOSTR3411();
+#endif
+ case MacAlgo::CMAC_DES:
+ return new OSSLCMACDES();
+ case MacAlgo::CMAC_AES:
+ return new OSSLCMACAES();
+ default:
+ // No algorithm implementation is available
+ ERROR_MSG("Unknown algorithm '%i'", algorithm);
+
+ return NULL;
+ }
+
+ // No algorithm implementation is available
+ return NULL;
+}
+
+// Get the global RNG (may be an unique RNG per thread)
+RNG* OSSLCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */)
+{
+ if (name == RNGImpl::Default)
+ {
+ return rng;
+ }
+ else
+ {
+ // No RNG implementation is available
+ ERROR_MSG("Unknown RNG '%i'", name);
+
+ return NULL;
+ }
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h
new file mode 100644
index 0000000..e8bfa2c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLCryptoFactory.h
+
+ This is an OpenSSL based cryptographic algorithm factory
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLCRYPTOFACTORY_H
+#define _SOFTHSM_V2_OSSLCRYPTOFACTORY_H
+
+#include "config.h"
+#include "CryptoFactory.h"
+#include "SymmetricAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include "MacAlgorithm.h"
+#include "RNG.h"
+#include <memory>
+#ifdef WITH_GOST
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+#endif
+
+class OSSLCryptoFactory : public CryptoFactory
+{
+public:
+ // Return the one-and-only instance
+ static OSSLCryptoFactory* i();
+
+ // This will destroy the one-and-only instance.
+ static void reset();
+
+#ifdef WITH_FIPS
+ // Return the FIPS 140-2 selftest status
+ virtual bool getFipsSelfTestStatus() const;
+#endif
+
+ // Create a concrete instance of a symmetric algorithm
+ virtual SymmetricAlgorithm* getSymmetricAlgorithm(SymAlgo::Type algorithm);
+
+ // Create a concrete instance of an asymmetric algorithm
+ virtual AsymmetricAlgorithm* getAsymmetricAlgorithm(AsymAlgo::Type algorithm);
+
+ // Create a concrete instance of a hash algorithm
+ virtual HashAlgorithm* getHashAlgorithm(HashAlgo::Type algorithm);
+
+ // Create a concrete instance of a MAC algorithm
+ virtual MacAlgorithm* getMacAlgorithm(MacAlgo::Type algorithm);
+
+ // Get the global RNG (may be an unique RNG per thread)
+ virtual RNG* getRNG(RNGImpl::Type name = RNGImpl::Default);
+
+ // Destructor
+ virtual ~OSSLCryptoFactory();
+
+#ifdef WITH_GOST
+ // The EVP_MD for GOST R 34.11-94
+ const EVP_MD *EVP_GOST_34_11;
+#endif
+
+private:
+ // Constructor
+ OSSLCryptoFactory();
+
+ // The one-and-only instance
+#ifdef HAVE_CXX11
+ static std::unique_ptr<OSSLCryptoFactory> instance;
+#else
+ static std::auto_ptr<OSSLCryptoFactory> instance;
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ bool setLockingCallback;
+#endif
+
+#ifdef WITH_FIPS
+ // The FIPS 140-2 selftest status
+ static bool FipsSelfTestStatus;
+#endif
+
+ // The one-and-only RNG instance
+ RNG* rng;
+
+#ifdef WITH_GOST
+ // The GOST engine
+ ENGINE *eg;
+#endif
+};
+
+#endif // !_SOFTHSM_V2_OSSLCRYPTOFACTORY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDES.cpp b/SoftHSMv2/src/lib/crypto/OSSLDES.cpp
new file mode 100644
index 0000000..4fb56b5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDES.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDES.cpp
+
+ OpenSSL (3)DES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLDES.h"
+#include <algorithm>
+#include "odd.h"
+
+bool OSSLDES::wrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/)
+{
+ ERROR_MSG("DES does not support key wrapping");
+
+ return false;
+}
+
+bool OSSLDES::unwrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/)
+{
+ ERROR_MSG("DES does not support key unwrapping");
+
+ return false;
+}
+
+const EVP_CIPHER* OSSLDES::getCipher() const
+{
+ if (currentKey == NULL) return NULL;
+
+ // Check currentKey bit length; 3DES only supports 56-bit, 112-bit or 168-bit keys
+ if (
+#ifndef WITH_FIPS
+ (currentKey->getBitLen() != 56) &&
+#endif
+ (currentKey->getBitLen() != 112) &&
+ (currentKey->getBitLen() != 168))
+ {
+ ERROR_MSG("Invalid DES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return NULL;
+ }
+
+ // People shouldn't really be using 56-bit DES keys, generate a warning
+ if (currentKey->getBitLen() == 56)
+ {
+ DEBUG_MSG("CAUTION: use of 56-bit DES keys is not recommended!");
+ }
+
+ // Determine the cipher mode
+ if (currentCipherMode == SymMode::CBC)
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return EVP_des_cbc();
+ case 112:
+ return EVP_des_ede_cbc();
+ case 168:
+ return EVP_des_ede3_cbc();
+ };
+ }
+ else if (currentCipherMode == SymMode::ECB)
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return EVP_des_ecb();
+ case 112:
+ return EVP_des_ede_ecb();
+ case 168:
+ return EVP_des_ede3_ecb();
+ };
+ }
+ else if (currentCipherMode == SymMode::OFB)
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return EVP_des_ofb();
+ case 112:
+ return EVP_des_ede_ofb();
+ case 168:
+ return EVP_des_ede3_ofb();
+ };
+ }
+ else if (currentCipherMode == SymMode::CFB)
+ {
+ switch(currentKey->getBitLen())
+ {
+ case 56:
+ return EVP_des_cfb();
+ case 112:
+ return EVP_des_ede_cfb();
+ case 168:
+ return EVP_des_ede3_cfb();
+ };
+ }
+
+ ERROR_MSG("Invalid DES cipher mode %i", currentCipherMode);
+
+ return NULL;
+}
+
+bool OSSLDES::generateKey(SymmetricKey& key, RNG* rng /* = NULL */)
+{
+ if (rng == NULL)
+ {
+ return false;
+ }
+
+ if (key.getBitLen() == 0)
+ {
+ return false;
+ }
+
+ ByteString keyBits;
+
+ // don't count parity bit
+ if (!rng->generateRandom(keyBits, key.getBitLen()/7))
+ {
+ return false;
+ }
+
+ // fix the odd parity
+ size_t i;
+ for (i = 0; i < keyBits.size(); i++)
+ {
+ keyBits[i] = odd_parity[keyBits[i]];
+ }
+
+ return key.setKeyBits(keyBits);
+}
+
+size_t OSSLDES::getBlockSize() const
+{
+ // The block size is 64 bits
+ return 64 >> 3;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDES.h b/SoftHSMv2/src/lib/crypto/OSSLDES.h
new file mode 100644
index 0000000..1ecdc8c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDES.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDES.h
+
+ OpenSSL AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDES_H
+#define _SOFTHSM_V2_OSSLDES_H
+
+#include <openssl/evp.h>
+#include <string>
+#include "config.h"
+#include "OSSLEVPSymmetricAlgorithm.h"
+
+class OSSLDES : public OSSLEVPSymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~OSSLDES() { }
+
+ // Wrap/Unwrap keys
+ virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out);
+
+ virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out);
+
+ // Generate key
+ virtual bool generateKey(SymmetricKey& key, RNG* rng = NULL);
+
+ // Return the block size
+ virtual size_t getBlockSize() const;
+
+protected:
+ // Return the right EVP cipher for the operation
+ virtual const EVP_CIPHER* getCipher() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDES_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDH.cpp b/SoftHSMv2/src/lib/crypto/OSSLDH.cpp
new file mode 100644
index 0000000..ee61733
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDH.cpp
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDH.cpp
+
+ OpenSSL Diffie-Hellman asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDH.h"
+#include "CryptoFactory.h"
+#include "DHParameters.h"
+#include "OSSLComp.h"
+#include "OSSLDHKeyPair.h"
+#include "OSSLUtil.h"
+#include <algorithm>
+#include <openssl/dh.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+// Signing functions
+bool OSSLDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("DH does not support signing");
+
+ return false;
+}
+
+bool OSSLDH::signUpdate(const ByteString& /*dataToSign*/)
+{
+ ERROR_MSG("DH does not support signing");
+
+ return false;
+}
+
+bool OSSLDH::signFinal(ByteString& /*signature*/)
+{
+ ERROR_MSG("DH does not support signing");
+
+ return false;
+}
+
+// Verification functions
+bool OSSLDH::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("DH does not support verifying");
+
+ return false;
+}
+
+bool OSSLDH::verifyUpdate(const ByteString& /*originalData*/)
+{
+ ERROR_MSG("DH does not support verifying");
+
+ return false;
+}
+
+bool OSSLDH::verifyFinal(const ByteString& /*signature*/)
+{
+ ERROR_MSG("DH does not support verifying");
+
+ return false;
+}
+
+// Encryption functions
+bool OSSLDH::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("DH does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool OSSLDH::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("DH does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(DHParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for DH key generation");
+
+ return false;
+ }
+
+ DHParameters* params = (DHParameters*) parameters;
+
+ // Generate the key-pair
+ DH* dh = DH_new();
+ if (dh == NULL)
+ {
+ ERROR_MSG("Failed to instantiate OpenSSL DH object");
+
+ return false;
+ }
+
+ BIGNUM* bn_p = OSSL::byteString2bn(params->getP());
+ BIGNUM* bn_g = OSSL::byteString2bn(params->getG());
+
+ if (!DH_set0_pqg(dh, bn_p, NULL, bn_g))
+ {
+ ERROR_MSG("DH set pqg failed (0x%08X)", ERR_get_error());
+
+ BN_free(bn_p);
+ BN_free(bn_g);
+ DH_free(dh);
+
+ return false;
+ }
+
+ if (params->getXBitLength() > 0)
+ {
+ if (!DH_set_length(dh, params->getXBitLength()))
+ {
+ ERROR_MSG("DH set length failed (0x%08X)", ERR_get_error());
+
+ DH_free(dh);
+
+ return false;
+ }
+ }
+
+ if (DH_generate_key(dh) != 1)
+ {
+ ERROR_MSG("DH key generation failed (0x%08X)", ERR_get_error());
+
+ DH_free(dh);
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ OSSLDHKeyPair* kp = new OSSLDHKeyPair();
+
+ ((OSSLDHPublicKey*) kp->getPublicKey())->setFromOSSL(dh);
+ ((OSSLDHPrivateKey*) kp->getPrivateKey())->setFromOSSL(dh);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ DH_free(dh);
+
+ return true;
+}
+
+bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
+{
+ // Check parameters
+ if ((ppSymmetricKey == NULL) ||
+ (publicKey == NULL) ||
+ (privateKey == NULL))
+ {
+ return false;
+ }
+
+ // Get keys
+ DH *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey();
+ DH *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey();
+ if (pub == NULL || priv == NULL)
+ {
+ ERROR_MSG("Failed to get OpenSSL DH keys");
+
+ return false;
+ }
+ const BIGNUM* bn_pub_key = NULL;
+ DH_get0_key(pub, &bn_pub_key, NULL);
+ if (bn_pub_key == NULL)
+ {
+ ERROR_MSG("Failed to get OpenSSL DH keys");
+
+ return false;
+ }
+
+ // Derive the secret
+ ByteString secret, derivedSecret;
+ int size = DH_size(priv);
+ secret.wipe(size);
+ derivedSecret.wipe(size);
+ int keySize = DH_compute_key(&derivedSecret[0], bn_pub_key, priv);
+
+ if (keySize <= 0)
+ {
+ ERROR_MSG("DH key derivation failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+
+ // We compensate that OpenSSL removes leading zeros
+ memcpy(&secret[0] + size - keySize, &derivedSecret[0], keySize);
+
+ *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
+ if (*ppSymmetricKey == NULL)
+ return false;
+ if (!(*ppSymmetricKey)->setKeyBits(secret))
+ {
+ delete *ppSymmetricKey;
+ *ppSymmetricKey = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+unsigned long OSSLDH::getMinKeySize()
+{
+#ifdef WITH_FIPS
+ // OPENSSL_DH_FIPS_MIN_MODULUS_BITS is 1024
+ return 1024;
+#else
+ return 512;
+#endif
+}
+
+unsigned long OSSLDH::getMaxKeySize()
+{
+ return OPENSSL_DH_MAX_MODULUS_BITS;
+}
+
+bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/)
+{
+ if ((ppParams == NULL) || (parameters == NULL))
+ {
+ return false;
+ }
+
+ size_t bitLen = (size_t) parameters;
+
+ if (bitLen < getMinKeySize() || bitLen > getMaxKeySize())
+ {
+ ERROR_MSG("This DH key size is not supported");
+
+ return false;
+ }
+
+ DH* dh = DH_new();
+ if (dh == NULL)
+ {
+ ERROR_MSG("Failed to create DH object");
+
+ return false;
+ }
+
+ if (!DH_generate_parameters_ex(dh, bitLen, 2, NULL))
+ {
+ ERROR_MSG("Failed to generate %d bit DH parameters", bitLen);
+
+ DH_free(dh);
+
+ return false;
+ }
+
+ // Store the DH parameters
+ DHParameters* params = new DHParameters();
+
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_g = NULL;
+
+ DH_get0_pqg(dh, &bn_p, NULL, &bn_g);
+ ByteString p = OSSL::bn2ByteString(bn_p); params->setP(p);
+ ByteString g = OSSL::bn2ByteString(bn_g); params->setG(g);
+
+ *ppParams = params;
+
+ DH_free(dh);
+
+ return true;
+}
+
+bool OSSLDH::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLDHKeyPair* kp = new OSSLDHKeyPair();
+
+ bool rv = true;
+
+ if (!((DHPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((DHPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLDH::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLDHPublicKey* pub = new OSSLDHPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLDH::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLDHPrivateKey* priv = new OSSLDHPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLDH::newPublicKey()
+{
+ return (PublicKey*) new OSSLDHPublicKey();
+}
+
+PrivateKey* OSSLDH::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLDHPrivateKey();
+}
+
+AsymmetricParameters* OSSLDH::newParameters()
+{
+ return (AsymmetricParameters*) new DHParameters();
+}
+
+bool OSSLDH::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ DHParameters* params = new DHParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDH.h b/SoftHSMv2/src/lib/crypto/OSSLDH.h
new file mode 100644
index 0000000..d611aee
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDH.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDH.h
+
+ OpenSSL Diffie-Hellman asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDH_H
+#define _SOFTHSM_V2_OSSLDH_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <openssl/dh.h>
+
+class OSSLDH : public AsymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~OSSLDH() { }
+
+ // Signing functions
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL);
+ virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_OSSLDH_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.cpp
new file mode 100644
index 0000000..4865553
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDHKeyPair.cpp
+
+ OpenSSL Diffie-Hellman key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDHKeyPair.h"
+
+// Set the public key
+void OSSLDHKeyPair::setPublicKey(OSSLDHPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void OSSLDHKeyPair::setPrivateKey(OSSLDHPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* OSSLDHKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* OSSLDHKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* OSSLDHKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* OSSLDHKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.h
new file mode 100644
index 0000000..320d5ab
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDHKeyPair.h
+
+ OpenSSL Diffie-Hellman key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDHKEYPAIR_H
+#define _SOFTHSM_V2_OSSLDHKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "OSSLDHPublicKey.h"
+#include "OSSLDHPrivateKey.h"
+
+class OSSLDHKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(OSSLDHPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(OSSLDHPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ OSSLDHPublicKey pubKey;
+
+ // The private key
+ OSSLDHPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDHKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.cpp
new file mode 100644
index 0000000..5571a88
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDHPrivateKey.cpp
+
+ OpenSSL Diffie-Hellman private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLComp.h"
+#include "OSSLDHPrivateKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <openssl/x509.h>
+#ifdef WITH_FIPS
+#include <openssl/fips.h>
+#endif
+#include <string.h>
+
+// Constructors
+OSSLDHPrivateKey::OSSLDHPrivateKey()
+{
+ dh = NULL;
+}
+
+OSSLDHPrivateKey::OSSLDHPrivateKey(const DH* inDH)
+{
+ dh = NULL;
+
+ setFromOSSL(inDH);
+}
+
+// Destructor
+OSSLDHPrivateKey::~OSSLDHPrivateKey()
+{
+ DH_free(dh);
+}
+
+// The type
+/*static*/ const char* OSSLDHPrivateKey::type = "OpenSSL DH Private Key";
+
+// Set from OpenSSL representation
+void OSSLDHPrivateKey::setFromOSSL(const DH* inDH)
+{
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_g = NULL;
+ const BIGNUM* bn_priv_key = NULL;
+
+ DH_get0_pqg(inDH, &bn_p, NULL, &bn_g);
+ DH_get0_key(inDH, NULL, &bn_priv_key);
+
+ if (bn_p)
+ {
+ ByteString inP = OSSL::bn2ByteString(bn_p);
+ setP(inP);
+ }
+ if (bn_g)
+ {
+ ByteString inG = OSSL::bn2ByteString(bn_g);
+ setG(inG);
+ }
+ if (bn_priv_key)
+ {
+ ByteString inX = OSSL::bn2ByteString(bn_priv_key);
+ setX(inX);
+ }
+}
+
+// Check if the key is of the given type
+bool OSSLDHPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the DH private key components
+void OSSLDHPrivateKey::setX(const ByteString& inX)
+{
+ DHPrivateKey::setX(inX);
+
+ if (dh)
+ {
+ DH_free(dh);
+ dh = NULL;
+ }
+}
+
+
+// Setters for the DH public key components
+void OSSLDHPrivateKey::setP(const ByteString& inP)
+{
+ DHPrivateKey::setP(inP);
+
+ if (dh)
+ {
+ DH_free(dh);
+ dh = NULL;
+ }
+}
+
+void OSSLDHPrivateKey::setG(const ByteString& inG)
+{
+ DHPrivateKey::setG(inG);
+
+ if (dh)
+ {
+ DH_free(dh);
+ dh = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString OSSLDHPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ if (dh == NULL) createOSSLKey();
+ if (dh == NULL) return der;
+ EVP_PKEY* pkey = EVP_PKEY_new();
+ if (pkey == NULL) return der;
+ if (!EVP_PKEY_set1_DH(pkey, dh))
+ {
+ EVP_PKEY_free(pkey);
+ return der;
+ }
+ PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey);
+ EVP_PKEY_free(pkey);
+ if (p8inf == NULL) return der;
+ int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL);
+ if (len < 0)
+ {
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return der;
+ }
+ der.resize(len);
+ unsigned char* priv = &der[0];
+ int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (len2 != len) der.wipe();
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool OSSLDHPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ int len = ber.size();
+ if (len <= 0) return false;
+ const unsigned char* priv = ber.const_byte_str();
+ PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len);
+ if (p8 == NULL) return false;
+ EVP_PKEY* pkey = EVP_PKCS82PKEY(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (pkey == NULL) return false;
+ DH* key = EVP_PKEY_get1_DH(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL) return false;
+ setFromOSSL(key);
+ DH_free(key);
+ return true;
+}
+
+// Retrieve the OpenSSL representation of the key
+DH* OSSLDHPrivateKey::getOSSLKey()
+{
+ if (dh == NULL) createOSSLKey();
+
+ return dh;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLDHPrivateKey::createOSSLKey()
+{
+ if (dh != NULL) return;
+
+ BN_CTX *ctx = BN_CTX_new();
+ if (ctx == NULL)
+ {
+ ERROR_MSG("Could not create BN_CTX");
+ return;
+ }
+
+ dh = DH_new();
+ if (dh == NULL)
+ {
+ ERROR_MSG("Could not create DH object");
+ return;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ DH_set_method(dh, FIPS_dh_openssl());
+ else
+ DH_set_method(dh, DH_OpenSSL());
+#else
+ DH_set_method(dh, DH_OpenSSL());
+#endif
+
+#else
+ DH_set_method(dh, DH_OpenSSL());
+#endif
+
+ BIGNUM* bn_p = OSSL::byteString2bn(p);
+ BIGNUM* bn_g = OSSL::byteString2bn(g);
+ BIGNUM* bn_priv_key = OSSL::byteString2bn(x);
+ BIGNUM* bn_pub_key = BN_new();
+
+ BN_mod_exp(bn_pub_key, bn_g, bn_priv_key, bn_p, ctx);
+ BN_CTX_free(ctx);
+
+ DH_set0_pqg(dh, bn_p, NULL, bn_g);
+ DH_set0_key(dh, bn_pub_key, bn_priv_key);
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.h
new file mode 100644
index 0000000..2cf8599
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDHPrivateKey.h
+
+ OpenSSL Diffie-Hellman private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDHPRIVATEKEY_H
+#define _SOFTHSM_V2_OSSLDHPRIVATEKEY_H
+
+#include "config.h"
+#include "DHPrivateKey.h"
+#include <openssl/dh.h>
+
+class OSSLDHPrivateKey : public DHPrivateKey
+{
+public:
+ // Constructors
+ OSSLDHPrivateKey();
+
+ OSSLDHPrivateKey(const DH* inDH);
+
+ // Destructor
+ virtual ~OSSLDHPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the DH private key components
+ virtual void setX(const ByteString& inX);
+
+ // Setters for the DH public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setG(const ByteString& inG);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const DH* inDH);
+
+ // Retrieve the OpenSSL representation of the key
+ DH* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ DH* dh;
+
+ // Create the OpenSSL representation of the key
+ void createOSSLKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLDHPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.cpp
new file mode 100644
index 0000000..e261726
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDHPublicKey.cpp
+
+ OpenSSL Diffie-Hellman public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLComp.h"
+#include "OSSLDHPublicKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#ifdef WITH_FIPS
+#include <openssl/fips.h>
+#endif
+#include <string.h>
+
+// Constructors
+OSSLDHPublicKey::OSSLDHPublicKey()
+{
+ dh = NULL;
+}
+
+OSSLDHPublicKey::OSSLDHPublicKey(const DH* inDH)
+{
+ dh = NULL;
+
+ setFromOSSL(inDH);
+}
+
+// Destructor
+OSSLDHPublicKey::~OSSLDHPublicKey()
+{
+ DH_free(dh);
+}
+
+// The type
+/*static*/ const char* OSSLDHPublicKey::type = "OpenSSL DH Public Key";
+
+// Set from OpenSSL representation
+void OSSLDHPublicKey::setFromOSSL(const DH* inDH)
+{
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_g = NULL;
+ const BIGNUM* bn_pub_key = NULL;
+
+ DH_get0_pqg(inDH, &bn_p, NULL, &bn_g);
+ DH_get0_key(inDH, &bn_pub_key, NULL);
+
+ if (bn_p)
+ {
+ ByteString inP = OSSL::bn2ByteString(bn_p);
+ setP(inP);
+ }
+ if (bn_g)
+ {
+ ByteString inG = OSSL::bn2ByteString(bn_g);
+ setG(inG);
+ }
+ if (bn_pub_key)
+ {
+ ByteString inY = OSSL::bn2ByteString(bn_pub_key);
+ setY(inY);
+ }
+}
+
+// Check if the key is of the given type
+bool OSSLDHPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the DH public key components
+void OSSLDHPublicKey::setP(const ByteString& inP)
+{
+ DHPublicKey::setP(inP);
+
+ if (dh)
+ {
+ DH_free(dh);
+ dh = NULL;
+ }
+}
+
+void OSSLDHPublicKey::setG(const ByteString& inG)
+{
+ DHPublicKey::setG(inG);
+
+ if (dh)
+ {
+ DH_free(dh);
+ dh = NULL;
+ }
+}
+
+void OSSLDHPublicKey::setY(const ByteString& inY)
+{
+ DHPublicKey::setY(inY);
+
+ if (dh)
+ {
+ DH_free(dh);
+ dh = NULL;
+ }
+}
+
+// Retrieve the OpenSSL representation of the key
+DH* OSSLDHPublicKey::getOSSLKey()
+{
+ if (dh == NULL) createOSSLKey();
+
+ return dh;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLDHPublicKey::createOSSLKey()
+{
+ if (dh != NULL) return;
+
+ dh = DH_new();
+ if (dh == NULL)
+ {
+ ERROR_MSG("Could not create DH object");
+ return;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ DH_set_method(dh, FIPS_dh_openssl());
+ else
+ DH_set_method(dh, DH_OpenSSL());
+#else
+ DH_set_method(dh, DH_OpenSSL());
+#endif
+
+#else
+ DH_set_method(dh, DH_OpenSSL());
+#endif
+
+ BIGNUM* bn_p = OSSL::byteString2bn(p);
+ BIGNUM* bn_g = OSSL::byteString2bn(g);
+ BIGNUM* bn_pub_key = OSSL::byteString2bn(y);
+
+ DH_set0_pqg(dh, bn_p, NULL, bn_g);
+ DH_set0_key(dh, bn_pub_key, NULL);
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.h
new file mode 100644
index 0000000..9f5eed8
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDHPublicKey.h
+
+ OpenSSL Diffie-Hellman public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDHPUBLICKEY_H
+#define _SOFTHSM_V2_OSSLDHPUBLICKEY_H
+
+#include "config.h"
+#include "DHPublicKey.h"
+#include <openssl/dh.h>
+
+class OSSLDHPublicKey : public DHPublicKey
+{
+public:
+ // Constructors
+ OSSLDHPublicKey();
+
+ OSSLDHPublicKey(const DH* inDH);
+
+ // Destructor
+ virtual ~OSSLDHPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the DH public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setG(const ByteString& inG);
+ virtual void setY(const ByteString& inY);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const DH* inDH);
+
+ // Retrieve the OpenSSL representation of the key
+ DH* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ DH* dh;
+
+ // Create the OpenSSL representation of the key
+ void createOSSLKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLDHPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSA.cpp b/SoftHSMv2/src/lib/crypto/OSSLDSA.cpp
new file mode 100644
index 0000000..06b5d50
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDSA.cpp
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSA.cpp
+
+ OpenSSL DSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDSA.h"
+#include "CryptoFactory.h"
+#include "DSAParameters.h"
+#include "OSSLDSAKeyPair.h"
+#include "OSSLComp.h"
+#include "OSSLUtil.h"
+#include <algorithm>
+#include <openssl/dsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+// Constructor
+OSSLDSA::OSSLDSA()
+{
+ pCurrentHash = NULL;
+}
+
+// Destructor
+OSSLDSA::~OSSLDSA()
+{
+ if (pCurrentHash != NULL)
+ {
+ delete pCurrentHash;
+ }
+}
+
+// Signing functions
+bool OSSLDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (mechanism == AsymMech::DSA)
+ {
+ // Separate implementation for DSA signing without hash computation
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLDSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ OSSLDSAPrivateKey* pk = (OSSLDSAPrivateKey*) privateKey;
+ DSA* dsa = pk->getOSSLKey();
+
+ // Perform the signature operation
+ unsigned int sigLen = pk->getOutputLength();
+ signature.resize(sigLen);
+ memset(&signature[0], 0, sigLen);
+ int dLen = dataToSign.size();
+ DSA_SIG* sig = DSA_do_sign(dataToSign.const_byte_str(), dLen, dsa);
+ if (sig == NULL)
+ return false;
+ // Store the 2 values with padding
+ const BIGNUM* bn_r = NULL;
+ const BIGNUM* bn_s = NULL;
+ DSA_SIG_get0(sig, &bn_r, &bn_s);
+ BN_bn2bin(bn_r, &signature[sigLen / 2 - BN_num_bytes(bn_r)]);
+ BN_bn2bin(bn_s, &signature[sigLen - BN_num_bytes(bn_s)]);
+ DSA_SIG_free(sig);
+ return true;
+ }
+ else
+ {
+ // Call default implementation
+ return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
+ }
+}
+
+bool OSSLDSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLDSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ HashAlgo::Type hash = HashAlgo::Unknown;
+
+ switch (mechanism)
+ {
+ case AsymMech::DSA_SHA1:
+ hash = HashAlgo::SHA1;
+ break;
+ case AsymMech::DSA_SHA224:
+ hash = HashAlgo::SHA224;
+ break;
+ case AsymMech::DSA_SHA256:
+ hash = HashAlgo::SHA256;
+ break;
+ case AsymMech::DSA_SHA384:
+ hash = HashAlgo::SHA384;
+ break;
+ case AsymMech::DSA_SHA512:
+ hash = HashAlgo::SHA512;
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash);
+
+ if (pCurrentHash == NULL)
+ {
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLDSA::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ if (!pCurrentHash->hashUpdate(dataToSign))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLDSA::signFinal(ByteString& signature)
+{
+ // Save necessary state before calling super class signFinal
+ OSSLDSAPrivateKey* pk = (OSSLDSAPrivateKey*) currentPrivateKey;
+
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString hash;
+
+ bool bFirstResult = pCurrentHash->hashFinal(hash);
+
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (!bFirstResult)
+ {
+ return false;
+ }
+
+ DSA* dsa = pk->getOSSLKey();
+
+ // Perform the signature operation
+ unsigned int sigLen = pk->getOutputLength();
+ signature.resize(sigLen);
+ memset(&signature[0], 0, sigLen);
+ DSA_SIG* sig = DSA_do_sign(&hash[0], hash.size(), dsa);
+ if (sig == NULL)
+ return false;
+ // Store the 2 values with padding
+ const BIGNUM* bn_r = NULL;
+ const BIGNUM* bn_s = NULL;
+ DSA_SIG_get0(sig, &bn_r, &bn_s);
+ BN_bn2bin(bn_r, &signature[sigLen / 2 - BN_num_bytes(bn_r)]);
+ BN_bn2bin(bn_s, &signature[sigLen - BN_num_bytes(bn_s)]);
+ DSA_SIG_free(sig);
+ return true;
+}
+
+// Verification functions
+bool OSSLDSA::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (mechanism == AsymMech::DSA)
+ {
+ // Separate implementation for DSA verification without hash computation
+
+ // Check if the private key is the right type
+ if (!publicKey->isOfType(OSSLDSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Perform the verify operation
+ OSSLDSAPublicKey* pk = (OSSLDSAPublicKey*) publicKey;
+ unsigned int sigLen = pk->getOutputLength();
+ if (signature.size() != sigLen)
+ return false;
+ DSA_SIG* sig = DSA_SIG_new();
+ if (sig == NULL)
+ return false;
+ const unsigned char *s = signature.const_byte_str();
+ BIGNUM* bn_r = BN_bin2bn(s, sigLen / 2, NULL);
+ BIGNUM* bn_s = BN_bin2bn(s + sigLen / 2, sigLen / 2, NULL);
+ if (bn_r == NULL || bn_s == NULL ||
+ !DSA_SIG_set0(sig, bn_r, bn_s))
+ {
+ DSA_SIG_free(sig);
+ return false;
+ }
+ int dLen = originalData.size();
+ int ret = DSA_do_verify(originalData.const_byte_str(), dLen, sig, pk->getOSSLKey());
+ if (ret != 1)
+ {
+ if (ret < 0)
+ ERROR_MSG("DSA verify failed (0x%08X)", ERR_get_error());
+
+ DSA_SIG_free(sig);
+ return false;
+ }
+
+ DSA_SIG_free(sig);
+ return true;
+ }
+ else
+ {
+ // Call the generic function
+ return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen);
+ }
+}
+
+bool OSSLDSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!publicKey->isOfType(OSSLDSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ HashAlgo::Type hash = HashAlgo::Unknown;
+
+ switch (mechanism)
+ {
+ case AsymMech::DSA_SHA1:
+ hash = HashAlgo::SHA1;
+ break;
+ case AsymMech::DSA_SHA224:
+ hash = HashAlgo::SHA224;
+ break;
+ case AsymMech::DSA_SHA256:
+ hash = HashAlgo::SHA256;
+ break;
+ case AsymMech::DSA_SHA384:
+ hash = HashAlgo::SHA384;
+ break;
+ case AsymMech::DSA_SHA512:
+ hash = HashAlgo::SHA512;
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash);
+
+
+ if (pCurrentHash == NULL)
+ {
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ if (!pCurrentHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLDSA::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ if (!pCurrentHash->hashUpdate(originalData))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLDSA::verifyFinal(const ByteString& signature)
+{
+ // Save necessary state before calling super class verifyFinal
+ OSSLDSAPublicKey* pk = (OSSLDSAPublicKey*) currentPublicKey;
+
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString hash;
+
+ bool bFirstResult = pCurrentHash->hashFinal(hash);
+
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (!bFirstResult)
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+ unsigned int sigLen = pk->getOutputLength();
+ if (signature.size() != sigLen)
+ return false;
+ DSA_SIG* sig = DSA_SIG_new();
+ if (sig == NULL)
+ return false;
+ const unsigned char *s = signature.const_byte_str();
+ BIGNUM* bn_r = BN_bin2bn(s, sigLen / 2, NULL);
+ BIGNUM* bn_s = BN_bin2bn(s + sigLen / 2, sigLen / 2, NULL);
+ if (bn_r == NULL || bn_s == NULL ||
+ !DSA_SIG_set0(sig, bn_r, bn_s))
+ {
+ DSA_SIG_free(sig);
+ return false;
+ }
+ int ret = DSA_do_verify(&hash[0], hash.size(), sig, pk->getOSSLKey());
+ if (ret != 1)
+ {
+ if (ret < 0)
+ ERROR_MSG("DSA verify failed (0x%08X)", ERR_get_error());
+
+ DSA_SIG_free(sig);
+ return false;
+ }
+
+ DSA_SIG_free(sig);
+ return true;
+}
+
+// Encryption functions
+bool OSSLDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("DSA does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool OSSLDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("DSA does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool OSSLDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(DSAParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for DSA key generation");
+
+ return false;
+ }
+
+ DSAParameters* params = (DSAParameters*) parameters;
+
+ // Generate the key-pair
+ DSA* dsa = DSA_new();
+ if (dsa == NULL)
+ {
+ ERROR_MSG("Failed to instantiate OpenSSL DSA object");
+
+ return false;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+ DSA_set_method(dsa, DSA_get_default_method());
+
+ BIGNUM* bn_p = OSSL::byteString2bn(params->getP());
+ BIGNUM* bn_q = OSSL::byteString2bn(params->getQ());
+ BIGNUM* bn_g = OSSL::byteString2bn(params->getG());
+ DSA_set0_pqg(dsa, bn_p, bn_q, bn_g);
+
+ if (DSA_generate_key(dsa) != 1)
+ {
+ ERROR_MSG("DSA key generation failed (0x%08X)", ERR_get_error());
+
+ DSA_free(dsa);
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ OSSLDSAKeyPair* kp = new OSSLDSAKeyPair();
+
+ ((OSSLDSAPublicKey*) kp->getPublicKey())->setFromOSSL(dsa);
+ ((OSSLDSAPrivateKey*) kp->getPrivateKey())->setFromOSSL(dsa);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ DSA_free(dsa);
+
+ return true;
+}
+
+unsigned long OSSLDSA::getMinKeySize()
+{
+#ifdef WITH_FIPS
+ // OPENSSL_DSA_FIPS_MIN_MODULUS_BITS is 1024
+ return 1024;
+#else
+ return 512;
+#endif
+}
+
+unsigned long OSSLDSA::getMaxKeySize()
+{
+ return OPENSSL_DSA_MAX_MODULUS_BITS;
+}
+
+bool OSSLDSA::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/)
+{
+ if ((ppParams == NULL) || (parameters == NULL))
+ {
+ return false;
+ }
+
+ size_t bitLen = (size_t) parameters;
+
+ if (bitLen < getMinKeySize() || bitLen > getMaxKeySize())
+ {
+ ERROR_MSG("This DSA key size is not supported");
+
+ return false;
+ }
+
+ DSA* dsa = DSA_new();
+
+ if (dsa == NULL ||
+ !DSA_generate_parameters_ex(dsa, bitLen, NULL, 0, NULL, NULL, NULL))
+ {
+ ERROR_MSG("Failed to generate %d bit DSA parameters", bitLen);
+
+ return false;
+ }
+
+ // Store the DSA parameters
+ DSAParameters* params = new DSAParameters();
+
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_q = NULL;
+ const BIGNUM* bn_g = NULL;
+ DSA_get0_pqg(dsa, &bn_p, &bn_q, &bn_g);
+
+ ByteString p = OSSL::bn2ByteString(bn_p); params->setP(p);
+ ByteString q = OSSL::bn2ByteString(bn_q); params->setQ(q);
+ ByteString g = OSSL::bn2ByteString(bn_g); params->setG(g);
+
+ *ppParams = params;
+
+ DSA_free(dsa);
+
+ return true;
+}
+
+bool OSSLDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLDSAKeyPair* kp = new OSSLDSAKeyPair();
+
+ bool rv = true;
+
+ if (!((DSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((DSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLDSAPublicKey* pub = new OSSLDSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLDSAPrivateKey* priv = new OSSLDSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLDSA::newPublicKey()
+{
+ return (PublicKey*) new OSSLDSAPublicKey();
+}
+
+PrivateKey* OSSLDSA::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLDSAPrivateKey();
+}
+
+AsymmetricParameters* OSSLDSA::newParameters()
+{
+ return (AsymmetricParameters*) new DSAParameters();
+}
+
+bool OSSLDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ DSAParameters* params = new DSAParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSA.h b/SoftHSMv2/src/lib/crypto/OSSLDSA.h
new file mode 100644
index 0000000..1fb2b1e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDSA.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSA.h
+
+ OpenSSL DSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDSA_H
+#define _SOFTHSM_V2_OSSLDSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include <openssl/dsa.h>
+
+class OSSLDSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ OSSLDSA();
+
+ // Destructor
+ virtual ~OSSLDSA();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ HashAlgorithm* pCurrentHash;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSA_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.cpp
new file mode 100644
index 0000000..aba56f1
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAKeyPair.cpp
+
+ OpenSSL DSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDSAKeyPair.h"
+
+// Set the public key
+void OSSLDSAKeyPair::setPublicKey(OSSLDSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void OSSLDSAKeyPair::setPrivateKey(OSSLDSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* OSSLDSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* OSSLDSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* OSSLDSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* OSSLDSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.h
new file mode 100644
index 0000000..6a0bdf2
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAKeyPair.h
+
+ OpenSSL DSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDSAKEYPAIR_H
+#define _SOFTHSM_V2_OSSLDSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "OSSLDSAPublicKey.h"
+#include "OSSLDSAPrivateKey.h"
+
+class OSSLDSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(OSSLDSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(OSSLDSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ OSSLDSAPublicKey pubKey;
+
+ // The private key
+ OSSLDSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.cpp
new file mode 100644
index 0000000..527e041
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAPrivateKey.cpp
+
+ OpenSSL DSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLComp.h"
+#include "OSSLDSAPrivateKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <openssl/x509.h>
+#ifdef WITH_FIPS
+#include <openssl/fips.h>
+#endif
+#include <string.h>
+
+// Constructors
+OSSLDSAPrivateKey::OSSLDSAPrivateKey()
+{
+ dsa = NULL;
+}
+
+OSSLDSAPrivateKey::OSSLDSAPrivateKey(const DSA* inDSA)
+{
+ dsa = NULL;
+
+ setFromOSSL(inDSA);
+}
+
+// Destructor
+OSSLDSAPrivateKey::~OSSLDSAPrivateKey()
+{
+ DSA_free(dsa);
+}
+
+// The type
+/*static*/ const char* OSSLDSAPrivateKey::type = "OpenSSL DSA Private Key";
+
+// Set from OpenSSL representation
+void OSSLDSAPrivateKey::setFromOSSL(const DSA* inDSA)
+{
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_q = NULL;
+ const BIGNUM* bn_g = NULL;
+ const BIGNUM* bn_priv_key = NULL;
+
+ DSA_get0_pqg(inDSA, &bn_p, &bn_q, &bn_g);
+ DSA_get0_key(inDSA, NULL, &bn_priv_key);
+
+ if (bn_p)
+ {
+ ByteString inP = OSSL::bn2ByteString(bn_p);
+ setP(inP);
+ }
+ if (bn_q)
+ {
+ ByteString inQ = OSSL::bn2ByteString(bn_q);
+ setQ(inQ);
+ }
+ if (bn_g)
+ {
+ ByteString inG = OSSL::bn2ByteString(bn_g);
+ setG(inG);
+ }
+ if (bn_priv_key)
+ {
+ ByteString inX = OSSL::bn2ByteString(bn_priv_key);
+ setX(inX);
+ }
+}
+
+// Check if the key is of the given type
+bool OSSLDSAPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the DSA private key components
+void OSSLDSAPrivateKey::setX(const ByteString& inX)
+{
+ DSAPrivateKey::setX(inX);
+
+ if (dsa)
+ {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+}
+
+
+// Setters for the DSA domain parameters
+void OSSLDSAPrivateKey::setP(const ByteString& inP)
+{
+ DSAPrivateKey::setP(inP);
+
+ if (dsa)
+ {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+}
+
+void OSSLDSAPrivateKey::setQ(const ByteString& inQ)
+{
+ DSAPrivateKey::setQ(inQ);
+
+ if (dsa)
+ {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+}
+
+void OSSLDSAPrivateKey::setG(const ByteString& inG)
+{
+ DSAPrivateKey::setG(inG);
+
+ if (dsa)
+ {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString OSSLDSAPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ if (dsa == NULL) createOSSLKey();
+ if (dsa == NULL) return der;
+ EVP_PKEY* pkey = EVP_PKEY_new();
+ if (pkey == NULL) return der;
+ if (!EVP_PKEY_set1_DSA(pkey, dsa))
+ {
+ EVP_PKEY_free(pkey);
+ return der;
+ }
+ PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey);
+ EVP_PKEY_free(pkey);
+ if (p8inf == NULL) return der;
+ int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL);
+ if (len < 0)
+ {
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return der;
+ }
+ der.resize(len);
+ unsigned char* priv = &der[0];
+ int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (len2 != len) der.wipe();
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool OSSLDSAPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ int len = ber.size();
+ if (len <= 0) return false;
+ const unsigned char* priv = ber.const_byte_str();
+ PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len);
+ if (p8 == NULL) return false;
+ EVP_PKEY* pkey = EVP_PKCS82PKEY(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (pkey == NULL) return false;
+ DSA* key = EVP_PKEY_get1_DSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL) return false;
+ setFromOSSL(key);
+ DSA_free(key);
+ return true;
+}
+
+// Retrieve the OpenSSL representation of the key
+DSA* OSSLDSAPrivateKey::getOSSLKey()
+{
+ if (dsa == NULL) createOSSLKey();
+
+ return dsa;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLDSAPrivateKey::createOSSLKey()
+{
+ if (dsa != NULL) return;
+
+ BN_CTX *ctx = BN_CTX_new();
+ if (ctx == NULL)
+ {
+ ERROR_MSG("Could not create BN_CTX");
+ return;
+ }
+
+ dsa = DSA_new();
+ if (dsa == NULL)
+ {
+ ERROR_MSG("Could not create DSA object");
+ return;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ DSA_set_method(dsa, FIPS_dsa_openssl());
+ else
+ DSA_set_method(dsa, DSA_OpenSSL());
+#else
+ DSA_set_method(dsa, DSA_OpenSSL());
+#endif
+
+#else
+ DSA_set_method(dsa, DSA_OpenSSL());
+#endif
+
+ BIGNUM* bn_p = OSSL::byteString2bn(p);
+ BIGNUM* bn_q = OSSL::byteString2bn(q);
+ BIGNUM* bn_g = OSSL::byteString2bn(g);
+ BIGNUM* bn_priv_key = OSSL::byteString2bn(x);
+ BIGNUM* bn_pub_key = BN_new();
+
+ BN_mod_exp(bn_pub_key, bn_g, bn_priv_key, bn_p, ctx);
+ BN_CTX_free(ctx);
+
+ DSA_set0_pqg(dsa, bn_p, bn_q, bn_g);
+ DSA_set0_key(dsa, bn_pub_key, bn_priv_key);
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.h
new file mode 100644
index 0000000..0e7a9ef
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAPrivateKey.h
+
+ OpenSSL DSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDSAPRIVATEKEY_H
+#define _SOFTHSM_V2_OSSLDSAPRIVATEKEY_H
+
+#include "config.h"
+#include "DSAPrivateKey.h"
+#include <openssl/dsa.h>
+
+class OSSLDSAPrivateKey : public DSAPrivateKey
+{
+public:
+ // Constructors
+ OSSLDSAPrivateKey();
+
+ OSSLDSAPrivateKey(const DSA* inDSA);
+
+ // Destructor
+ virtual ~OSSLDSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the DSA private key components
+ virtual void setX(const ByteString& inX);
+
+ // Setters for the DSA domain parameters
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setG(const ByteString& inG);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const DSA* inDSA);
+
+ // Retrieve the OpenSSL representation of the key
+ DSA* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ DSA* dsa;
+
+ // Create the OpenSSL representation of the key
+ void createOSSLKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.cpp
new file mode 100644
index 0000000..38ecc79
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAPublicKey.cpp
+
+ OpenSSL DSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLDSAPublicKey.h"
+#include "OSSLComp.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#ifdef WITH_FIPS
+#include <openssl/fips.h>
+#endif
+#include <string.h>
+
+// Constructors
+OSSLDSAPublicKey::OSSLDSAPublicKey()
+{
+ dsa = NULL;
+}
+
+OSSLDSAPublicKey::OSSLDSAPublicKey(const DSA* inDSA)
+{
+ dsa = NULL;
+
+ setFromOSSL(inDSA);
+}
+
+// Destructor
+OSSLDSAPublicKey::~OSSLDSAPublicKey()
+{
+ DSA_free(dsa);
+}
+
+// The type
+/*static*/ const char* OSSLDSAPublicKey::type = "OpenSSL DSA Public Key";
+
+// Set from OpenSSL representation
+void OSSLDSAPublicKey::setFromOSSL(const DSA* inDSA)
+{
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_q = NULL;
+ const BIGNUM* bn_g = NULL;
+ const BIGNUM* bn_pub_key = NULL;
+
+ DSA_get0_pqg(inDSA, &bn_p, &bn_q, &bn_g);
+ DSA_get0_key(inDSA, &bn_pub_key, NULL);
+
+ if (bn_p)
+ {
+ ByteString inP = OSSL::bn2ByteString(bn_p);
+ setP(inP);
+ }
+ if (bn_q)
+ {
+ ByteString inQ = OSSL::bn2ByteString(bn_q);
+ setQ(inQ);
+ }
+ if (bn_g)
+ {
+ ByteString inG = OSSL::bn2ByteString(bn_g);
+ setG(inG);
+ }
+ if (bn_pub_key)
+ {
+ ByteString inY = OSSL::bn2ByteString(bn_pub_key);
+ setY(inY);
+ }
+}
+
+// Check if the key is of the given type
+bool OSSLDSAPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the DSA public key components
+void OSSLDSAPublicKey::setP(const ByteString& inP)
+{
+ DSAPublicKey::setP(inP);
+
+ if (dsa)
+ {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+}
+
+void OSSLDSAPublicKey::setQ(const ByteString& inQ)
+{
+ DSAPublicKey::setQ(inQ);
+
+ if (dsa)
+ {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+}
+
+void OSSLDSAPublicKey::setG(const ByteString& inG)
+{
+ DSAPublicKey::setG(inG);
+
+ if (dsa)
+ {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+}
+
+void OSSLDSAPublicKey::setY(const ByteString& inY)
+{
+ DSAPublicKey::setY(inY);
+
+ if (dsa)
+ {
+ DSA_free(dsa);
+ dsa = NULL;
+ }
+}
+
+// Retrieve the OpenSSL representation of the key
+DSA* OSSLDSAPublicKey::getOSSLKey()
+{
+ if (dsa == NULL) createOSSLKey();
+
+ return dsa;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLDSAPublicKey::createOSSLKey()
+{
+ if (dsa != NULL) return;
+
+ dsa = DSA_new();
+ if (dsa == NULL)
+ {
+ ERROR_MSG("Could not create DSA object");
+ return;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ DSA_set_method(dsa, FIPS_dsa_openssl());
+ else
+ DSA_set_method(dsa, DSA_OpenSSL());
+#else
+ DSA_set_method(dsa, DSA_OpenSSL());
+#endif
+
+#else
+ DSA_set_method(dsa, DSA_OpenSSL());
+#endif
+
+ BIGNUM* bn_p = OSSL::byteString2bn(p);
+ BIGNUM* bn_q = OSSL::byteString2bn(q);
+ BIGNUM* bn_g = OSSL::byteString2bn(g);
+ BIGNUM* bn_pub_key = OSSL::byteString2bn(y);
+
+ DSA_set0_pqg(dsa, bn_p, bn_q, bn_g);
+ DSA_set0_key(dsa, bn_pub_key, NULL);
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.h
new file mode 100644
index 0000000..b30d05c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLDSAPublicKey.h
+
+ OpenSSL DSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+#define _SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+
+#include "config.h"
+#include "DSAPublicKey.h"
+#include <openssl/dsa.h>
+
+class OSSLDSAPublicKey : public DSAPublicKey
+{
+public:
+ // Constructors
+ OSSLDSAPublicKey();
+
+ OSSLDSAPublicKey(const DSA* inDSA);
+
+ // Destructor
+ virtual ~OSSLDSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the DSA public key components
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setG(const ByteString& inG);
+ virtual void setY(const ByteString& inY);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const DSA* inDSA);
+
+ // Retrieve the OpenSSL representation of the key
+ DSA* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ DSA* dsa;
+
+ // Create the OpenSSL representation of the key
+ void createOSSLKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECDH.cpp b/SoftHSMv2/src/lib/crypto/OSSLECDH.cpp
new file mode 100644
index 0000000..e2abaeb
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECDH.cpp
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECDH.cpp
+
+ OpenSSL Diffie-Hellman asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "OSSLECDH.h"
+#include "CryptoFactory.h"
+#include "ECParameters.h"
+#include "OSSLECKeyPair.h"
+#include "OSSLUtil.h"
+#include <algorithm>
+#include <openssl/ecdh.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#ifdef WITH_FIPS
+#include <openssl/fips.h>
+#endif
+
+// Signing functions
+bool OSSLECDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("ECDH does not support signing");
+
+ return false;
+}
+
+bool OSSLECDH::signUpdate(const ByteString& /*dataToSign*/)
+{
+ ERROR_MSG("ECDH does not support signing");
+
+ return false;
+}
+
+bool OSSLECDH::signFinal(ByteString& /*signature*/)
+{
+ ERROR_MSG("ECDH does not support signing");
+
+ return false;
+}
+
+// Verification functions
+bool OSSLECDH::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("ECDH does not support verifying");
+
+ return false;
+}
+
+bool OSSLECDH::verifyUpdate(const ByteString& /*originalData*/)
+{
+ ERROR_MSG("ECDH does not support verifying");
+
+ return false;
+}
+
+bool OSSLECDH::verifyFinal(const ByteString& /*signature*/)
+{
+ ERROR_MSG("ECDH does not support verifying");
+
+ return false;
+}
+
+// Encryption functions
+bool OSSLECDH::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("ECDH does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool OSSLECDH::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("ECDH does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool OSSLECDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(ECParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for ECDH key generation");
+
+ return false;
+ }
+
+ ECParameters* params = (ECParameters*) parameters;
+
+ // Generate the key-pair
+ EC_KEY* eckey = EC_KEY_new();
+
+ if (eckey == NULL)
+ {
+ ERROR_MSG("Failed to instantiate OpenSSL ECDH object");
+
+ return false;
+ }
+
+ EC_GROUP* grp = OSSL::byteString2grp(params->getEC());
+ EC_KEY_set_group(eckey, grp);
+ EC_GROUP_free(grp);
+
+ if (!EC_KEY_generate_key(eckey))
+ {
+ ERROR_MSG("ECDH key generation failed (0x%08X)", ERR_get_error());
+
+ EC_KEY_free(eckey);
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ OSSLECKeyPair* kp = new OSSLECKeyPair();
+
+ ((OSSLECPublicKey*) kp->getPublicKey())->setFromOSSL(eckey);
+ ((OSSLECPrivateKey*) kp->getPrivateKey())->setFromOSSL(eckey);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ EC_KEY_free(eckey);
+
+ return true;
+}
+
+bool OSSLECDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
+{
+ // Check parameters
+ if ((ppSymmetricKey == NULL) ||
+ (publicKey == NULL) ||
+ (privateKey == NULL))
+ {
+ return false;
+ }
+
+ // Get keys
+ EC_KEY *pub = ((OSSLECPublicKey *)publicKey)->getOSSLKey();
+ EC_KEY *priv = ((OSSLECPrivateKey *)privateKey)->getOSSLKey();
+ if (pub == NULL || EC_KEY_get0_public_key(pub) == NULL || priv == NULL)
+ {
+ ERROR_MSG("Failed to get OpenSSL ECDH keys");
+
+ return false;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ {
+ ECDH_set_method(pub, FIPS_ecdh_openssl());
+ ECDH_set_method(priv, FIPS_ecdh_openssl());
+ }
+ else
+ {
+ ECDH_set_method(pub, ECDH_OpenSSL());
+ ECDH_set_method(priv, ECDH_OpenSSL());
+ }
+#else
+ ECDH_set_method(pub, ECDH_OpenSSL());
+ ECDH_set_method(priv, ECDH_OpenSSL());
+#endif
+
+#else
+ EC_KEY_set_method(pub, EC_KEY_OpenSSL());
+ EC_KEY_set_method(priv, EC_KEY_OpenSSL());
+#endif
+
+ // Derive the secret
+ ByteString secret, derivedSecret;
+ int size = ((OSSLECPublicKey *)publicKey)->getOrderLength();
+ secret.wipe(size);
+ derivedSecret.wipe(size);
+ int keySize = ECDH_compute_key(&derivedSecret[0], derivedSecret.size(), EC_KEY_get0_public_key(pub), priv, NULL);
+
+ if (keySize <= 0)
+ {
+ ERROR_MSG("ECDH key derivation failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+
+ // We compensate that OpenSSL removes leading zeros
+ memcpy(&secret[0] + size - keySize, &derivedSecret[0], keySize);
+
+ *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
+ if (*ppSymmetricKey == NULL)
+ return false;
+ if (!(*ppSymmetricKey)->setKeyBits(secret))
+ {
+ delete *ppSymmetricKey;
+ *ppSymmetricKey = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+unsigned long OSSLECDH::getMinKeySize()
+{
+ // Smallest EC group is secp112r1
+ return 112;
+}
+
+unsigned long OSSLECDH::getMaxKeySize()
+{
+ // Biggest EC group is secp521r1
+ return 521;
+}
+
+bool OSSLECDH::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLECKeyPair* kp = new OSSLECKeyPair();
+
+ bool rv = true;
+
+ if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLECDH::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLECPublicKey* pub = new OSSLECPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLECDH::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLECPrivateKey* priv = new OSSLECPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLECDH::newPublicKey()
+{
+ return (PublicKey*) new OSSLECPublicKey();
+}
+
+PrivateKey* OSSLECDH::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLECPrivateKey();
+}
+
+AsymmetricParameters* OSSLECDH::newParameters()
+{
+ return (AsymmetricParameters*) new ECParameters();
+}
+
+bool OSSLECDH::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ECParameters* params = new ECParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECDH.h b/SoftHSMv2/src/lib/crypto/OSSLECDH.h
new file mode 100644
index 0000000..2cafa6f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECDH.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECDH.h
+
+ OpenSSL ECDH asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLECDH_H
+#define _SOFTHSM_V2_OSSLECDH_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <openssl/ecdh.h>
+
+class OSSLECDH : public AsymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~OSSLECDH() { }
+
+ // Signing functions
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_OSSLECDH_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECDSA.cpp b/SoftHSMv2/src/lib/crypto/OSSLECDSA.cpp
new file mode 100644
index 0000000..7387367
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECDSA.cpp
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECDSA.cpp
+
+ OpenSSL ECDSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "OSSLECDSA.h"
+#include "CryptoFactory.h"
+#include "ECParameters.h"
+#include "OSSLECKeyPair.h"
+#include "OSSLComp.h"
+#include "OSSLUtil.h"
+#include <algorithm>
+#include <openssl/ecdsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#ifdef WITH_FIPS
+#include <openssl/fips.h>
+#endif
+#include <string.h>
+
+// Signing functions
+bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ if (mechanism != AsymMech::ECDSA)
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLECPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ OSSLECPrivateKey* pk = (OSSLECPrivateKey*) privateKey;
+ EC_KEY* eckey = pk->getOSSLKey();
+
+ if (eckey == NULL)
+ {
+ ERROR_MSG("Could not get the OpenSSL private key");
+
+ return false;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ ECDSA_set_method(eckey, FIPS_ecdsa_openssl());
+ else
+ ECDSA_set_method(eckey, ECDSA_OpenSSL());
+#else
+ ECDSA_set_method(eckey, ECDSA_OpenSSL());
+#endif
+
+#else
+ EC_KEY_set_method(eckey, EC_KEY_OpenSSL());
+#endif
+
+ // Perform the signature operation
+ size_t len = pk->getOrderLength();
+ if (len == 0)
+ {
+ ERROR_MSG("Could not get the order length");
+ return false;
+ }
+ signature.resize(2 * len);
+ memset(&signature[0], 0, 2 * len);
+ ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey);
+ if (sig == NULL)
+ {
+ ERROR_MSG("ECDSA sign failed (0x%08X)", ERR_get_error());
+ return false;
+ }
+ // Store the 2 values with padding
+ const BIGNUM* bn_r = NULL;
+ const BIGNUM* bn_s = NULL;
+ ECDSA_SIG_get0(sig, &bn_r, &bn_s);
+ BN_bn2bin(bn_r, &signature[len - BN_num_bytes(bn_r)]);
+ BN_bn2bin(bn_s, &signature[2 * len - BN_num_bytes(bn_s)]);
+ ECDSA_SIG_free(sig);
+ return true;
+}
+
+bool OSSLECDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("ECDSA does not support multi part signing");
+
+ return false;
+}
+
+bool OSSLECDSA::signUpdate(const ByteString& /*dataToSign*/)
+{
+ ERROR_MSG("ECDSA does not support multi part signing");
+
+ return false;
+}
+
+bool OSSLECDSA::signFinal(ByteString& /*signature*/)
+{
+ ERROR_MSG("ECDSA does not support multi part signing");
+
+ return false;
+}
+
+// Verification functions
+bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ if (mechanism != AsymMech::ECDSA)
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!publicKey->isOfType(OSSLECPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ OSSLECPublicKey* pk = (OSSLECPublicKey*) publicKey;
+ EC_KEY* eckey = pk->getOSSLKey();
+
+ if (eckey == NULL)
+ {
+ ERROR_MSG("Could not get the OpenSSL public key");
+
+ return false;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ ECDSA_set_method(eckey, FIPS_ecdsa_openssl());
+ else
+ ECDSA_set_method(eckey, ECDSA_OpenSSL());
+#else
+ ECDSA_set_method(eckey, ECDSA_OpenSSL());
+#endif
+
+#else
+ EC_KEY_set_method(eckey, EC_KEY_OpenSSL());
+#endif
+
+ // Perform the verify operation
+ size_t len = pk->getOrderLength();
+ if (len == 0)
+ {
+ ERROR_MSG("Could not get the order length");
+ return false;
+ }
+ if (signature.size() != 2 * len)
+ {
+ ERROR_MSG("Invalid buffer length");
+ return false;
+ }
+ ECDSA_SIG* sig = ECDSA_SIG_new();
+ if (sig == NULL)
+ {
+ ERROR_MSG("Could not create an ECDSA_SIG object");
+ return false;
+ }
+ const unsigned char *s = signature.const_byte_str();
+ BIGNUM* bn_r = BN_bin2bn(s, len, NULL);
+ BIGNUM* bn_s = BN_bin2bn(s + len, len, NULL);
+ if (bn_r == NULL || bn_s == NULL ||
+ !ECDSA_SIG_set0(sig, bn_r, bn_s))
+ {
+ ERROR_MSG("Could not add data to the ECDSA_SIG object");
+ ECDSA_SIG_free(sig);
+ return false;
+ }
+ int ret = ECDSA_do_verify(originalData.const_byte_str(), originalData.size(), sig, eckey);
+ if (ret != 1)
+ {
+ if (ret < 0)
+ ERROR_MSG("ECDSA verify failed (0x%08X)", ERR_get_error());
+
+ ECDSA_SIG_free(sig);
+ return false;
+ }
+
+ ECDSA_SIG_free(sig);
+ return true;
+}
+
+bool OSSLECDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("ECDSA does not support multi part verifying");
+
+ return false;
+}
+
+bool OSSLECDSA::verifyUpdate(const ByteString& /*originalData*/)
+{
+ ERROR_MSG("ECDSA does not support multi part verifying");
+
+ return false;
+}
+
+bool OSSLECDSA::verifyFinal(const ByteString& /*signature*/)
+{
+ ERROR_MSG("ECDSA does not support multi part verifying");
+
+ return false;
+}
+
+// Encryption functions
+bool OSSLECDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("ECDSA does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool OSSLECDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("ECDSA does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool OSSLECDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(ECParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for ECDSA key generation");
+
+ return false;
+ }
+
+ ECParameters* params = (ECParameters*) parameters;
+
+ // Generate the key-pair
+ EC_KEY* eckey = EC_KEY_new();
+ if (eckey == NULL)
+ {
+ ERROR_MSG("Failed to instantiate OpenSSL ECDSA object");
+
+ return false;
+ }
+
+ EC_GROUP* grp = OSSL::byteString2grp(params->getEC());
+ EC_KEY_set_group(eckey, grp);
+ EC_GROUP_free(grp);
+
+ if (!EC_KEY_generate_key(eckey))
+ {
+ ERROR_MSG("ECDSA key generation failed (0x%08X)", ERR_get_error());
+
+ EC_KEY_free(eckey);
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ OSSLECKeyPair* kp = new OSSLECKeyPair();
+
+ ((OSSLECPublicKey*) kp->getPublicKey())->setFromOSSL(eckey);
+ ((OSSLECPrivateKey*) kp->getPrivateKey())->setFromOSSL(eckey);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ EC_KEY_free(eckey);
+
+ return true;
+}
+
+unsigned long OSSLECDSA::getMinKeySize()
+{
+ // Smallest EC group is secp112r1
+ return 112;
+}
+
+unsigned long OSSLECDSA::getMaxKeySize()
+{
+ // Biggest EC group is secp521r1
+ return 521;
+}
+
+bool OSSLECDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLECKeyPair* kp = new OSSLECKeyPair();
+
+ bool rv = true;
+
+ if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLECDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLECPublicKey* pub = new OSSLECPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLECDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLECPrivateKey* priv = new OSSLECPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLECDSA::newPublicKey()
+{
+ return (PublicKey*) new OSSLECPublicKey();
+}
+
+PrivateKey* OSSLECDSA::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLECPrivateKey();
+}
+
+AsymmetricParameters* OSSLECDSA::newParameters()
+{
+ return (AsymmetricParameters*) new ECParameters();
+}
+
+bool OSSLECDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ECParameters* params = new ECParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECDSA.h b/SoftHSMv2/src/lib/crypto/OSSLECDSA.h
new file mode 100644
index 0000000..992fa40
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECDSA.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECDSA.h
+
+ OpenSSL ECDSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLECDSA_H
+#define _SOFTHSM_V2_OSSLECDSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <openssl/ecdsa.h>
+
+class OSSLECDSA : public AsymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~OSSLECDSA() { }
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_OSSLECDSA_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.cpp
new file mode 100644
index 0000000..2e55f8f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECKeyPair.cpp
+
+ OpenSSL Elliptic Curve key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "OSSLECKeyPair.h"
+
+// Set the public key
+void OSSLECKeyPair::setPublicKey(OSSLECPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void OSSLECKeyPair::setPrivateKey(OSSLECPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* OSSLECKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* OSSLECKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* OSSLECKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* OSSLECKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.h
new file mode 100644
index 0000000..ada9b8d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECKeyPair.h
+
+ OpenSSL Elliptic Curve key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLECKEYPAIR_H
+#define _SOFTHSM_V2_OSSLECKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "OSSLECPublicKey.h"
+#include "OSSLECPrivateKey.h"
+
+class OSSLECKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(OSSLECPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(OSSLECPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ OSSLECPublicKey pubKey;
+
+ // The private key
+ OSSLECPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLECKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.cpp
new file mode 100644
index 0000000..4f6b055
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECPrivateKey.cpp
+
+ OpenSSL EC private key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "OSSLECPrivateKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <openssl/x509.h>
+
+// Constructors
+OSSLECPrivateKey::OSSLECPrivateKey()
+{
+ eckey = EC_KEY_new();
+
+ // For PKCS#8 encoding
+ EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
+}
+
+OSSLECPrivateKey::OSSLECPrivateKey(const EC_KEY* inECKEY)
+{
+ eckey = EC_KEY_new();
+
+ // For PKCS#8 encoding
+ EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
+
+ setFromOSSL(inECKEY);
+}
+
+// Destructor
+OSSLECPrivateKey::~OSSLECPrivateKey()
+{
+ EC_KEY_free(eckey);
+}
+
+// The type
+/*static*/ const char* OSSLECPrivateKey::type = "OpenSSL EC Private Key";
+
+// Get the base point order length
+unsigned long OSSLECPrivateKey::getOrderLength() const
+{
+ const EC_GROUP* grp = EC_KEY_get0_group(eckey);
+ if (grp != NULL)
+ {
+ BIGNUM* order = BN_new();
+ if (order == NULL)
+ return 0;
+ if (!EC_GROUP_get_order(grp, order, NULL))
+ {
+ BN_clear_free(order);
+ return 0;
+ }
+ unsigned long len = BN_num_bytes(order);
+ BN_clear_free(order);
+ return len;
+ }
+ return 0;
+}
+
+// Set from OpenSSL representation
+void OSSLECPrivateKey::setFromOSSL(const EC_KEY* inECKEY)
+{
+ const EC_GROUP* grp = EC_KEY_get0_group(inECKEY);
+ if (grp != NULL)
+ {
+ ByteString inEC = OSSL::grp2ByteString(grp);
+ setEC(inEC);
+ }
+ const BIGNUM* pk = EC_KEY_get0_private_key(inECKEY);
+ if (pk != NULL)
+ {
+ ByteString inD = OSSL::bn2ByteString(pk);
+ setD(inD);
+ }
+}
+
+// Check if the key is of the given type
+bool OSSLECPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the EC private key components
+void OSSLECPrivateKey::setD(const ByteString& inD)
+{
+ ECPrivateKey::setD(inD);
+
+ BIGNUM* pk = OSSL::byteString2bn(inD);
+ EC_KEY_set_private_key(eckey, pk);
+ BN_clear_free(pk);
+}
+
+
+// Setters for the EC public key components
+void OSSLECPrivateKey::setEC(const ByteString& inEC)
+{
+ ECPrivateKey::setEC(inEC);
+
+ EC_GROUP* grp = OSSL::byteString2grp(inEC);
+ EC_KEY_set_group(eckey, grp);
+ EC_GROUP_free(grp);
+}
+
+// Encode into PKCS#8 DER
+ByteString OSSLECPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ if (eckey == NULL) return der;
+ EVP_PKEY* pkey = EVP_PKEY_new();
+ if (pkey == NULL) return der;
+ if (!EVP_PKEY_set1_EC_KEY(pkey, eckey))
+ {
+ EVP_PKEY_free(pkey);
+ return der;
+ }
+ PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey);
+ EVP_PKEY_free(pkey);
+ if (p8inf == NULL) return der;
+ int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL);
+ if (len < 0)
+ {
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return der;
+ }
+ der.resize(len);
+ unsigned char* priv = &der[0];
+ int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (len2 != len) der.wipe();
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool OSSLECPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ int len = ber.size();
+ if (len <= 0) return false;
+ const unsigned char* priv = ber.const_byte_str();
+ PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len);
+ if (p8 == NULL) return false;
+ EVP_PKEY* pkey = EVP_PKCS82PKEY(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (pkey == NULL) return false;
+ EC_KEY* key = EVP_PKEY_get1_EC_KEY(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL) return false;
+ setFromOSSL(key);
+ EC_KEY_free(key);
+ return true;
+}
+
+// Retrieve the OpenSSL representation of the key
+EC_KEY* OSSLECPrivateKey::getOSSLKey()
+{
+ return eckey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.h
new file mode 100644
index 0000000..152ad03
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECPrivateKey.h
+
+ OpenSSL Elliptic Curve private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLECPRIVATEKEY_H
+#define _SOFTHSM_V2_OSSLECPRIVATEKEY_H
+
+#include "config.h"
+#include "ECPrivateKey.h"
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+
+class OSSLECPrivateKey : public ECPrivateKey
+{
+public:
+ // Constructors
+ OSSLECPrivateKey();
+
+ OSSLECPrivateKey(const EC_KEY* inECKEY);
+
+ // Destructor
+ virtual ~OSSLECPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the EC private key components
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the EC public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const EC_KEY* inECKEY);
+
+ // Retrieve the OpenSSL representation of the key
+ EC_KEY* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ EC_KEY* eckey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLECPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.cpp
new file mode 100644
index 0000000..b2d80af
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECPublicKey.cpp
+
+ OpenSSL Elliptic Curve public key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_ECC
+#include "log.h"
+#include "OSSLECPublicKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <string.h>
+
+// Constructors
+OSSLECPublicKey::OSSLECPublicKey()
+{
+ eckey = EC_KEY_new();
+}
+
+OSSLECPublicKey::OSSLECPublicKey(const EC_KEY* inECKEY)
+{
+ eckey = EC_KEY_new();
+
+ setFromOSSL(inECKEY);
+}
+
+// Destructor
+OSSLECPublicKey::~OSSLECPublicKey()
+{
+ EC_KEY_free(eckey);
+}
+
+// The type
+/*static*/ const char* OSSLECPublicKey::type = "OpenSSL EC Public Key";
+
+// Get the base point order length
+unsigned long OSSLECPublicKey::getOrderLength() const
+{
+ const EC_GROUP* grp = EC_KEY_get0_group(eckey);
+ if (grp != NULL)
+ {
+ BIGNUM* order = BN_new();
+ if (order == NULL)
+ return 0;
+ if (!EC_GROUP_get_order(grp, order, NULL))
+ {
+ BN_clear_free(order);
+ return 0;
+ }
+ unsigned long len = BN_num_bytes(order);
+ BN_clear_free(order);
+ return len;
+ }
+ return 0;
+}
+
+// Set from OpenSSL representation
+void OSSLECPublicKey::setFromOSSL(const EC_KEY* inECKEY)
+{
+ const EC_GROUP* grp = EC_KEY_get0_group(inECKEY);
+ if (grp != NULL)
+ {
+ ByteString inEC = OSSL::grp2ByteString(grp);
+ setEC(inEC);
+ }
+ const EC_POINT* pub = EC_KEY_get0_public_key(inECKEY);
+ if (pub != NULL && grp != NULL)
+ {
+ ByteString inQ = OSSL::pt2ByteString(pub, grp);
+ setQ(inQ);
+ }
+}
+
+// Check if the key is of the given type
+bool OSSLECPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the EC public key components
+void OSSLECPublicKey::setEC(const ByteString& inEC)
+{
+ ECPublicKey::setEC(inEC);
+
+ EC_GROUP* grp = OSSL::byteString2grp(inEC);
+ EC_KEY_set_group(eckey, grp);
+ EC_GROUP_free(grp);
+}
+
+void OSSLECPublicKey::setQ(const ByteString& inQ)
+{
+ ECPublicKey::setQ(inQ);
+
+ EC_POINT* pub = OSSL::byteString2pt(inQ, EC_KEY_get0_group(eckey));
+ EC_KEY_set_public_key(eckey, pub);
+ EC_POINT_free(pub);
+}
+
+// Retrieve the OpenSSL representation of the key
+EC_KEY* OSSLECPublicKey::getOSSLKey()
+{
+ return eckey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.h
new file mode 100644
index 0000000..3fb4f35
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLECPublicKey.h
+
+ OpenSSL Elliptic Curve public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLECPUBLICKEY_H
+#define _SOFTHSM_V2_OSSLECPUBLICKEY_H
+
+#include "config.h"
+#include "ECPublicKey.h"
+#include <openssl/ec.h>
+
+class OSSLECPublicKey : public ECPublicKey
+{
+public:
+ // Constructors
+ OSSLECPublicKey();
+
+ OSSLECPublicKey(const EC_KEY* inECKEY);
+
+ // Destructor
+ virtual ~OSSLECPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the EC public key components
+ virtual void setEC(const ByteString& inEC);
+ virtual void setQ(const ByteString& inQ);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const EC_KEY* inECKEY);
+
+ // Retrieve the OpenSSL representation of the key
+ EC_KEY* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ EC_KEY* eckey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.cpp
new file mode 100644
index 0000000..27e29d9
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2017 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// TODO: Store context in securely allocated memory
+
+/*****************************************************************************
+ OSSLEVPCMacAlgorithm.cpp
+
+ OpenSSL CMAC algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLEVPCMacAlgorithm.h"
+#include "OSSLComp.h"
+#include <openssl/err.h>
+
+// Destructor
+OSSLEVPCMacAlgorithm::~OSSLEVPCMacAlgorithm()
+{
+ if (curCTX != NULL)
+ CMAC_CTX_free(curCTX);
+}
+
+// Signing functions
+bool OSSLEVPCMacAlgorithm::signInit(const SymmetricKey* key)
+{
+ // Call the superclass initialiser
+ if (!MacAlgorithm::signInit(key))
+ {
+ return false;
+ }
+
+ // Determine the cipher class
+ const EVP_CIPHER* cipher = getEVPCipher();
+ if (cipher == NULL)
+ {
+ ERROR_MSG("Invalid sign mac algorithm");
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ // Initialize the context
+ curCTX = CMAC_CTX_new();
+ if (curCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for CMAC_CTX");
+
+ return false;
+ }
+
+ // Initialize EVP signing
+ if (!CMAC_Init(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), cipher, NULL))
+ {
+ ERROR_MSG("CMAC_Init failed: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ CMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPCMacAlgorithm::signUpdate(const ByteString& dataToSign)
+{
+ if (!MacAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ if (dataToSign.size() == 0) return true;
+
+ if (!CMAC_Update(curCTX, dataToSign.const_byte_str(), dataToSign.size()))
+ {
+ ERROR_MSG("CMAC_Update failed");
+
+ CMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPCMacAlgorithm::signFinal(ByteString& signature)
+{
+ if (!MacAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ size_t outLen = getMacSize();
+ signature.resize(outLen);
+
+ if (!CMAC_Final(curCTX, &signature[0], &outLen))
+ {
+ ERROR_MSG("CMAC_Final failed");
+
+ CMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return false;
+ }
+
+ signature.resize(outLen);
+
+ CMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool OSSLEVPCMacAlgorithm::verifyInit(const SymmetricKey* key)
+{
+ // Call the superclass initialiser
+ if (!MacAlgorithm::verifyInit(key))
+ {
+ return false;
+ }
+
+ // Determine the cipher class
+ const EVP_CIPHER* cipher = getEVPCipher();
+ if (cipher == NULL)
+ {
+ ERROR_MSG("Invalid verify mac algorithm");
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ // Initialize the context
+ curCTX = CMAC_CTX_new();
+ if (curCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for CMAC_CTX");
+
+ return false;
+ }
+
+ // Initialize EVP signing
+ if (!CMAC_Init(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), cipher, NULL))
+ {
+ ERROR_MSG("CMAC_Init failed: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ CMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ MacAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPCMacAlgorithm::verifyUpdate(const ByteString& originalData)
+{
+ if (!MacAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ if (originalData.size() == 0) return true;
+
+ if (!CMAC_Update(curCTX, originalData.const_byte_str(), originalData.size()))
+ {
+ ERROR_MSG("CMAC_Update failed");
+
+ CMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ MacAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPCMacAlgorithm::verifyFinal(ByteString& signature)
+{
+ if (!MacAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString macResult;
+ size_t outLen = getMacSize();
+ macResult.resize(outLen);
+
+ if (!CMAC_Final(curCTX, &macResult[0], &outLen))
+ {
+ ERROR_MSG("CMAC_Final failed");
+
+ CMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return false;
+ }
+
+ CMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return macResult == signature;
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.h b/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.h
new file mode 100644
index 0000000..621e995
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEVPCMacAlgorithm.h
+
+ OpenSSL CMAC algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEVPCMACALGORITHM_H
+#define _SOFTHSM_V2_OSSLEVPCMACALGORITHM_H
+
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "MacAlgorithm.h"
+#include <openssl/evp.h>
+#include <openssl/cmac.h>
+
+class OSSLEVPCMacAlgorithm : public MacAlgorithm
+{
+public:
+ // Constructor
+ OSSLEVPCMacAlgorithm() {
+ curCTX = NULL;
+ };
+
+ // Destructor
+ ~OSSLEVPCMacAlgorithm();
+
+ // Signing functions
+ virtual bool signInit(const SymmetricKey* key);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(const SymmetricKey* key);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(ByteString& signature);
+
+ // Return the MAC size
+ virtual size_t getMacSize() const = 0;
+
+protected:
+ // Return the right cipher for the operation
+ virtual const EVP_CIPHER* getEVPCipher() const = 0;
+
+private:
+ // The current context
+ CMAC_CTX* curCTX;
+};
+
+#endif // !_SOFTHSM_V2_OSSLEVPCMACALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.cpp
new file mode 100644
index 0000000..a1b4f73
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEVPHashAlgorithm.cpp
+
+ Base class for OpenSSL hash algorithm classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include "OSSLComp.h"
+
+// Destructor
+OSSLEVPHashAlgorithm::~OSSLEVPHashAlgorithm()
+{
+ EVP_MD_CTX_free(curCTX);
+}
+
+// Hashing functions
+bool OSSLEVPHashAlgorithm::hashInit()
+{
+ if (!HashAlgorithm::hashInit())
+ {
+ return false;
+ }
+
+ // Initialize the context
+ curCTX = EVP_MD_CTX_new();
+ if (curCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for EVP_MD_CTX");
+
+ return false;
+ }
+
+ // Initialize EVP digesting
+ if (!EVP_DigestInit_ex(curCTX, getEVPHash(), NULL))
+ {
+ ERROR_MSG("EVP_DigestInit failed");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ HashAlgorithm::hashFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPHashAlgorithm::hashUpdate(const ByteString& data)
+{
+ if (!HashAlgorithm::hashUpdate(data))
+ {
+ return false;
+ }
+
+ // Continue digesting
+ if (data.size() == 0)
+ {
+ return true;
+ }
+
+ if (!EVP_DigestUpdate(curCTX, (unsigned char*) data.const_byte_str(), data.size()))
+ {
+ ERROR_MSG("EVP_DigestUpdate failed");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ HashAlgorithm::hashFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPHashAlgorithm::hashFinal(ByteString& hashedData)
+{
+ if (!HashAlgorithm::hashFinal(hashedData))
+ {
+ return false;
+ }
+
+ hashedData.resize(EVP_MD_size(getEVPHash()));
+ unsigned int outLen = hashedData.size();
+
+ if (!EVP_DigestFinal_ex(curCTX, &hashedData[0], &outLen))
+ {
+ ERROR_MSG("EVP_DigestFinal failed");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return false;
+ }
+
+ hashedData.resize(outLen);
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.h b/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.h
new file mode 100644
index 0000000..1775df2
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEVPHashAlgorithm.h
+
+ Base class for OpenSSL hash algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEVPHASHALGORITHM_H
+#define _SOFTHSM_V2_OSSLEVPHASHALGORITHM_H
+
+#include "config.h"
+#include "HashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLEVPHashAlgorithm : public HashAlgorithm
+{
+public:
+ // Base constructors
+ OSSLEVPHashAlgorithm() : HashAlgorithm() {
+ curCTX = NULL;
+ }
+
+ // Destructor
+ ~OSSLEVPHashAlgorithm();
+
+ // Hashing functions
+ virtual bool hashInit();
+ virtual bool hashUpdate(const ByteString& data);
+ virtual bool hashFinal(ByteString& hashedData);
+
+ virtual int getHashSize() = 0;
+protected:
+ virtual const EVP_MD* getEVPHash() const = 0;
+
+private:
+ // Current hashing context
+ EVP_MD_CTX* curCTX;
+};
+
+#endif // !_SOFTHSM_V2_OSSLEVPHASHALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.cpp
new file mode 100644
index 0000000..960b341
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// TODO: Store context in securely allocated memory
+
+/*****************************************************************************
+ OSSLEVPMacAlgorithm.cpp
+
+ OpenSSL MAC algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLEVPMacAlgorithm.h"
+#include "OSSLComp.h"
+
+// Destructor
+OSSLEVPMacAlgorithm::~OSSLEVPMacAlgorithm()
+{
+ HMAC_CTX_free(curCTX);
+}
+
+// Signing functions
+bool OSSLEVPMacAlgorithm::signInit(const SymmetricKey* key)
+{
+ // Call the superclass initialiser
+ if (!MacAlgorithm::signInit(key))
+ {
+ return false;
+ }
+
+ // Initialize the context
+ curCTX = HMAC_CTX_new();
+ if (curCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for HMAC_CTX");
+
+ return false;
+ }
+
+ // Initialize EVP signing
+ if (!HMAC_Init_ex(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), getEVPHash(), NULL))
+ {
+ ERROR_MSG("HMAC_Init failed");
+
+ HMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPMacAlgorithm::signUpdate(const ByteString& dataToSign)
+{
+ if (!MacAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ // The GOST implementation in OpenSSL will segfault if we update with zero length.
+ if (dataToSign.size() == 0) return true;
+
+ if (!HMAC_Update(curCTX, dataToSign.const_byte_str(), dataToSign.size()))
+ {
+ ERROR_MSG("HMAC_Update failed");
+
+ HMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ MacAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPMacAlgorithm::signFinal(ByteString& signature)
+{
+ if (!MacAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ signature.resize(EVP_MD_size(getEVPHash()));
+ unsigned int outLen = signature.size();
+
+ if (!HMAC_Final(curCTX, &signature[0], &outLen))
+ {
+ ERROR_MSG("HMAC_Final failed");
+
+ HMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return false;
+ }
+
+ signature.resize(outLen);
+
+ HMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool OSSLEVPMacAlgorithm::verifyInit(const SymmetricKey* key)
+{
+ // Call the superclass initialiser
+ if (!MacAlgorithm::verifyInit(key))
+ {
+ return false;
+ }
+
+ // Initialize the context
+ curCTX = HMAC_CTX_new();
+ if (curCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for HMAC_CTX");
+
+ return false;
+ }
+
+ // Initialize EVP signing
+ if (!HMAC_Init_ex(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), getEVPHash(), NULL))
+ {
+ ERROR_MSG("HMAC_Init failed");
+
+ HMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ MacAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPMacAlgorithm::verifyUpdate(const ByteString& originalData)
+{
+ if (!MacAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ // The GOST implementation in OpenSSL will segfault if we update with zero length.
+ if (originalData.size() == 0) return true;
+
+ if (!HMAC_Update(curCTX, originalData.const_byte_str(), originalData.size()))
+ {
+ ERROR_MSG("HMAC_Update failed");
+
+ HMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ MacAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLEVPMacAlgorithm::verifyFinal(ByteString& signature)
+{
+ if (!MacAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString macResult;
+ unsigned int outLen = EVP_MD_size(getEVPHash());
+ macResult.resize(outLen);
+
+ if (!HMAC_Final(curCTX, &macResult[0], &outLen))
+ {
+ ERROR_MSG("HMAC_Final failed");
+
+ HMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return false;
+ }
+
+ HMAC_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return macResult == signature;
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.h b/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.h
new file mode 100644
index 0000000..69e3f18
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEVPMacAlgorithm.h
+
+ OpenSSL MAC algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEVPMACALGORITHM_H
+#define _SOFTHSM_V2_OSSLEVPMACALGORITHM_H
+
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "MacAlgorithm.h"
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+class OSSLEVPMacAlgorithm : public MacAlgorithm
+{
+public:
+ // Constructor
+ OSSLEVPMacAlgorithm() {
+ curCTX = NULL;
+ };
+
+ // Destructor
+ ~OSSLEVPMacAlgorithm();
+
+ // Signing functions
+ virtual bool signInit(const SymmetricKey* key);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verifyInit(const SymmetricKey* key);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(ByteString& signature);
+
+ // Return the MAC size
+ virtual size_t getMacSize() const = 0;
+
+protected:
+ // Return the right hash for the operation
+ virtual const EVP_MD* getEVPHash() const = 0;
+
+private:
+ // The current context
+ HMAC_CTX* curCTX;
+};
+
+#endif // !_SOFTHSM_V2_OSSLEVPMACALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp
new file mode 100644
index 0000000..d43e741
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// TODO: Store EVP context in securely allocated memory
+
+/*****************************************************************************
+ OSSLEVPSymmetricAlgorithm.cpp
+
+ OpenSSL symmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLEVPSymmetricAlgorithm.h"
+#include "OSSLUtil.h"
+#include "salloc.h"
+#include <openssl/err.h>
+
+// Constructor
+OSSLEVPSymmetricAlgorithm::OSSLEVPSymmetricAlgorithm()
+{
+ pCurCTX = NULL;
+ maximumBytes = BN_new();
+ BN_one(maximumBytes);
+ BN_set_negative(maximumBytes, 1);
+ counterBytes = BN_new();
+ BN_zero(counterBytes);
+}
+
+// Destructor
+OSSLEVPSymmetricAlgorithm::~OSSLEVPSymmetricAlgorithm()
+{
+ EVP_CIPHER_CTX_free(pCurCTX);
+ BN_free(maximumBytes);
+ BN_free(counterBytes);
+}
+
+// Encryption functions
+bool OSSLEVPSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& IV /* = ByteString()*/, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& aad /* = ByteString() */, size_t tagBytes /* = 0 */)
+{
+ // Call the superclass initialiser
+ if (!SymmetricAlgorithm::encryptInit(key, mode, IV, padding, counterBits, aad, tagBytes))
+ {
+ return false;
+ }
+
+ // Check the IV
+ if (mode != SymMode::GCM && (IV.size() > 0) && (IV.size() != getBlockSize()))
+ {
+ ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ ByteString iv;
+
+ if (IV.size() > 0)
+ {
+ iv = IV;
+ }
+ else
+ {
+ iv.wipe(getBlockSize());
+ }
+
+ // Check the counter bits
+ if (counterBits > 0)
+ {
+ BIGNUM* counter = OSSL::byteString2bn(iv);
+ BN_mask_bits(counter, counterBits);
+
+ // Reverse the bits
+ while (counterBits > 0)
+ {
+ counterBits--;
+ if (BN_is_bit_set(counter, counterBits))
+ {
+ BN_clear_bit(counter, counterBits);
+ }
+ else
+ {
+ BN_set_bit(counter, counterBits);
+ }
+ }
+
+ // Set the maximum bytes
+ BN_add_word(counter, 1);
+ BN_mul_word(counter, getBlockSize());
+ BN_copy(maximumBytes, counter);
+ BN_free(counter);
+ BN_zero(counterBytes);
+ }
+ else
+ {
+ BN_one(maximumBytes);
+ BN_set_negative(maximumBytes, 1);
+ }
+
+ // Determine the cipher class
+ const EVP_CIPHER* cipher = getCipher();
+
+ if (cipher == NULL)
+ {
+ ERROR_MSG("Failed to initialise EVP encrypt operation");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the EVP context
+ pCurCTX = EVP_CIPHER_CTX_new();
+
+ if (pCurCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX");
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ int rv;
+ if (mode == SymMode::GCM)
+ {
+ rv = EVP_EncryptInit_ex(pCurCTX, cipher, NULL, NULL, NULL);
+
+ if (rv)
+ {
+ EVP_CIPHER_CTX_ctrl(pCurCTX, EVP_CTRL_GCM_SET_IVLEN, iv.size(), NULL);
+ rv = EVP_EncryptInit_ex(pCurCTX, NULL, NULL, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str());
+ }
+ }
+ else
+ {
+ rv = EVP_EncryptInit(pCurCTX, cipher, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str());
+ }
+
+ if (!rv)
+ {
+ ERROR_MSG("Failed to initialise EVP encrypt operation: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ EVP_CIPHER_CTX_set_padding(pCurCTX, padding ? 1 : 0);
+
+ if (mode == SymMode::GCM)
+ {
+ int outLen = 0;
+ if (aad.size() && !EVP_EncryptUpdate(pCurCTX, NULL, &outLen, (unsigned char*) aad.const_byte_str(), aad.size()))
+ {
+ ERROR_MSG("Failed to update with AAD: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool OSSLEVPSymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& encryptedData)
+{
+ if (!SymmetricAlgorithm::encryptUpdate(data, encryptedData))
+ {
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ if (data.size() == 0)
+ {
+ encryptedData.resize(0);
+
+ return true;
+ }
+
+ // Count number of bytes written
+ if (!BN_is_negative(maximumBytes))
+ {
+ BN_add_word(counterBytes, data.size());
+ }
+
+ // Prepare the output block
+ encryptedData.resize(data.size() + getBlockSize() - 1);
+
+ int outLen = encryptedData.size();
+ if (!EVP_EncryptUpdate(pCurCTX, &encryptedData[0], &outLen, (unsigned char*) data.const_byte_str(), data.size()))
+ {
+ ERROR_MSG("EVP_EncryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::encryptFinal(dummy);
+
+ return false;
+ }
+
+ // Resize the output block
+ encryptedData.resize(outLen);
+ currentBufferSize -= outLen;
+
+ return true;
+}
+
+bool OSSLEVPSymmetricAlgorithm::encryptFinal(ByteString& encryptedData)
+{
+ SymMode::Type mode = currentCipherMode;
+ size_t tagBytes = currentTagBytes;
+
+ if (!SymmetricAlgorithm::encryptFinal(encryptedData))
+ {
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ // Prepare the output block
+ encryptedData.resize(getBlockSize());
+
+ int outLen = encryptedData.size();
+
+ if (!EVP_EncryptFinal(pCurCTX, &encryptedData[0], &outLen))
+ {
+ ERROR_MSG("EVP_EncryptFinal failed: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ // Resize the output block
+ encryptedData.resize(outLen);
+
+ if (mode == SymMode::GCM)
+ {
+ ByteString tag;
+ tag.resize(tagBytes);
+ EVP_CIPHER_CTX_ctrl(pCurCTX, EVP_CTRL_GCM_GET_TAG, tagBytes, &tag[0]);
+ encryptedData += tag;
+ }
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return true;
+}
+
+// Decryption functions
+bool OSSLEVPSymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& IV /* = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& aad /* = ByteString() */, size_t tagBytes /* = 0 */)
+{
+ // Call the superclass initialiser
+ if (!SymmetricAlgorithm::decryptInit(key, mode, IV, padding, counterBits, aad, tagBytes))
+ {
+ return false;
+ }
+
+ // Check the IV
+ if (mode != SymMode::GCM && (IV.size() > 0) && (IV.size() != getBlockSize()))
+ {
+ ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize());
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ ByteString iv;
+
+ if (IV.size() > 0)
+ {
+ iv = IV;
+ }
+ else
+ {
+ iv.wipe(getBlockSize());
+ }
+
+ // Check the counter bits
+ if (counterBits > 0)
+ {
+ BIGNUM* counter = OSSL::byteString2bn(iv);
+ BN_mask_bits(counter, counterBits);
+
+ // Reverse the bits
+ while (counterBits > 0)
+ {
+ counterBits--;
+ if (BN_is_bit_set(counter, counterBits))
+ {
+ BN_clear_bit(counter, counterBits);
+ }
+ else
+ {
+ BN_set_bit(counter, counterBits);
+ }
+ }
+
+ // Set the maximum bytes
+ BN_add_word(counter, 1);
+ BN_mul_word(counter, getBlockSize());
+ BN_copy(maximumBytes, counter);
+ BN_free(counter);
+ BN_zero(counterBytes);
+ }
+ else
+ {
+ BN_one(maximumBytes);
+ BN_set_negative(maximumBytes, 1);
+ }
+
+ // Determine the cipher class
+ const EVP_CIPHER* cipher = getCipher();
+
+ if (cipher == NULL)
+ {
+ ERROR_MSG("Failed to initialise EVP decrypt operation");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ // Allocate the EVP context
+ pCurCTX = EVP_CIPHER_CTX_new();
+
+ if (pCurCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX");
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ int rv;
+ if (mode == SymMode::GCM)
+ {
+ rv = EVP_DecryptInit_ex(pCurCTX, cipher, NULL, NULL, NULL);
+
+ if (rv)
+ {
+ EVP_CIPHER_CTX_ctrl(pCurCTX, EVP_CTRL_GCM_SET_IVLEN, iv.size(), NULL);
+ rv = EVP_DecryptInit_ex(pCurCTX, NULL, NULL, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str());
+ }
+ }
+ else
+ {
+ rv = EVP_DecryptInit(pCurCTX, cipher, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str());
+ }
+
+ if (!rv)
+ {
+ ERROR_MSG("Failed to initialise EVP decrypt operation: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ EVP_CIPHER_CTX_set_padding(pCurCTX, padding ? 1 : 0);
+
+ if (mode == SymMode::GCM)
+ {
+ int outLen = 0;
+ if (aad.size() && !EVP_DecryptUpdate(pCurCTX, NULL, &outLen, (unsigned char*) aad.const_byte_str(), aad.size()))
+ {
+ ERROR_MSG("Failed to update with AAD: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool OSSLEVPSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& data)
+{
+ if (!SymmetricAlgorithm::decryptUpdate(encryptedData, data))
+ {
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ // AEAD ciphers should not return decrypted data until final is called
+ if (currentCipherMode == SymMode::GCM)
+ {
+ data.resize(0);
+ return true;
+ }
+
+ // Count number of bytes written
+ if (!BN_is_negative(maximumBytes))
+ {
+ BN_add_word(counterBytes, encryptedData.size());
+ }
+
+ // Prepare the output block
+ data.resize(encryptedData.size() + getBlockSize());
+
+ int outLen = data.size();
+
+ DEBUG_MSG("Decrypting %d bytes into buffer of %d bytes", encryptedData.size(), data.size());
+
+ if (!EVP_DecryptUpdate(pCurCTX, &data[0], &outLen, (unsigned char*) encryptedData.const_byte_str(), encryptedData.size()))
+ {
+ ERROR_MSG("EVP_DecryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ ByteString dummy;
+ SymmetricAlgorithm::decryptFinal(dummy);
+
+ return false;
+ }
+
+ DEBUG_MSG("Decrypt returned %d bytes of data", outLen);
+
+ // Resize the output block
+ data.resize(outLen);
+ currentBufferSize -= outLen;
+
+ return true;
+}
+
+bool OSSLEVPSymmetricAlgorithm::decryptFinal(ByteString& data)
+{
+ SymMode::Type mode = currentCipherMode;
+ size_t tagBytes = currentTagBytes;
+ ByteString aeadBuffer = currentAEADBuffer;
+
+ if (!SymmetricAlgorithm::decryptFinal(data))
+ {
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ data.resize(0);
+ if (mode == SymMode::GCM)
+ {
+ // Check buffer size
+ if (aeadBuffer.size() < tagBytes)
+ {
+ ERROR_MSG("Tag bytes (%d) does not fit in AEAD buffer (%d)", tagBytes, aeadBuffer.size());
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ // Set the tag
+ EVP_CIPHER_CTX_ctrl(pCurCTX, EVP_CTRL_GCM_SET_TAG, tagBytes, &aeadBuffer[aeadBuffer.size()-tagBytes]);
+
+ // Prepare the output block
+ data.resize(aeadBuffer.size() - tagBytes + getBlockSize());
+ int outLen = data.size();
+
+ if (!EVP_DecryptUpdate(pCurCTX, &data[0], &outLen, (unsigned char*) aeadBuffer.const_byte_str(), aeadBuffer.size() - tagBytes))
+ {
+ ERROR_MSG("EVP_DecryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ data.resize(outLen);
+ }
+
+ // Prepare the output block
+ int initialSize = data.size();
+ data.resize(initialSize + getBlockSize());
+
+ int outLen = data.size() - initialSize;
+ int rv;
+
+ if (!(rv = EVP_DecryptFinal(pCurCTX, &data[initialSize], &outLen)))
+ {
+ ERROR_MSG("EVP_DecryptFinal failed (0x%08X): %s", rv, ERR_error_string(ERR_get_error(), NULL));
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return false;
+ }
+
+ // Resize the output block
+ data.resize(initialSize + outLen);
+
+ EVP_CIPHER_CTX_free(pCurCTX);
+ pCurCTX = NULL;
+
+ return true;
+}
+
+// Check if more bytes of data can be encrypted
+bool OSSLEVPSymmetricAlgorithm::checkMaximumBytes(unsigned long bytes)
+{
+ if (BN_is_negative(maximumBytes)) return true;
+
+ BIGNUM* bigNum = BN_new();
+ BN_copy(bigNum, counterBytes);
+ BN_add_word(bigNum, bytes);
+
+ bool rv = false;
+ if (BN_cmp(maximumBytes, bigNum) >= 0) rv = true;
+
+ BN_free(bigNum);
+
+ return rv;
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.h
new file mode 100644
index 0000000..66bbeef
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEVPSymmetricAlgorithm.h
+
+ OpenSSL symmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H
+#define _SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H
+
+#include <openssl/evp.h>
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "SymmetricAlgorithm.h"
+
+class OSSLEVPSymmetricAlgorithm : public SymmetricAlgorithm
+{
+public:
+ // Constructor
+ OSSLEVPSymmetricAlgorithm();
+
+ // Destructor
+ virtual ~OSSLEVPSymmetricAlgorithm();
+
+ // Encryption functions
+ virtual bool encryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0);
+ virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData);
+ virtual bool encryptFinal(ByteString& encryptedData);
+
+ // Decryption functions
+ virtual bool decryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0);
+ virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data);
+ virtual bool decryptFinal(ByteString& data);
+
+ // Return the block size
+ virtual size_t getBlockSize() const = 0;
+
+ // Check if more bytes of data can be encrypted
+ virtual bool checkMaximumBytes(unsigned long bytes);
+
+protected:
+ // Return the right EVP cipher for the operation
+ virtual const EVP_CIPHER* getCipher() const = 0;
+
+private:
+ // The current EVP context
+ EVP_CIPHER_CTX* pCurCTX;
+
+ // The maximum bytes to encrypt/decrypt
+ BIGNUM* maximumBytes;
+ BIGNUM* counterBytes;
+};
+
+#endif // !_SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOST.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOST.cpp
new file mode 100644
index 0000000..4f34d45
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOST.cpp
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOST.cpp
+
+ OpenSSL GOST R 34.10-2001 asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "log.h"
+#include "OSSLGOST.h"
+#include "OSSLCryptoFactory.h"
+#include "ECParameters.h"
+#include "OSSLGOSTKeyPair.h"
+#include "OSSLGOSTPrivateKey.h"
+#include "OSSLGOSTPublicKey.h"
+#include "OSSLComp.h"
+#include <algorithm>
+#include <openssl/ecdsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <string.h>
+
+// Destructor
+OSSLGOST::~OSSLGOST()
+{
+ EVP_MD_CTX_free(curCTX);
+}
+
+// Signing functions
+bool OSSLGOST::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (mechanism == AsymMech::GOST)
+ {
+ // Separate implementation for GOST signing without hash computation
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLGOSTPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // In case of raw GOST, the length of the input data must be 32 bytes
+ if (dataToSign.size() != 32)
+ {
+ ERROR_MSG("Size of data to sign is not 32 bytes");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ OSSLGOSTPrivateKey* osslKey = (OSSLGOSTPrivateKey*) privateKey;
+ EVP_PKEY* pkey = osslKey->getOSSLKey();
+ size_t outLen;
+
+ if (pkey == NULL)
+ {
+ ERROR_MSG("Could not get the OpenSSL private key");
+
+ return false;
+ }
+
+ signature.resize(EVP_PKEY_size(pkey));
+ outLen = signature.size();
+
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey,NULL);
+ if (ctx == NULL)
+ {
+ ERROR_MSG("EVP_PKEY_CTX_new failed");
+ return false;
+ }
+
+ if (EVP_PKEY_sign_init(ctx) <= 0)
+ {
+ ERROR_MSG("EVP_PKEY_sign_init failed");
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+
+ if (EVP_PKEY_sign(ctx, &signature[0], &outLen, dataToSign.const_byte_str(), dataToSign.size()) <= 0)
+ {
+ ERROR_MSG("An error occurred while performing a signature");
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+
+ signature.resize(outLen);
+ EVP_PKEY_CTX_free(ctx);
+
+ return true;
+ }
+ else
+ {
+ // Call default implementation
+ return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
+ }
+}
+
+bool OSSLGOST::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLGOSTPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ if (mechanism != AsymMech::GOST_GOST)
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ curCTX = EVP_MD_CTX_new();
+ if (curCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for EVP_MD_CTX");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ const EVP_MD* md = OSSLCryptoFactory::i()->EVP_GOST_34_11;
+ if (!EVP_DigestInit_ex(curCTX, md, NULL))
+ {
+ ERROR_MSG("EVP_DigestInit_ex failed");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLGOST::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ if (!EVP_DigestUpdate(curCTX, dataToSign.const_byte_str(), dataToSign.size()))
+ {
+ ERROR_MSG("EVP_DigestUpdate failed");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLGOST::signFinal(ByteString& signature)
+{
+ // Save necessary state before calling super class signFinal
+ OSSLGOSTPrivateKey* pk = (OSSLGOSTPrivateKey*) currentPrivateKey;
+
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the signature operation
+ EVP_PKEY* pkey = pk->getOSSLKey();
+ unsigned int outLen;
+
+ if (pkey == NULL)
+ {
+ ERROR_MSG("Could not get the OpenSSL private key");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return false;
+ }
+
+ signature.resize(EVP_PKEY_size(pkey));
+ outLen = signature.size();
+ if (!EVP_SignFinal(curCTX, &signature[0], &outLen, pkey))
+ {
+ ERROR_MSG("EVP_SignFinal failed");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return false;
+ }
+
+ signature.resize(outLen);
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return true;
+}
+
+// Verification functions
+bool OSSLGOST::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (mechanism == AsymMech::GOST)
+ {
+ // Separate implementation for GOST verification without hash computation
+
+ // Check if the private key is the right type
+ if (!publicKey->isOfType(OSSLGOSTPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Perform the verification operation
+ OSSLGOSTPublicKey* osslKey = (OSSLGOSTPublicKey*) publicKey;
+ EVP_PKEY* pkey = osslKey->getOSSLKey();
+
+ if (pkey == NULL)
+ {
+ ERROR_MSG("Could not get the OpenSSL public key");
+
+ return false;
+ }
+
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey,NULL);
+ if (ctx == NULL)
+ {
+ ERROR_MSG("EVP_PKEY_CTX_new failed");
+ return false;
+ }
+
+ if (EVP_PKEY_verify_init(ctx) <= 0)
+ {
+ ERROR_MSG("EVP_PKEY_verify_init failed");
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+
+ int ret = EVP_PKEY_verify(ctx, signature.const_byte_str(), signature.size(), originalData.const_byte_str(), originalData.size());
+ EVP_PKEY_CTX_free(ctx);
+ if (ret != 1)
+ {
+ if (ret < 0)
+ ERROR_MSG("GOST verify failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+ return true;
+ }
+ else
+ {
+ // Call the generic function
+ return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen);
+ }
+}
+
+bool OSSLGOST::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLGOSTPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ if (mechanism != AsymMech::GOST_GOST)
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ curCTX = EVP_MD_CTX_new();
+ if (curCTX == NULL)
+ {
+ ERROR_MSG("Failed to allocate space for EVP_MD_CTX");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ const EVP_MD* md = OSSLCryptoFactory::i()->EVP_GOST_34_11;
+ if (!EVP_DigestInit_ex(curCTX, md, NULL))
+ {
+ ERROR_MSG("EVP_DigestInit_ex failed");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLGOST::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ if (!EVP_DigestUpdate(curCTX, originalData.const_byte_str(), originalData.size()))
+ {
+ ERROR_MSG("EVP_DigestUpdate failed");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLGOST::verifyFinal(const ByteString& signature)
+{
+ // Save necessary state before calling super class verifyFinal
+ OSSLGOSTPublicKey* pk = (OSSLGOSTPublicKey*) currentPublicKey;
+
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ // Perform the verify operation
+ EVP_PKEY *pkey = pk->getOSSLKey();
+ int ret;
+
+ if (pkey == NULL)
+ {
+ ERROR_MSG("Could not get the OpenSSL public key");
+
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+
+ return false;
+ }
+
+ ret = EVP_VerifyFinal(curCTX, signature.const_byte_str(), signature.size(), pkey);
+ EVP_MD_CTX_free(curCTX);
+ curCTX = NULL;
+ if (ret != 1)
+ {
+ if (ret < 0)
+ ERROR_MSG("GOST verify failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+ return true;
+}
+
+// Encryption functions
+bool OSSLGOST::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("GOST does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool OSSLGOST::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("GOST does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool OSSLGOST::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(ECParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for GOST key generation");
+
+ return false;
+ }
+
+ ECParameters* params = (ECParameters*) parameters;
+ ByteString paramA = "06072a850302022301";
+ if (params->getEC() != paramA)
+ {
+ ERROR_MSG("unsupported parameters");
+
+ return false;
+ }
+
+ // Generate the key-pair
+ EVP_PKEY_CTX* ctx = NULL;
+ EVP_PKEY* pkey = NULL;
+ OSSLGOSTKeyPair* kp;
+
+ ctx = EVP_PKEY_CTX_new_id(NID_id_GostR3410_2001, NULL);
+ if (ctx == NULL)
+ {
+ ERROR_MSG("EVP_PKEY_CTX_new_id failed");
+
+ goto err;
+ }
+ if (EVP_PKEY_keygen_init(ctx) <= 0)
+ {
+ ERROR_MSG("EVP_PKEY_keygen_init failed");
+
+ goto err;
+ }
+ if (EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0)
+ {
+ ERROR_MSG("EVP_PKEY_CTX_ctrl_str failed");
+
+ goto err;
+ }
+ if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
+ {
+ ERROR_MSG("EVP_PKEY_keygen failed");
+
+ goto err;
+ }
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+
+ // Create an asymmetric key-pair object to return
+ kp = new OSSLGOSTKeyPair();
+
+ ((OSSLGOSTPublicKey*) kp->getPublicKey())->setFromOSSL(pkey);
+ ((OSSLGOSTPrivateKey*) kp->getPrivateKey())->setFromOSSL(pkey);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ EVP_PKEY_free(pkey);
+
+ return true;
+
+err:
+ if (ctx != NULL)
+ EVP_PKEY_CTX_free(ctx);
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+
+ return false;
+}
+
+unsigned long OSSLGOST::getMinKeySize()
+{
+ return 0;
+}
+
+unsigned long OSSLGOST::getMaxKeySize()
+{
+ return 0;
+}
+
+bool OSSLGOST::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLGOSTKeyPair* kp = new OSSLGOSTKeyPair();
+
+ bool rv = true;
+
+ if (!((OSSLGOSTPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((OSSLGOSTPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLGOST::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLGOSTPublicKey* pub = new OSSLGOSTPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLGOST::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLGOSTPrivateKey* priv = new OSSLGOSTPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLGOST::newPublicKey()
+{
+ return (PublicKey*) new OSSLGOSTPublicKey();
+}
+
+PrivateKey* OSSLGOST::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLGOSTPrivateKey();
+}
+
+AsymmetricParameters* OSSLGOST::newParameters()
+{
+ return (AsymmetricParameters*) new ECParameters();
+}
+
+bool OSSLGOST::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ECParameters* params = new ECParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOST.h b/SoftHSMv2/src/lib/crypto/OSSLGOST.h
new file mode 100644
index 0000000..ad399f1
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOST.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOST.h
+
+ OpenSSL GOST R 34.10-2001 asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLGOST_H
+#define _SOFTHSM_V2_OSSLGOST_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLGOST : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ OSSLGOST() : AsymmetricAlgorithm() {
+ curCTX = NULL;
+ }
+
+ // Destructor
+ ~OSSLGOST();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ EVP_MD_CTX* curCTX;
+};
+
+#endif // !_SOFTHSM_V2_OSSLGOST_H
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.cpp
new file mode 100644
index 0000000..969a216
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOSTKeyPair.cpp
+
+ OpenSSL GOST R 34.10-2001 key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "log.h"
+#include "OSSLGOSTKeyPair.h"
+
+// Set the public key
+void OSSLGOSTKeyPair::setPublicKey(OSSLGOSTPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void OSSLGOSTKeyPair::setPrivateKey(OSSLGOSTPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* OSSLGOSTKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* OSSLGOSTKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* OSSLGOSTKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* OSSLGOSTKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.h
new file mode 100644
index 0000000..b064704
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOSTKeyPair.h
+
+ OpenSSL GOST R 34.10-2001 key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLGOSTKEYPAIR_H
+#define _SOFTHSM_V2_OSSLGOSTKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "OSSLGOSTPublicKey.h"
+#include "OSSLGOSTPrivateKey.h"
+
+class OSSLGOSTKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(OSSLGOSTPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(OSSLGOSTPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ OSSLGOSTPublicKey pubKey;
+
+ // The private key
+ OSSLGOSTPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLGOSTKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.cpp
new file mode 100644
index 0000000..6371e8f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOSTPrivateKey.cpp
+
+ OpenSSL GOST R 34.10-2001 private key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "log.h"
+#include "OSSLGOSTPrivateKey.h"
+#include "OSSLUtil.h"
+#include <string.h>
+#include <openssl/ec.h>
+
+// DER of a private key
+const unsigned char dummyKey[] = {
+ 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
+ 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
+ 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
+ 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
+ 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20, 0x1b,
+ 0x3f, 0x94, 0xf7, 0x1a, 0x5f, 0x2f, 0xe7, 0xe5,
+ 0x74, 0x0b, 0x8c, 0xd4, 0xb7, 0x18, 0xdd, 0x65,
+ 0x68, 0x26, 0xd1, 0x54, 0xfb, 0x77, 0xba, 0x63,
+ 0x72, 0xd9, 0xf0, 0x63, 0x87, 0xe0, 0xd6
+};
+
+// Constructors
+OSSLGOSTPrivateKey::OSSLGOSTPrivateKey()
+{
+ pkey = EVP_PKEY_new();
+}
+
+OSSLGOSTPrivateKey::OSSLGOSTPrivateKey(const EVP_PKEY* inPKEY)
+{
+ OSSLGOSTPrivateKey();
+
+ setFromOSSL(inPKEY);
+}
+
+// Destructor
+OSSLGOSTPrivateKey::~OSSLGOSTPrivateKey()
+{
+ EVP_PKEY_free(pkey);
+}
+
+// The type
+/*static*/ const char* OSSLGOSTPrivateKey::type = "OpenSSL GOST Private Key";
+
+// Get the output length
+unsigned long OSSLGOSTPrivateKey::getOutputLength() const
+{
+ return 64;
+}
+
+// Set from OpenSSL representation
+void OSSLGOSTPrivateKey::setFromOSSL(const EVP_PKEY* pkey)
+{
+ const EC_KEY* eckey = (const EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey);
+ const BIGNUM* priv = EC_KEY_get0_private_key(eckey);
+ setD(OSSL::bn2ByteString(priv));
+
+ ByteString inEC;
+ int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+ inEC.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL));
+ unsigned char *p = &inEC[0];
+ i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p);
+ setEC(inEC);
+}
+
+// Check if the key is of the given type
+bool OSSLGOSTPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the GOST private key components
+void OSSLGOSTPrivateKey::setD(const ByteString& inD)
+{
+ GOSTPrivateKey::setD(inD);
+
+ EC_KEY* inEC = (EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey);
+ if (inEC == NULL)
+ {
+ const unsigned char* p = dummyKey;
+ if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, (long) sizeof(dummyKey)) == NULL)
+ {
+ ERROR_MSG("d2i_PrivateKey failed");
+
+ return;
+ }
+ inEC = (EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey);
+ }
+
+ const BIGNUM* priv = OSSL::byteString2bn(inD);
+ if (EC_KEY_set_private_key(inEC, priv) <= 0)
+ {
+ ERROR_MSG("EC_KEY_set_private_key failed");
+ return;
+ }
+ BN_clear_free((BIGNUM*)priv);
+
+#ifdef notyet
+ if (gost2001_compute_public(inEC) <= 0)
+ ERROR_MSG("gost2001_compute_public failed");
+#endif
+}
+
+// Setters for the GOST public key components
+void OSSLGOSTPrivateKey::setEC(const ByteString& inEC)
+{
+ GOSTPrivateKey::setEC(inEC);
+}
+
+// Retrieve the OpenSSL representation of the key
+EVP_PKEY* OSSLGOSTPrivateKey::getOSSLKey()
+{
+ return pkey;
+}
+
+// Serialisation
+ByteString OSSLGOSTPrivateKey::serialise() const
+{
+ return ec.serialise() +
+ d.serialise();
+}
+
+bool OSSLGOSTPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+ ByteString dD = ByteString::chainDeserialise(serialised);
+
+ if ((dEC.size() == 0) ||
+ (dD.size() == 0))
+ {
+ return false;
+ }
+
+ setEC(dEC);
+ setD(dD);
+
+ return true;
+}
+
+// Encode into PKCS#8 DER
+ByteString OSSLGOSTPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ // TODO
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool OSSLGOSTPrivateKey::PKCS8Decode(const ByteString& /*ber*/)
+{
+ return false;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.h
new file mode 100644
index 0000000..eca0f13
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOSTPrivateKey.h
+
+ OpenSSL GOST R 34.10-2001 private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLGOSTPRIVATEKEY_H
+#define _SOFTHSM_V2_OSSLGOSTPRIVATEKEY_H
+
+#include "config.h"
+#include "GOSTPrivateKey.h"
+#include <openssl/evp.h>
+
+class OSSLGOSTPrivateKey : public GOSTPrivateKey
+{
+public:
+ // Constructors
+ OSSLGOSTPrivateKey();
+
+ OSSLGOSTPrivateKey(const EVP_PKEY* inPKEY);
+
+ // Destructor
+ virtual ~OSSLGOSTPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the GOST private key components
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the GOST public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const EVP_PKEY* pkey);
+
+ // Retrieve the OpenSSL representation of the key
+ EVP_PKEY* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ EVP_PKEY* pkey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLGOSTPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.cpp
new file mode 100644
index 0000000..5810637
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOSTPublicKey.cpp
+
+ OpenSSL GOST R 34.10-2001 public key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "log.h"
+#include "OSSLGOSTPublicKey.h"
+#include <openssl/x509.h>
+#include <string.h>
+
+// the 37 bytes of prefix
+const unsigned char gost_prefix[] = {
+ 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
+ 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07,
+ 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01, 0x06,
+ 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01,
+ 0x03, 0x43, 0x00, 0x04, 0x40
+};
+
+// Constructors
+OSSLGOSTPublicKey::OSSLGOSTPublicKey()
+{
+ pkey = EVP_PKEY_new();
+}
+
+OSSLGOSTPublicKey::OSSLGOSTPublicKey(const EVP_PKEY* inPKEY)
+{
+ OSSLGOSTPublicKey();
+
+ setFromOSSL(inPKEY);
+}
+
+// Destructor
+OSSLGOSTPublicKey::~OSSLGOSTPublicKey()
+{
+ EVP_PKEY_free(pkey);
+}
+
+// The type
+/*static*/ const char* OSSLGOSTPublicKey::type = "OpenSSL GOST Public Key";
+
+// Get the output length
+unsigned long OSSLGOSTPublicKey::getOutputLength() const
+{
+ return getQ().size();
+}
+
+// Set from OpenSSL representation
+void OSSLGOSTPublicKey::setFromOSSL(const EVP_PKEY* pkey)
+{
+ ByteString der;
+ int len = i2d_PUBKEY((EVP_PKEY*) pkey, NULL);
+ if (len != 37 + 64)
+ {
+ ERROR_MSG("bad GOST public key encoding length %d", len);
+ return;
+ }
+ der.resize(len);
+ unsigned char *p = &der[0];
+ i2d_PUBKEY((EVP_PKEY*) pkey, &p);
+ // can check: der is prefix + 64 bytes
+ setQ(der.substr(37));
+
+ ByteString inEC;
+ const EC_KEY* eckey = (const EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey);
+ int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+ inEC.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL));
+ p = &inEC[0];
+ i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p);
+ setEC(inEC);
+}
+
+// Check if the key is of the given type
+bool OSSLGOSTPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the GOST public key components
+void OSSLGOSTPublicKey::setEC(const ByteString& inEC)
+{
+ GOSTPublicKey::setEC(inEC);
+}
+
+void OSSLGOSTPublicKey::setQ(const ByteString& inQ)
+{
+ GOSTPublicKey::setQ(inQ);
+
+ if (inQ.size() != 64)
+ {
+ ERROR_MSG("bad GOST public key size %zu", q.size());
+ return;
+ }
+
+ ByteString der;
+ der.resize(37 + 64);
+ memcpy(&der[0], gost_prefix, 37);
+ memcpy(&der[37], inQ.const_byte_str(), 64);
+ const unsigned char *p = &der[0];
+ if (d2i_PUBKEY(&pkey, &p, (long) der.size()) == NULL)
+ ERROR_MSG("d2i_PUBKEY failed");
+}
+
+// Serialisation
+ByteString OSSLGOSTPublicKey::serialise() const
+{
+ return ec.serialise() +
+ q.serialise();
+}
+
+bool OSSLGOSTPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+
+ if ((dEC.size() == 0) ||
+ (dQ.size() == 0))
+ {
+ return false;
+ }
+
+ setEC(dEC);
+ setQ(dQ);
+
+ return true;
+}
+
+// Retrieve the OpenSSL representation of the key
+EVP_PKEY* OSSLGOSTPublicKey::getOSSLKey()
+{
+ return pkey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.h
new file mode 100644
index 0000000..c951962
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOSTPublicKey.h
+
+ OpenSSL GOST R 34.10-2001 public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLGOSTPUBLICKEY_H
+#define _SOFTHSM_V2_OSSLGOSTPUBLICKEY_H
+
+#include "config.h"
+#include "GOSTPublicKey.h"
+#include <openssl/evp.h>
+
+class OSSLGOSTPublicKey : public GOSTPublicKey
+{
+public:
+ // Constructors
+ OSSLGOSTPublicKey();
+
+ OSSLGOSTPublicKey(const EVP_PKEY* inPKEY);
+
+ // Destructor
+ virtual ~OSSLGOSTPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the GOST public key components
+ virtual void setEC(const ByteString& inEC);
+ virtual void setQ(const ByteString& inQ);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const EVP_PKEY* pkey);
+
+ // Retrieve the OpenSSL representation of the key
+ EVP_PKEY* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ EVP_PKEY* pkey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.cpp
new file mode 100644
index 0000000..5361075
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOSTR3411.h
+
+ OpenSSL GOST R 34.11-94 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_GOST
+#include "OSSLGOSTR3411.h"
+#include "OSSLCryptoFactory.h"
+#include <openssl/evp.h>
+
+int OSSLGOSTR3411::getHashSize()
+{
+ return 32;
+}
+
+const EVP_MD* OSSLGOSTR3411::getEVPHash() const
+{
+ return OSSLCryptoFactory::i()->EVP_GOST_34_11;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.h b/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.h
new file mode 100644
index 0000000..8175258
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLGOSTR3411.h
+
+ OpenSSL GOST R 34.11-94 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLGOSTR3411_H
+#define _SOFTHSM_V2_OSSLGOSTR3411_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLGOSTR3411 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLGOSTR3411_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLHMAC.cpp b/SoftHSMv2/src/lib/crypto/OSSLHMAC.cpp
new file mode 100644
index 0000000..f8b73a7
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLHMAC.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLHMAC.cpp
+
+ OpenSSL HMAC implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLHMAC.h"
+#ifdef WITH_GOST
+#include "OSSLCryptoFactory.h"
+#endif
+
+const EVP_MD* OSSLHMACMD5::getEVPHash() const
+{
+ return EVP_md5();
+}
+
+size_t OSSLHMACMD5::getMacSize() const
+{
+ return 16;
+}
+
+const EVP_MD* OSSLHMACSHA1::getEVPHash() const
+{
+ return EVP_sha1();
+}
+
+size_t OSSLHMACSHA1::getMacSize() const
+{
+ return 20;
+}
+
+const EVP_MD* OSSLHMACSHA224::getEVPHash() const
+{
+ return EVP_sha224();
+}
+
+size_t OSSLHMACSHA224::getMacSize() const
+{
+ return 28;
+}
+
+const EVP_MD* OSSLHMACSHA256::getEVPHash() const
+{
+ return EVP_sha256();
+}
+
+size_t OSSLHMACSHA256::getMacSize() const
+{
+ return 32;
+}
+
+const EVP_MD* OSSLHMACSHA384::getEVPHash() const
+{
+ return EVP_sha384();
+}
+
+size_t OSSLHMACSHA384::getMacSize() const
+{
+ return 48;
+}
+
+const EVP_MD* OSSLHMACSHA512::getEVPHash() const
+{
+ return EVP_sha512();
+}
+
+size_t OSSLHMACSHA512::getMacSize() const
+{
+ return 64;
+}
+
+#ifdef WITH_GOST
+const EVP_MD* OSSLHMACGOSTR3411::getEVPHash() const
+{
+ return OSSLCryptoFactory::i()->EVP_GOST_34_11;
+}
+
+size_t OSSLHMACGOSTR3411::getMacSize() const
+{
+ return 32;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLHMAC.h b/SoftHSMv2/src/lib/crypto/OSSLHMAC.h
new file mode 100644
index 0000000..852614e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLHMAC.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLHMAC.h
+
+ OpenSSL HMAC implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLHMAC_H
+#define _SOFTHSM_V2_OSSLHMAC_H
+
+#include "config.h"
+#include "OSSLEVPMacAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLHMACMD5 : public OSSLEVPMacAlgorithm
+{
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+ virtual size_t getMacSize() const;
+};
+
+class OSSLHMACSHA1 : public OSSLEVPMacAlgorithm
+{
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+ virtual size_t getMacSize() const;
+};
+
+class OSSLHMACSHA224 : public OSSLEVPMacAlgorithm
+{
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+ virtual size_t getMacSize() const;
+};
+
+class OSSLHMACSHA256 : public OSSLEVPMacAlgorithm
+{
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+ virtual size_t getMacSize() const;
+};
+
+class OSSLHMACSHA384 : public OSSLEVPMacAlgorithm
+{
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+ virtual size_t getMacSize() const;
+};
+
+class OSSLHMACSHA512 : public OSSLEVPMacAlgorithm
+{
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+ virtual size_t getMacSize() const;
+};
+
+#ifdef WITH_GOST
+class OSSLHMACGOSTR3411 : public OSSLEVPMacAlgorithm
+{
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+ virtual size_t getMacSize() const;
+};
+#endif
+
+#endif // !_SOFTHSM_V2_OSSLHMAC_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLMD5.cpp b/SoftHSMv2/src/lib/crypto/OSSLMD5.cpp
new file mode 100644
index 0000000..2c962a6
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLMD5.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLMD5.h
+
+ OpenSSL MD5 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLMD5.h"
+#include <openssl/evp.h>
+
+int OSSLMD5::getHashSize()
+{
+ return 16;
+}
+
+const EVP_MD* OSSLMD5::getEVPHash() const
+{
+ return EVP_md5();
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLMD5.h b/SoftHSMv2/src/lib/crypto/OSSLMD5.h
new file mode 100644
index 0000000..22d7111
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLMD5.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLMD5.h
+
+ OpenSSL MD5 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLMD5_H
+#define _SOFTHSM_V2_OSSLMD5_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLMD5 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLMD5_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRNG.cpp b/SoftHSMv2/src/lib/crypto/OSSLRNG.cpp
new file mode 100644
index 0000000..d6a1e5d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRNG.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRNG.cpp
+
+ OpenSSL random number generator class
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLRNG.h"
+#include <openssl/rand.h>
+
+// Generate random data
+bool OSSLRNG::generateRandom(ByteString& data, const size_t len)
+{
+ data.wipe(len);
+
+ if (len == 0)
+ return true;
+ return RAND_bytes(&data[0], len) == 1;
+}
+
+// Seed the random pool
+void OSSLRNG::seed(ByteString& seedData)
+{
+ RAND_seed(seedData.byte_str(), seedData.size());
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRNG.h b/SoftHSMv2/src/lib/crypto/OSSLRNG.h
new file mode 100644
index 0000000..829f593
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRNG.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRNG.h
+
+ OpenSSL random number generator class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRNG_H
+#define _SOFTHSM_V2_OSSLRNG_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "RNG.h"
+
+class OSSLRNG : public RNG
+{
+public:
+ // Generate random data
+ virtual bool generateRandom(ByteString& data, const size_t len);
+
+ // Seed the random pool
+ virtual void seed(ByteString& seedData);
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_OSSLRNG_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSA.cpp b/SoftHSMv2/src/lib/crypto/OSSLRSA.cpp
new file mode 100644
index 0000000..1e5638a
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRSA.cpp
@@ -0,0 +1,1554 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSA.cpp
+
+ OpenSSL RSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLRSA.h"
+#include "OSSLUtil.h"
+#include "CryptoFactory.h"
+#include "RSAParameters.h"
+#include "OSSLRSAKeyPair.h"
+#include <algorithm>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+// Constructor
+OSSLRSA::OSSLRSA()
+{
+ pCurrentHash = NULL;
+ pSecondHash = NULL;
+ sLen = 0;
+}
+
+// Destructor
+OSSLRSA::~OSSLRSA()
+{
+ if (pCurrentHash != NULL)
+ {
+ delete pCurrentHash;
+ }
+
+ if (pSecondHash != NULL)
+ {
+ delete pSecondHash;
+ }
+}
+
+// Signing functions
+bool OSSLRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (mechanism == AsymMech::RSA_PKCS)
+ {
+ // Separate implementation for RSA PKCS #1 signing without hash computation
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // In case of PKCS #1 signing the length of the input data may not exceed 40% of the
+ // modulus size
+ OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey;
+
+ size_t allowedLen = osslKey->getN().size() - 11;
+
+ if (dataToSign.size() > allowedLen)
+ {
+ ERROR_MSG("Data to sign exceeds maximum for PKCS #1 signature");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ signature.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ if (!RSA_blinding_on(rsa, NULL))
+ {
+ ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key");
+
+ return false;
+ }
+
+ int sigLen = RSA_private_encrypt(dataToSign.size(), (unsigned char*) dataToSign.const_byte_str(), &signature[0], rsa, RSA_PKCS1_PADDING);
+
+ RSA_blinding_off(rsa);
+
+ if (sigLen == -1)
+ {
+ ERROR_MSG("An error occurred while performing a PKCS #1 signature");
+
+ return false;
+ }
+
+ signature.resize(sigLen);
+
+ return true;
+ }
+ else if (mechanism == AsymMech::RSA_PKCS_PSS)
+ {
+ const RSA_PKCS_PSS_PARAMS *pssParam = (RSA_PKCS_PSS_PARAMS*)param;
+
+ // Separate implementation for RSA PKCS #1 signing without hash computation
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ if (pssParam == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS))
+ {
+ ERROR_MSG("Invalid parameters supplied");
+
+ return false;
+ }
+
+ size_t allowedLen;
+ const EVP_MD* hash = NULL;
+
+ switch (pssParam->hashAlg)
+ {
+ case HashAlgo::SHA1:
+ hash = EVP_sha1();
+ allowedLen = 20;
+ break;
+ case HashAlgo::SHA224:
+ hash = EVP_sha224();
+ allowedLen = 28;
+ break;
+ case HashAlgo::SHA256:
+ hash = EVP_sha256();
+ allowedLen = 32;
+ break;
+ case HashAlgo::SHA384:
+ hash = EVP_sha384();
+ allowedLen = 48;
+ break;
+ case HashAlgo::SHA512:
+ hash = EVP_sha512();
+ allowedLen = 64;
+ break;
+ default:
+ return false;
+ }
+
+ OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey;
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ if (dataToSign.size() != allowedLen)
+ {
+ ERROR_MSG("Data to sign does not match expected (%d) for RSA PSS", (int)allowedLen);
+
+ return false;
+ }
+
+ size_t sLen = pssParam->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-allowedLen))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ return false;
+ }
+
+ ByteString em;
+ em.resize(osslKey->getN().size());
+
+ int status = RSA_padding_add_PKCS1_PSS_mgf1(rsa, &em[0], (unsigned char*) dataToSign.const_byte_str(), hash, hash, pssParam->sLen);
+ if (!status)
+ {
+ ERROR_MSG("Error in RSA PSS padding generation");
+
+ return false;
+ }
+
+
+ if (!RSA_blinding_on(rsa, NULL))
+ {
+ ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ signature.resize(osslKey->getN().size());
+
+ int sigLen = RSA_private_encrypt(osslKey->getN().size(), &em[0], &signature[0], rsa, RSA_NO_PADDING);
+
+ RSA_blinding_off(rsa);
+
+ if (sigLen == -1)
+ {
+ ERROR_MSG("An error occurred while performing the RSA-PSS signature");
+
+ return false;
+ }
+
+ signature.resize(sigLen);
+
+ return true;
+ }
+ else if (mechanism == AsymMech::RSA)
+ {
+ // Separate implementation for raw RSA signing
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // In case of raw RSA, the length of the input data must match the length of the modulus
+ OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey;
+
+ if (dataToSign.size() != osslKey->getN().size())
+ {
+ ERROR_MSG("Size of data to sign does not match the modulus size");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ signature.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ if (!RSA_blinding_on(rsa, NULL))
+ {
+ ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key");
+
+ return false;
+ }
+
+ int sigLen = RSA_private_encrypt(dataToSign.size(), (unsigned char*) dataToSign.const_byte_str(), &signature[0], rsa, RSA_NO_PADDING);
+
+ RSA_blinding_off(rsa);
+
+ if (sigLen == -1)
+ {
+ ERROR_MSG("An error occurred while performing a raw RSA signature");
+
+ return false;
+ }
+
+ signature.resize(sigLen);
+
+ return true;
+ }
+ else
+ {
+ // Call default implementation
+ return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
+ }
+}
+
+bool OSSLRSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ HashAlgo::Type hash1 = HashAlgo::Unknown;
+ HashAlgo::Type hash2 = HashAlgo::Unknown;
+
+ switch (mechanism)
+ {
+ case AsymMech::RSA_MD5_PKCS:
+ hash1 = HashAlgo::MD5;
+ break;
+ case AsymMech::RSA_SHA1_PKCS:
+ hash1 = HashAlgo::SHA1;
+ break;
+ case AsymMech::RSA_SHA224_PKCS:
+ hash1 = HashAlgo::SHA224;
+ break;
+ case AsymMech::RSA_SHA256_PKCS:
+ hash1 = HashAlgo::SHA256;
+ break;
+ case AsymMech::RSA_SHA384_PKCS:
+ hash1 = HashAlgo::SHA384;
+ break;
+ case AsymMech::RSA_SHA512_PKCS:
+ hash1 = HashAlgo::SHA512;
+ break;
+ case AsymMech::RSA_SHA1_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-20))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA1;
+ break;
+ case AsymMech::RSA_SHA224_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-28))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA224;
+ break;
+ case AsymMech::RSA_SHA256_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-32))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA256;
+ break;
+ case AsymMech::RSA_SHA384_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-48))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA384;
+ break;
+ case AsymMech::RSA_SHA512_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((privateKey->getBitLength()+6)/8-2-64))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, privateKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA512;
+ break;
+ case AsymMech::RSA_SSL:
+ hash1 = HashAlgo::MD5;
+ hash2 = HashAlgo::SHA1;
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash1);
+
+ if (pCurrentHash == NULL || !pCurrentHash->hashInit())
+ {
+ if (pCurrentHash != NULL)
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ if (hash2 != HashAlgo::Unknown)
+ {
+ pSecondHash = CryptoFactory::i()->getHashAlgorithm(hash2);
+
+ if (pSecondHash == NULL || !pSecondHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (pSecondHash != NULL)
+ {
+ delete pSecondHash;
+ pSecondHash = NULL;
+ }
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool OSSLRSA::signUpdate(const ByteString& dataToSign)
+{
+ if (!AsymmetricAlgorithm::signUpdate(dataToSign))
+ {
+ return false;
+ }
+
+ if (!pCurrentHash->hashUpdate(dataToSign))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ if ((pSecondHash != NULL) && !pSecondHash->hashUpdate(dataToSign))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ delete pSecondHash;
+ pSecondHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::signFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLRSA::signFinal(ByteString& signature)
+{
+ // Save necessary state before calling super class signFinal
+ OSSLRSAPrivateKey* pk = (OSSLRSAPrivateKey*) currentPrivateKey;
+ AsymMech::Type mechanism = currentMechanism;
+
+ if (!AsymmetricAlgorithm::signFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString firstHash, secondHash;
+
+ bool bFirstResult = pCurrentHash->hashFinal(firstHash);
+ bool bSecondResult = (pSecondHash != NULL) ? pSecondHash->hashFinal(secondHash) : true;
+
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (pSecondHash != NULL)
+ {
+ delete pSecondHash;
+
+ pSecondHash = NULL;
+ }
+
+ if (!bFirstResult || !bSecondResult)
+ {
+ return false;
+ }
+
+ ByteString digest = firstHash + secondHash;
+
+ // Resize the data block for the signature to the modulus size of the key
+ signature.resize(pk->getN().size());
+
+ // Determine the signature NID type
+ int type = 0;
+ bool isPSS = false;
+ const EVP_MD* hash = NULL;
+
+ switch (mechanism)
+ {
+ case AsymMech::RSA_MD5_PKCS:
+ type = NID_md5;
+ break;
+ case AsymMech::RSA_SHA1_PKCS:
+ type = NID_sha1;
+ break;
+ case AsymMech::RSA_SHA224_PKCS:
+ type = NID_sha224;
+ break;
+ case AsymMech::RSA_SHA256_PKCS:
+ type = NID_sha256;
+ break;
+ case AsymMech::RSA_SHA384_PKCS:
+ type = NID_sha384;
+ break;
+ case AsymMech::RSA_SHA512_PKCS:
+ type = NID_sha512;
+ break;
+ case AsymMech::RSA_SHA1_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha1();
+ break;
+ case AsymMech::RSA_SHA224_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha224();
+ break;
+ case AsymMech::RSA_SHA256_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha256();
+ break;
+ case AsymMech::RSA_SHA384_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha384();
+ break;
+ case AsymMech::RSA_SHA512_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha512();
+ break;
+ case AsymMech::RSA_SSL:
+ type = NID_md5_sha1;
+ break;
+ default:
+ break;
+ }
+
+ // Perform the signature operation
+ unsigned int sigLen = signature.size();
+
+ RSA* rsa = pk->getOSSLKey();
+
+ if (!RSA_blinding_on(rsa, NULL))
+ {
+ ERROR_MSG("Failed to turn blinding on for OpenSSL RSA key");
+
+ return false;
+ }
+
+ bool rv;
+ int result;
+
+ if (isPSS)
+ {
+ ByteString em;
+ em.resize(pk->getN().size());
+
+ result = (RSA_padding_add_PKCS1_PSS(pk->getOSSLKey(), &em[0], &digest[0],
+ hash, sLen) == 1);
+ if (!result)
+ {
+ ERROR_MSG("RSA PSS padding failed (0x%08X)", ERR_get_error());
+ rv = false;
+ }
+ else
+ {
+ result = RSA_private_encrypt(em.size(), &em[0], &signature[0],
+ pk->getOSSLKey(), RSA_NO_PADDING);
+ if (result >= 0)
+ {
+ sigLen = result;
+ rv = true;
+ }
+ else
+ {
+ ERROR_MSG("RSA private encrypt failed (0x%08X)", ERR_get_error());
+ rv = false;
+ }
+ }
+ }
+ else
+ {
+ result = RSA_sign(type, &digest[0], digest.size(), &signature[0],
+ &sigLen, pk->getOSSLKey());
+ if (result > 0)
+ {
+ rv = true;
+ }
+ else
+ {
+ ERROR_MSG("RSA sign failed (0x%08X)", ERR_get_error());
+ rv = false;
+ }
+ }
+
+ RSA_blinding_off(rsa);
+
+ signature.resize(sigLen);
+
+ return rv;
+}
+
+// Verification functions
+bool OSSLRSA::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (mechanism == AsymMech::RSA_PKCS)
+ {
+ // Specific implementation for PKCS #1 only verification; originalData is assumed to contain
+ // a digestInfo structure and verification is performed by comparing originalData to the data
+ // recovered from the signature
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Perform the RSA public key operation
+ OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey;
+
+ ByteString recoveredData;
+
+ recoveredData.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_PKCS1_PADDING);
+
+ if (retLen == -1)
+ {
+ ERROR_MSG("Public key operation failed");
+
+ return false;
+ }
+
+ recoveredData.resize(retLen);
+
+ return (originalData == recoveredData);
+ }
+ else if (mechanism == AsymMech::RSA_PKCS_PSS)
+ {
+ const RSA_PKCS_PSS_PARAMS *pssParam = (RSA_PKCS_PSS_PARAMS*)param;
+
+ if (pssParam == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS))
+ {
+ ERROR_MSG("Invalid parameters supplied");
+
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Perform the RSA public key operation
+ OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey;
+
+ ByteString recoveredData;
+
+ recoveredData.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_NO_PADDING);
+
+ if (retLen == -1)
+ {
+ ERROR_MSG("Public key operation failed");
+
+ return false;
+ }
+
+ recoveredData.resize(retLen);
+
+ size_t allowedLen;
+ const EVP_MD* hash = NULL;
+
+ switch (pssParam->hashAlg)
+ {
+ case HashAlgo::SHA1:
+ hash = EVP_sha1();
+ allowedLen = 20;
+ break;
+ case HashAlgo::SHA224:
+ hash = EVP_sha224();
+ allowedLen = 28;
+ break;
+ case HashAlgo::SHA256:
+ hash = EVP_sha256();
+ allowedLen = 32;
+ break;
+ case HashAlgo::SHA384:
+ hash = EVP_sha384();
+ allowedLen = 48;
+ break;
+ case HashAlgo::SHA512:
+ hash = EVP_sha512();
+ allowedLen = 64;
+ break;
+ default:
+ return false;
+ }
+
+ if (originalData.size() != allowedLen) {
+ return false;
+ }
+
+ size_t sLen = pssParam->sLen;
+ if (sLen > ((osslKey->getBitLength()+6)/8-2-allowedLen))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, osslKey->getBitLength());
+ return false;
+ }
+
+ int status = RSA_verify_PKCS1_PSS_mgf1(rsa, (unsigned char*)originalData.const_byte_str(), hash, hash, (unsigned char*) recoveredData.const_byte_str(), pssParam->sLen);
+
+ return (status == 1);
+ }
+ else if (mechanism == AsymMech::RSA)
+ {
+ // Specific implementation for raw RSA verifiction; originalData is assumed to contain the
+ // full input data used to compute the signature and verification is performed by comparing
+ // originalData to the data recovered from the signature
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Perform the RSA public key operation
+ OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey;
+
+ ByteString recoveredData;
+
+ recoveredData.resize(osslKey->getN().size());
+
+ RSA* rsa = osslKey->getOSSLKey();
+
+ int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_NO_PADDING);
+
+ if (retLen == -1)
+ {
+ ERROR_MSG("Public key operation failed");
+
+ return false;
+ }
+
+ recoveredData.resize(retLen);
+
+ return (originalData == recoveredData);
+ }
+ else
+ {
+ // Call the generic function
+ return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen);
+ }
+}
+
+bool OSSLRSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
+ const void* param /* = NULL */, const size_t paramLen /* = 0 */)
+{
+ if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen))
+ {
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ HashAlgo::Type hash1 = HashAlgo::Unknown;
+ HashAlgo::Type hash2 = HashAlgo::Unknown;
+
+ switch (mechanism)
+ {
+ case AsymMech::RSA_MD5_PKCS:
+ hash1 = HashAlgo::MD5;
+ break;
+ case AsymMech::RSA_SHA1_PKCS:
+ hash1 = HashAlgo::SHA1;
+ break;
+ case AsymMech::RSA_SHA224_PKCS:
+ hash1 = HashAlgo::SHA224;
+ break;
+ case AsymMech::RSA_SHA256_PKCS:
+ hash1 = HashAlgo::SHA256;
+ break;
+ case AsymMech::RSA_SHA384_PKCS:
+ hash1 = HashAlgo::SHA384;
+ break;
+ case AsymMech::RSA_SHA512_PKCS:
+ hash1 = HashAlgo::SHA512;
+ break;
+ case AsymMech::RSA_SHA1_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-20))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA1;
+ break;
+ case AsymMech::RSA_SHA224_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-28))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA224;
+ break;
+ case AsymMech::RSA_SHA256_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-32))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA256;
+ break;
+ case AsymMech::RSA_SHA384_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-48))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA384;
+ break;
+ case AsymMech::RSA_SHA512_PKCS_PSS:
+ if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 ||
+ ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512)
+ {
+ ERROR_MSG("Invalid parameters");
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen;
+ if (sLen > ((publicKey->getBitLength()+6)/8-2-64))
+ {
+ ERROR_MSG("sLen (%lu) is too large for current key size (%lu)",
+ (unsigned long)sLen, publicKey->getBitLength());
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+ return false;
+ }
+ hash1 = HashAlgo::SHA512;
+ break;
+ case AsymMech::RSA_SSL:
+ hash1 = HashAlgo::MD5;
+ hash2 = HashAlgo::SHA1;
+ break;
+ default:
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash1);
+
+ if (pCurrentHash == NULL || !pCurrentHash->hashInit())
+ {
+ if (pCurrentHash != NULL)
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+ }
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ if (hash2 != HashAlgo::Unknown)
+ {
+ pSecondHash = CryptoFactory::i()->getHashAlgorithm(hash2);
+
+ if (pSecondHash == NULL || !pSecondHash->hashInit())
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (pSecondHash != NULL)
+ {
+ delete pSecondHash;
+ pSecondHash = NULL;
+ }
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool OSSLRSA::verifyUpdate(const ByteString& originalData)
+{
+ if (!AsymmetricAlgorithm::verifyUpdate(originalData))
+ {
+ return false;
+ }
+
+ if (!pCurrentHash->hashUpdate(originalData))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ if ((pSecondHash != NULL) && !pSecondHash->hashUpdate(originalData))
+ {
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ delete pSecondHash;
+ pSecondHash = NULL;
+
+ ByteString dummy;
+ AsymmetricAlgorithm::verifyFinal(dummy);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool OSSLRSA::verifyFinal(const ByteString& signature)
+{
+ // Save necessary state before calling super class verifyFinal
+ OSSLRSAPublicKey* pk = (OSSLRSAPublicKey*) currentPublicKey;
+ AsymMech::Type mechanism = currentMechanism;
+
+ if (!AsymmetricAlgorithm::verifyFinal(signature))
+ {
+ return false;
+ }
+
+ ByteString firstHash, secondHash;
+
+ bool bFirstResult = pCurrentHash->hashFinal(firstHash);
+ bool bSecondResult = (pSecondHash != NULL) ? pSecondHash->hashFinal(secondHash) : true;
+
+ delete pCurrentHash;
+ pCurrentHash = NULL;
+
+ if (pSecondHash != NULL)
+ {
+ delete pSecondHash;
+
+ pSecondHash = NULL;
+ }
+
+ if (!bFirstResult || !bSecondResult)
+ {
+ return false;
+ }
+
+ ByteString digest = firstHash + secondHash;
+
+ // Determine the signature NID type
+ int type = 0;
+ bool isPSS = false;
+ const EVP_MD* hash = NULL;
+
+ switch (mechanism)
+ {
+ case AsymMech::RSA_MD5_PKCS:
+ type = NID_md5;
+ break;
+ case AsymMech::RSA_SHA1_PKCS:
+ type = NID_sha1;
+ break;
+ case AsymMech::RSA_SHA224_PKCS:
+ type = NID_sha224;
+ break;
+ case AsymMech::RSA_SHA256_PKCS:
+ type = NID_sha256;
+ break;
+ case AsymMech::RSA_SHA384_PKCS:
+ type = NID_sha384;
+ break;
+ case AsymMech::RSA_SHA512_PKCS:
+ type = NID_sha512;
+ break;
+ case AsymMech::RSA_SHA1_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha1();
+ break;
+ case AsymMech::RSA_SHA224_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha224();
+ break;
+ case AsymMech::RSA_SHA256_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha256();
+ break;
+ case AsymMech::RSA_SHA384_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha384();
+ break;
+ case AsymMech::RSA_SHA512_PKCS_PSS:
+ isPSS = true;
+ hash = EVP_sha512();
+ break;
+ case AsymMech::RSA_SSL:
+ type = NID_md5_sha1;
+ break;
+ default:
+ break;
+ }
+
+ // Perform the verify operation
+ bool rv;
+
+ if (isPSS)
+ {
+ ByteString plain;
+ plain.resize(pk->getN().size());
+ int result = RSA_public_decrypt(signature.size(),
+ (unsigned char*) signature.const_byte_str(),
+ &plain[0],
+ pk->getOSSLKey(),
+ RSA_NO_PADDING);
+ if (result < 0)
+ {
+ rv = false;
+ ERROR_MSG("RSA public decrypt failed (0x%08X)", ERR_get_error());
+ }
+ else
+ {
+ plain.resize(result);
+ result = RSA_verify_PKCS1_PSS(pk->getOSSLKey(), &digest[0],
+ hash, &plain[0], sLen);
+ if (result == 1)
+ {
+ rv = true;
+ }
+ else
+ {
+ rv = false;
+ ERROR_MSG("RSA PSS verify failed (0x%08X)", ERR_get_error());
+ }
+ }
+ }
+ else
+ {
+ rv = (RSA_verify(type, &digest[0], digest.size(), (unsigned char*) signature.const_byte_str(), signature.size(), pk->getOSSLKey()) == 1);
+
+ if (!rv) ERROR_MSG("RSA verify failed (0x%08X)", ERR_get_error());
+ }
+
+ return rv;
+}
+
+// Encryption functions
+bool OSSLRSA::encrypt(PublicKey* publicKey, const ByteString& data,
+ ByteString& encryptedData, const AsymMech::Type padding)
+{
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(OSSLRSAPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Retrieve the OpenSSL key object
+ RSA* rsa = ((OSSLRSAPublicKey*) publicKey)->getOSSLKey();
+
+ // Check the data and padding algorithm
+ int osslPadding = 0;
+
+ if (padding == AsymMech::RSA_PKCS)
+ {
+ // The size of the input data cannot be more than the modulus
+ // length of the key - 11
+ if (data.size() > (size_t) (RSA_size(rsa) - 11))
+ {
+ ERROR_MSG("Too much data supplied for RSA PKCS #1 encryption");
+
+ return false;
+ }
+
+ osslPadding = RSA_PKCS1_PADDING;
+ }
+ else if (padding == AsymMech::RSA_PKCS_OAEP)
+ {
+ // The size of the input data cannot be more than the modulus
+ // length of the key - 41
+ if (data.size() > (size_t) (RSA_size(rsa) - 41))
+ {
+ ERROR_MSG("Too much data supplied for RSA OAEP encryption");
+
+ return false;
+ }
+
+ osslPadding = RSA_PKCS1_OAEP_PADDING;
+ }
+ else if (padding == AsymMech::RSA)
+ {
+ // The size of the input data should be exactly equal to the modulus length
+ if (data.size() != (size_t) RSA_size(rsa))
+ {
+ ERROR_MSG("Incorrect amount of input data supplied for raw RSA encryption");
+
+ return false;
+ }
+
+ osslPadding = RSA_NO_PADDING;
+ }
+ else
+ {
+ ERROR_MSG("Invalid padding mechanism supplied (%i)", padding);
+
+ return false;
+ }
+
+ // Perform the RSA operation
+ encryptedData.resize(RSA_size(rsa));
+
+ if (RSA_public_encrypt(data.size(), (unsigned char*) data.const_byte_str(), &encryptedData[0], rsa, osslPadding) == -1)
+ {
+ ERROR_MSG("RSA public key encryption failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+
+ return true;
+}
+
+// Decryption functions
+bool OSSLRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData,
+ ByteString& data, const AsymMech::Type padding)
+{
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLRSAPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ // Retrieve the OpenSSL key object
+ RSA* rsa = ((OSSLRSAPrivateKey*) privateKey)->getOSSLKey();
+
+ // Check the input size
+ if (encryptedData.size() != (size_t) RSA_size(rsa))
+ {
+ ERROR_MSG("Invalid amount of input data supplied for RSA decryption");
+
+ return false;
+ }
+
+ // Determine the OpenSSL padding algorithm
+ int osslPadding = 0;
+
+ switch (padding)
+ {
+ case AsymMech::RSA_PKCS:
+ osslPadding = RSA_PKCS1_PADDING;
+ break;
+ case AsymMech::RSA_PKCS_OAEP:
+ osslPadding = RSA_PKCS1_OAEP_PADDING;
+ break;
+ case AsymMech::RSA:
+ osslPadding = RSA_NO_PADDING;
+ break;
+ default:
+ ERROR_MSG("Invalid padding mechanism supplied (%i)", padding);
+ return false;
+ }
+
+ // Perform the RSA operation
+ data.resize(RSA_size(rsa));
+
+ int decSize = RSA_private_decrypt(encryptedData.size(), (unsigned char*) encryptedData.const_byte_str(), &data[0], rsa, osslPadding);
+
+ if (decSize == -1)
+ {
+ ERROR_MSG("RSA private key decryption failed (0x%08X)", ERR_get_error());
+
+ return false;
+ }
+
+ data.resize(decSize);
+
+ return true;
+}
+
+// Key factory
+bool OSSLRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(RSAParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for RSA key generation");
+
+ return false;
+ }
+
+ RSAParameters* params = (RSAParameters*) parameters;
+
+ if (params->getBitLength() < getMinKeySize() || params->getBitLength() > getMaxKeySize())
+ {
+ ERROR_MSG("This RSA key size (%lu) is not supported", params->getBitLength());
+
+ return false;
+ }
+
+ if (params->getBitLength() < 1024)
+ {
+ WARNING_MSG("Using an RSA key size < 1024 bits is not recommended");
+ }
+
+ // Retrieve the desired public exponent
+ unsigned long e = params->getE().long_val();
+
+ // Check the public exponent
+ if ((e == 0) || (e % 2 != 1))
+ {
+ ERROR_MSG("Invalid RSA public exponent %d", e);
+
+ return false;
+ }
+
+ // Generate the key-pair
+ RSA* rsa = RSA_new();
+ if (rsa == NULL)
+ {
+ ERROR_MSG("Failed to instantiate OpenSSL RSA object");
+
+ return false;
+ }
+
+ BIGNUM* bn_e = OSSL::byteString2bn(params->getE());
+
+ // Check if the key was successfully generated
+ if (!RSA_generate_key_ex(rsa, params->getBitLength(), bn_e, NULL))
+ {
+ ERROR_MSG("RSA key generation failed (0x%08X)", ERR_get_error());
+ BN_free(bn_e);
+ RSA_free(rsa);
+
+ return false;
+ }
+ BN_free(bn_e);
+
+ // Create an asymmetric key-pair object to return
+ OSSLRSAKeyPair* kp = new OSSLRSAKeyPair();
+
+ ((OSSLRSAPublicKey*) kp->getPublicKey())->setFromOSSL(rsa);
+ ((OSSLRSAPrivateKey*) kp->getPrivateKey())->setFromOSSL(rsa);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ RSA_free(rsa);
+
+ return true;
+}
+
+unsigned long OSSLRSA::getMinKeySize()
+{
+#ifdef WITH_FIPS
+ // OPENSSL_RSA_FIPS_MIN_MODULUS_BITS is 1024
+ return 1024;
+#else
+ return 512;
+#endif
+}
+
+unsigned long OSSLRSA::getMaxKeySize()
+{
+ return OPENSSL_RSA_MAX_MODULUS_BITS;
+}
+
+bool OSSLRSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLRSAKeyPair* kp = new OSSLRSAKeyPair();
+
+ bool rv = true;
+
+ if (!((RSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((RSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLRSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLRSAPublicKey* pub = new OSSLRSAPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLRSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLRSAPrivateKey* priv = new OSSLRSAPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLRSA::newPublicKey()
+{
+ return (PublicKey*) new OSSLRSAPublicKey();
+}
+
+PrivateKey* OSSLRSA::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLRSAPrivateKey();
+}
+
+AsymmetricParameters* OSSLRSA::newParameters()
+{
+ return (AsymmetricParameters*) new RSAParameters();
+}
+
+bool OSSLRSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ RSAParameters* params = new RSAParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSA.h b/SoftHSMv2/src/lib/crypto/OSSLRSA.h
new file mode 100644
index 0000000..5b7db6d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRSA.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSA.h
+
+ OpenSSL RSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRSA_H
+#define _SOFTHSM_V2_OSSLRSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include <openssl/rsa.h>
+
+class OSSLRSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ OSSLRSA();
+
+ // Destructor
+ virtual ~OSSLRSA();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ HashAlgorithm* pCurrentHash;
+ HashAlgorithm* pSecondHash;
+ size_t sLen;
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSA_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.cpp
new file mode 100644
index 0000000..6465d9c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAKeyPair.cpp
+
+ OpenSSL RSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLRSAKeyPair.h"
+
+// Set the public key
+void OSSLRSAKeyPair::setPublicKey(OSSLRSAPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void OSSLRSAKeyPair::setPrivateKey(OSSLRSAPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* OSSLRSAKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* OSSLRSAKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* OSSLRSAKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* OSSLRSAKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.h
new file mode 100644
index 0000000..546ba96
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAKeyPair.h
+
+ OpenSSL RSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRSAKEYPAIR_H
+#define _SOFTHSM_V2_OSSLRSAKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "OSSLRSAPublicKey.h"
+#include "OSSLRSAPrivateKey.h"
+
+class OSSLRSAKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(OSSLRSAPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(OSSLRSAPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ OSSLRSAPublicKey pubKey;
+
+ // The private key
+ OSSLRSAPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSAKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.cpp
new file mode 100644
index 0000000..26065cf
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAPrivateKey.cpp
+
+ OpenSSL RSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLComp.h"
+#include "OSSLRSAPrivateKey.h"
+#include "OSSLUtil.h"
+#include <openssl/bn.h>
+#include <openssl/x509.h>
+#ifdef WITH_FIPS
+#include <openssl/fips.h>
+#endif
+#include <string.h>
+
+// Constructors
+OSSLRSAPrivateKey::OSSLRSAPrivateKey()
+{
+ rsa = NULL;
+}
+
+OSSLRSAPrivateKey::OSSLRSAPrivateKey(const RSA* inRSA)
+{
+ rsa = NULL;
+
+ setFromOSSL(inRSA);
+}
+
+// Destructor
+OSSLRSAPrivateKey::~OSSLRSAPrivateKey()
+{
+ RSA_free(rsa);
+}
+
+// The type
+/*static*/ const char* OSSLRSAPrivateKey::type = "OpenSSL RSA Private Key";
+
+// Set from OpenSSL representation
+void OSSLRSAPrivateKey::setFromOSSL(const RSA* inRSA)
+{
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_q = NULL;
+ const BIGNUM* bn_dmp1 = NULL;
+ const BIGNUM* bn_dmq1 = NULL;
+ const BIGNUM* bn_iqmp = NULL;
+ const BIGNUM* bn_n = NULL;
+ const BIGNUM* bn_e = NULL;
+ const BIGNUM* bn_d = NULL;
+
+ RSA_get0_factors(inRSA, &bn_p, &bn_q);
+ RSA_get0_crt_params(inRSA, &bn_dmp1, &bn_dmq1, &bn_iqmp);
+ RSA_get0_key(inRSA, &bn_n, &bn_e, &bn_d);
+
+ if (bn_p)
+ {
+ ByteString inP = OSSL::bn2ByteString(bn_p);
+ setP(inP);
+ }
+ if (bn_q)
+ {
+ ByteString inQ = OSSL::bn2ByteString(bn_q);
+ setQ(inQ);
+ }
+ if (bn_dmp1)
+ {
+ ByteString inDP1 = OSSL::bn2ByteString(bn_dmp1);
+ setDP1(inDP1);
+ }
+ if (bn_dmq1)
+ {
+ ByteString inDQ1 = OSSL::bn2ByteString(bn_dmq1);
+ setDQ1(inDQ1);
+ }
+ if (bn_iqmp)
+ {
+ ByteString inPQ = OSSL::bn2ByteString(bn_iqmp);
+ setPQ(inPQ);
+ }
+ if (bn_n)
+ {
+ ByteString inN = OSSL::bn2ByteString(bn_n);
+ setN(inN);
+ }
+ if (bn_e)
+ {
+ ByteString inE = OSSL::bn2ByteString(bn_e);
+ setE(inE);
+ }
+ if (bn_d)
+ {
+ ByteString inD = OSSL::bn2ByteString(bn_d);
+ setD(inD);
+ }
+}
+
+// Check if the key is of the given type
+bool OSSLRSAPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the RSA private key components
+void OSSLRSAPrivateKey::setP(const ByteString& inP)
+{
+ RSAPrivateKey::setP(inP);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+void OSSLRSAPrivateKey::setQ(const ByteString& inQ)
+{
+ RSAPrivateKey::setQ(inQ);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+void OSSLRSAPrivateKey::setPQ(const ByteString& inPQ)
+{
+ RSAPrivateKey::setPQ(inPQ);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+void OSSLRSAPrivateKey::setDP1(const ByteString& inDP1)
+{
+ RSAPrivateKey::setDP1(inDP1);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+void OSSLRSAPrivateKey::setDQ1(const ByteString& inDQ1)
+{
+ RSAPrivateKey::setDQ1(inDQ1);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+void OSSLRSAPrivateKey::setD(const ByteString& inD)
+{
+ RSAPrivateKey::setD(inD);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+
+// Setters for the RSA public key components
+void OSSLRSAPrivateKey::setN(const ByteString& inN)
+{
+ RSAPrivateKey::setN(inN);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+void OSSLRSAPrivateKey::setE(const ByteString& inE)
+{
+ RSAPrivateKey::setE(inE);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString OSSLRSAPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ if (rsa == NULL) createOSSLKey();
+ if (rsa == NULL) return der;
+ EVP_PKEY* pkey = EVP_PKEY_new();
+ if (pkey == NULL) return der;
+ if (!EVP_PKEY_set1_RSA(pkey, rsa))
+ {
+ EVP_PKEY_free(pkey);
+ return der;
+ }
+ PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey);
+ EVP_PKEY_free(pkey);
+ if (p8inf == NULL) return der;
+ int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL);
+ if (len < 0)
+ {
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return der;
+ }
+ der.resize(len);
+ unsigned char* priv = &der[0];
+ int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (len2 != len) der.wipe();
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool OSSLRSAPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ int len = ber.size();
+ if (len <= 0) return false;
+ const unsigned char* priv = ber.const_byte_str();
+ PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len);
+ if (p8 == NULL) return false;
+ EVP_PKEY* pkey = EVP_PKCS82PKEY(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (pkey == NULL) return false;
+ RSA* key = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (key == NULL) return false;
+ setFromOSSL(key);
+ RSA_free(key);
+ return true;
+}
+
+// Retrieve the OpenSSL representation of the key
+RSA* OSSLRSAPrivateKey::getOSSLKey()
+{
+ if (rsa == NULL) createOSSLKey();
+
+ return rsa;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLRSAPrivateKey::createOSSLKey()
+{
+ if (rsa != NULL) return;
+
+ rsa = RSA_new();
+ if (rsa == NULL)
+ {
+ ERROR_MSG("Could not create RSA object");
+ return;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ RSA_set_method(rsa, FIPS_rsa_pkcs1_ssleay());
+ else
+ RSA_set_method(rsa, RSA_PKCS1_SSLeay());
+#else
+ RSA_set_method(rsa, RSA_PKCS1_SSLeay());
+#endif
+
+#else
+ RSA_set_method(rsa, RSA_PKCS1_OpenSSL());
+#endif
+
+ BIGNUM* bn_p = OSSL::byteString2bn(p);
+ BIGNUM* bn_q = OSSL::byteString2bn(q);
+ BIGNUM* bn_dmp1 = OSSL::byteString2bn(dp1);
+ BIGNUM* bn_dmq1 = OSSL::byteString2bn(dq1);
+ BIGNUM* bn_iqmp = OSSL::byteString2bn(pq);
+ BIGNUM* bn_n = OSSL::byteString2bn(n);
+ BIGNUM* bn_e = OSSL::byteString2bn(e);
+ BIGNUM* bn_d = OSSL::byteString2bn(d);
+
+ RSA_set0_factors(rsa, bn_p, bn_q);
+ RSA_set0_crt_params(rsa, bn_dmp1, bn_dmq1, bn_iqmp);
+ RSA_set0_key(rsa, bn_n, bn_e, bn_d);
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.h
new file mode 100644
index 0000000..bb876d5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAPrivateKey.h
+
+ OpenSSL RSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRSAPRIVATEKEY_H
+#define _SOFTHSM_V2_OSSLRSAPRIVATEKEY_H
+
+#include "config.h"
+#include "RSAPrivateKey.h"
+#include <openssl/rsa.h>
+
+class OSSLRSAPrivateKey : public RSAPrivateKey
+{
+public:
+ // Constructors
+ OSSLRSAPrivateKey();
+
+ OSSLRSAPrivateKey(const RSA* inRSA);
+
+ // Destructor
+ virtual ~OSSLRSAPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the RSA private key components
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setPQ(const ByteString& inPQ);
+ virtual void setDP1(const ByteString& inDP1);
+ virtual void setDQ1(const ByteString& inDQ1);
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& inN);
+ virtual void setE(const ByteString& inE);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const RSA* inRSA);
+
+ // Retrieve the OpenSSL representation of the key
+ RSA* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ RSA* rsa;
+
+ // Create the OpenSSL representation of the key
+ void createOSSLKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSAPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.cpp
new file mode 100644
index 0000000..2a6893b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAPublicKey.cpp
+
+ OpenSSL RSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLComp.h"
+#include "OSSLRSAPublicKey.h"
+#include "OSSLUtil.h"
+#include <string.h>
+#include <openssl/bn.h>
+#ifdef WITH_FIPS
+#include <openssl/fips.h>
+#endif
+
+// Constructors
+OSSLRSAPublicKey::OSSLRSAPublicKey()
+{
+ rsa = NULL;
+}
+
+OSSLRSAPublicKey::OSSLRSAPublicKey(const RSA* inRSA)
+{
+ rsa = NULL;
+
+ setFromOSSL(inRSA);
+}
+
+// Destructor
+OSSLRSAPublicKey::~OSSLRSAPublicKey()
+{
+ RSA_free(rsa);
+}
+
+// The type
+/*static*/ const char* OSSLRSAPublicKey::type = "OpenSSL RSA Public Key";
+
+// Check if the key is of the given type
+bool OSSLRSAPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Set from OpenSSL representation
+void OSSLRSAPublicKey::setFromOSSL(const RSA* inRSA)
+{
+ const BIGNUM* bn_n = NULL;
+ const BIGNUM* bn_e = NULL;
+
+ RSA_get0_key(inRSA, &bn_n, &bn_e, NULL);
+
+ if (bn_n)
+ {
+ ByteString inN = OSSL::bn2ByteString(bn_n);
+ setN(inN);
+ }
+ if (bn_e)
+ {
+ ByteString inE = OSSL::bn2ByteString(bn_e);
+ setE(inE);
+ }
+}
+
+// Setters for the RSA public key components
+void OSSLRSAPublicKey::setN(const ByteString& inN)
+{
+ RSAPublicKey::setN(inN);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+void OSSLRSAPublicKey::setE(const ByteString& inE)
+{
+ RSAPublicKey::setE(inE);
+
+ if (rsa)
+ {
+ RSA_free(rsa);
+ rsa = NULL;
+ }
+}
+
+// Retrieve the OpenSSL representation of the key
+RSA* OSSLRSAPublicKey::getOSSLKey()
+{
+ if (rsa == NULL) createOSSLKey();
+
+ return rsa;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLRSAPublicKey::createOSSLKey()
+{
+ if (rsa != NULL) return;
+
+ rsa = RSA_new();
+ if (rsa == NULL)
+ {
+ ERROR_MSG("Could not create RSA object");
+ return;
+ }
+
+ // Use the OpenSSL implementation and not any engine
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+
+#ifdef WITH_FIPS
+ if (FIPS_mode())
+ RSA_set_method(rsa, FIPS_rsa_pkcs1_ssleay());
+ else
+ RSA_set_method(rsa, RSA_PKCS1_SSLeay());
+#else
+ RSA_set_method(rsa, RSA_PKCS1_SSLeay());
+#endif
+
+#else
+ RSA_set_method(rsa, RSA_PKCS1_OpenSSL());
+#endif
+
+ BIGNUM* bn_n = OSSL::byteString2bn(n);
+ BIGNUM* bn_e = OSSL::byteString2bn(e);
+
+ RSA_set0_key(rsa, bn_n, bn_e, NULL);
+}
diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.h
new file mode 100644
index 0000000..98f99f2
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLRSAPublicKey.h
+
+ OpenSSL RSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLRSAPUBLICKEY_H
+#define _SOFTHSM_V2_OSSLRSAPUBLICKEY_H
+
+#include "config.h"
+#include "RSAPublicKey.h"
+#include <openssl/rsa.h>
+
+class OSSLRSAPublicKey : public RSAPublicKey
+{
+public:
+ // Constructors
+ OSSLRSAPublicKey();
+
+ OSSLRSAPublicKey(const RSA* inRSA);
+
+ // Destructor
+ virtual ~OSSLRSAPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& inN);
+ virtual void setE(const ByteString& inE);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const RSA* inRSA);
+
+ // Retrieve the OpenSSL representation of the key
+ RSA* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ RSA* rsa;
+
+ // Create the OpenSSL representation of the key
+ void createOSSLKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLRSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA1.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA1.cpp
new file mode 100644
index 0000000..fcee390
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA1.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA1.h
+
+ OpenSSL SHA1 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA1.h"
+#include <openssl/evp.h>
+
+int OSSLSHA1::getHashSize()
+{
+ return 20;
+}
+
+const EVP_MD* OSSLSHA1::getEVPHash() const
+{
+ return EVP_sha1();
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA1.h b/SoftHSMv2/src/lib/crypto/OSSLSHA1.h
new file mode 100644
index 0000000..011803b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA1.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA1.h
+
+ OpenSSL SHA1 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA1_H
+#define _SOFTHSM_V2_OSSLSHA1_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA1 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA1_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA224.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA224.cpp
new file mode 100644
index 0000000..7dacf56
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA224.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA224.h
+
+ OpenSSL SHA224 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA224.h"
+#include <openssl/evp.h>
+
+int OSSLSHA224::getHashSize()
+{
+ return 28;
+}
+
+const EVP_MD* OSSLSHA224::getEVPHash() const
+{
+ return EVP_sha224();
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA224.h b/SoftHSMv2/src/lib/crypto/OSSLSHA224.h
new file mode 100644
index 0000000..f83ddf7
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA224.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA224.h
+
+ OpenSSL SHA224 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA224_H
+#define _SOFTHSM_V2_OSSLSHA224_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA224 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA224_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA256.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA256.cpp
new file mode 100644
index 0000000..d8b57b0
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA256.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA256.h
+
+ OpenSSL SHA256 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA256.h"
+#include <openssl/evp.h>
+
+int OSSLSHA256::getHashSize()
+{
+ return 32;
+}
+
+const EVP_MD* OSSLSHA256::getEVPHash() const
+{
+ return EVP_sha256();
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA256.h b/SoftHSMv2/src/lib/crypto/OSSLSHA256.h
new file mode 100644
index 0000000..1f22386
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA256.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA256.h
+
+ OpenSSL SHA256 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA256_H
+#define _SOFTHSM_V2_OSSLSHA256_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA256 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA256_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA384.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA384.cpp
new file mode 100644
index 0000000..01b6fce
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA384.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA384.h
+
+ OpenSSL SHA384 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA384.h"
+#include <openssl/evp.h>
+
+int OSSLSHA384::getHashSize()
+{
+ return 48;
+}
+
+const EVP_MD* OSSLSHA384::getEVPHash() const
+{
+ return EVP_sha384();
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA384.h b/SoftHSMv2/src/lib/crypto/OSSLSHA384.h
new file mode 100644
index 0000000..9b93724
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA384.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA384.h
+
+ OpenSSL SHA384 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA384_H
+#define _SOFTHSM_V2_OSSLSHA384_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA384 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA384_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA512.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA512.cpp
new file mode 100644
index 0000000..4533354
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA512.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA512.h
+
+ OpenSSL SHA512 implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSSLSHA512.h"
+#include <openssl/evp.h>
+
+int OSSLSHA512::getHashSize()
+{
+ return 64;
+}
+
+const EVP_MD* OSSLSHA512::getEVPHash() const
+{
+ return EVP_sha512();
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA512.h b/SoftHSMv2/src/lib/crypto/OSSLSHA512.h
new file mode 100644
index 0000000..cb266d8
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLSHA512.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLSHA512.h
+
+ OpenSSL SHA512 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLSHA512_H
+#define _SOFTHSM_V2_OSSLSHA512_H
+
+#include "config.h"
+#include "OSSLEVPHashAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLSHA512 : public OSSLEVPHashAlgorithm
+{
+ virtual int getHashSize();
+protected:
+ virtual const EVP_MD* getEVPHash() const;
+};
+
+#endif // !_SOFTHSM_V2_OSSLSHA512_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp b/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp
new file mode 100644
index 0000000..981bb98
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLUtil.h
+
+ OpenSSL convenience functions
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSSLUtil.h"
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+
+// Convert an OpenSSL BIGNUM to a ByteString
+ByteString OSSL::bn2ByteString(const BIGNUM* bn)
+{
+ ByteString rv;
+
+ if (bn != NULL)
+ {
+ rv.resize(BN_num_bytes(bn));
+ BN_bn2bin(bn, &rv[0]);
+ }
+
+ return rv;
+}
+
+// Convert a ByteString to an OpenSSL BIGNUM
+BIGNUM* OSSL::byteString2bn(const ByteString& byteString)
+{
+ if (byteString.size() == 0) return NULL;
+
+ return BN_bin2bn(byteString.const_byte_str(), byteString.size(), NULL);
+}
+
+#ifdef WITH_ECC
+// Convert an OpenSSL EC GROUP to a ByteString
+ByteString OSSL::grp2ByteString(const EC_GROUP* grp)
+{
+ ByteString rv;
+
+ if (grp != NULL)
+ {
+ rv.resize(i2d_ECPKParameters(grp, NULL));
+ unsigned char *p = &rv[0];
+ i2d_ECPKParameters(grp, &p);
+ }
+
+ return rv;
+}
+
+// Convert a ByteString to an OpenSSL EC GROUP
+EC_GROUP* OSSL::byteString2grp(const ByteString& byteString)
+{
+ const unsigned char *p = byteString.const_byte_str();
+ return d2i_ECPKParameters(NULL, &p, byteString.size());
+}
+
+// POINT_CONVERSION_UNCOMPRESSED 0x04
+
+// Convert an OpenSSL EC POINT in the given EC GROUP to a ByteString
+ByteString OSSL::pt2ByteString(const EC_POINT* pt, const EC_GROUP* grp)
+{
+ ByteString rv;
+
+ if (pt != NULL && grp != NULL)
+ {
+ size_t len = EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+ // Definite, short
+ if (len <= 0x7f)
+ {
+ rv.resize(2 + len);
+ rv[0] = V_ASN1_OCTET_STRING;
+ rv[1] = len & 0x7f;
+ EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, &rv[2], len, NULL);
+ }
+ // Definite, long
+ else
+ {
+ // Get the number of length octets
+ ByteString length(len);
+ unsigned int counter = 0;
+ while (length[counter] == 0 && counter < (length.size()-1)) counter++;
+ ByteString lengthOctets(&length[counter], length.size() - counter);
+
+ rv.resize(len + 2 + lengthOctets.size());
+ rv[0] = V_ASN1_OCTET_STRING;
+ rv[1] = 0x80 | lengthOctets.size();
+ memcpy(&rv[2], &lengthOctets[0], lengthOctets.size());
+ EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, &rv[2 + lengthOctets.size()], len, NULL);
+ }
+ }
+
+ return rv;
+}
+
+// Convert a ByteString to an OpenSSL EC POINT in the given EC GROUP
+EC_POINT* OSSL::byteString2pt(const ByteString& byteString, const EC_GROUP* grp)
+{
+ size_t len = byteString.size();
+ size_t controlOctets = 2;
+ if (len < controlOctets)
+ {
+ ERROR_MSG("Undersized EC point");
+
+ return NULL;
+ }
+
+ ByteString repr = byteString;
+
+ if (repr[0] != V_ASN1_OCTET_STRING)
+ {
+ ERROR_MSG("EC point tag is not OCTET STRING");
+
+ return NULL;
+ }
+
+ // Definite, short
+ if (repr[1] < 0x80)
+ {
+ if (repr[1] != (len - controlOctets))
+ {
+ if (repr[1] < (len - controlOctets))
+ {
+ ERROR_MSG("Underrun EC point");
+ }
+ else
+ {
+ ERROR_MSG("Overrun EC point");
+ }
+
+ return NULL;
+ }
+ }
+ // Definite, long
+ else
+ {
+ size_t lengthOctets = repr[1] & 0x7f;
+ controlOctets += lengthOctets;
+
+ if (controlOctets >= repr.size())
+ {
+ ERROR_MSG("Undersized EC point");
+
+ return NULL;
+ }
+
+ ByteString length(&repr[2], lengthOctets);
+
+ if (length.long_val() != (len - controlOctets))
+ {
+ if (length.long_val() < (len - controlOctets))
+ {
+ ERROR_MSG("Underrun EC point");
+ }
+ else
+ {
+ ERROR_MSG("Overrun EC point");
+ }
+
+ return NULL;
+ }
+ }
+
+ EC_POINT* pt = EC_POINT_new(grp);
+ if (!EC_POINT_oct2point(grp, pt, &repr[controlOctets], len - controlOctets, NULL))
+ {
+ ERROR_MSG("EC_POINT_oct2point failed: %s", ERR_error_string(ERR_get_error(), NULL));
+ EC_POINT_free(pt);
+ return NULL;
+ }
+ return pt;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLUtil.h b/SoftHSMv2/src/lib/crypto/OSSLUtil.h
new file mode 100644
index 0000000..f353cc6
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLUtil.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLUtil.h
+
+ OpenSSL convenience functions
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLUTIL_H
+#define _SOFTHSM_V2_OSSLUTIL_H
+
+#include "config.h"
+#include "ByteString.h"
+#include <openssl/bn.h>
+#ifdef WITH_ECC
+#include <openssl/ec.h>
+#endif
+
+namespace OSSL
+{
+ // Convert an OpenSSL BIGNUM to a ByteString
+ ByteString bn2ByteString(const BIGNUM* bn);
+
+ // Convert a ByteString to an OpenSSL BIGNUM
+ BIGNUM* byteString2bn(const ByteString& byteString);
+
+#ifdef WITH_ECC
+ // Convert an OpenSSL EC GROUP to a ByteString
+ ByteString grp2ByteString(const EC_GROUP* grp);
+
+ // Convert a ByteString to an OpenSSL EC GROUP
+ EC_GROUP* byteString2grp(const ByteString& byteString);
+
+ // Convert an OpenSSL EC POINT in the given EC GROUP to a ByteString
+ ByteString pt2ByteString(const EC_POINT* pt, const EC_GROUP* grp);
+
+ // Convert a ByteString to an OpenSSL EC POINT in the given EC GROUP
+ EC_POINT* byteString2pt(const ByteString& byteString, const EC_GROUP* grp);
+#endif
+}
+
+#endif // !_SOFTHSM_V2_OSSLUTIL_H
+
diff --git a/SoftHSMv2/src/lib/crypto/PrivateKey.h b/SoftHSMv2/src/lib/crypto/PrivateKey.h
new file mode 100644
index 0000000..cb14539
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/PrivateKey.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ PrivateKey.h
+
+ Base class for private key classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_PRIVATEKEY_H
+#define _SOFTHSM_V2_PRIVATEKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include <string>
+
+class PrivateKey : public Serialisable
+{
+public:
+ // Base constructors
+ PrivateKey() { }
+
+ PrivateKey(const PrivateKey& in);
+
+ // Destructor
+ virtual ~PrivateKey() { }
+
+ // Check if the private key is of the given type
+ virtual bool isOfType(const char* inType) = 0;
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const = 0;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const = 0;
+
+ // Serialisation
+ virtual ByteString serialise() const = 0;
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode() = 0;
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber) = 0;
+};
+
+#endif // !_SOFTHSM_V2_PRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/PublicKey.h b/SoftHSMv2/src/lib/crypto/PublicKey.h
new file mode 100644
index 0000000..2207e8d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/PublicKey.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ PublicKey.h
+
+ Base class for public key classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_PUBLICKEY_H
+#define _SOFTHSM_V2_PUBLICKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+
+class PublicKey : public Serialisable
+{
+public:
+ // Base constructors
+ PublicKey() { }
+
+ PublicKey(const PublicKey& /*in*/) { }
+
+ // Destructor
+ virtual ~PublicKey() { }
+
+ // Check if it is of the given type
+ virtual bool isOfType(const char* inType) = 0;
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const = 0;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const = 0;
+
+ // Serialisation
+ virtual ByteString serialise() const = 0;
+};
+
+#endif // !_SOFTHSM_V2_PUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/RNG.h b/SoftHSMv2/src/lib/crypto/RNG.h
new file mode 100644
index 0000000..ea0548f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/RNG.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RNG.h
+
+ Base class for random number generator classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RNG_H
+#define _SOFTHSM_V2_RNG_H
+
+#include "config.h"
+#include "ByteString.h"
+
+struct RNGImpl
+{
+ enum Type
+ {
+ Unknown,
+ Default
+ };
+};
+
+class RNG
+{
+public:
+ // Base constructor
+ RNG() { }
+
+ // Destructor
+ virtual ~RNG() { }
+
+ // Generate random data
+ virtual bool generateRandom(ByteString& data, const size_t len) = 0;
+
+ // Seed the random pool
+ virtual void seed(ByteString& seedData) = 0;
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_RNG_H
+
diff --git a/SoftHSMv2/src/lib/crypto/RSAParameters.cpp b/SoftHSMv2/src/lib/crypto/RSAParameters.cpp
new file mode 100644
index 0000000..26ba7a7
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/RSAParameters.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAParameters.h
+
+ RSA parameters (only used for key generation)
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "RSAParameters.h"
+#include <string.h>
+
+// The type
+/*static*/ const char* RSAParameters::type = "Generic RSA parameters";
+
+// Set the public exponent
+void RSAParameters::setE(const ByteString& inE)
+{
+ e = inE;
+}
+
+// Set the bit length
+void RSAParameters::setBitLength(const size_t inBitLen)
+{
+ bitLen = inBitLen;
+}
+
+// Get the public exponent
+const ByteString& RSAParameters::getE() const
+{
+ return e;
+}
+
+// Get the bit length
+size_t RSAParameters::getBitLength() const
+{
+ return bitLen;
+}
+
+// Are the parameters of the given type?
+bool RSAParameters::areOfType(const char* inType)
+{
+ return (strcmp(type, inType) == 0);
+}
+
+// Serialisation
+ByteString RSAParameters::serialise() const
+{
+ ByteString len(bitLen);
+
+ return e.serialise() + len.serialise();
+}
+
+bool RSAParameters::deserialise(ByteString& serialised)
+{
+ ByteString dE = ByteString::chainDeserialise(serialised);
+ ByteString dLen = ByteString::chainDeserialise(serialised);
+
+ if ((dE.size() == 0) ||
+ (dLen.size() == 0))
+ {
+ return false;
+ }
+
+ setE(dE);
+ setBitLength(dLen.long_val());
+
+ return true;
+}
diff --git a/SoftHSMv2/src/lib/crypto/RSAParameters.h b/SoftHSMv2/src/lib/crypto/RSAParameters.h
new file mode 100644
index 0000000..c8e748e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/RSAParameters.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAParameters.h
+
+ RSA parameters (only used for key generation)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RSAPARAMETERS_H
+#define _SOFTHSM_V2_RSAPARAMETERS_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "AsymmetricParameters.h"
+
+class RSAParameters : public AsymmetricParameters
+{
+public:
+ // Base constructor
+ RSAParameters() : bitLen(0) { }
+
+ // The type
+ static const char* type;
+
+ // Set the public exponent
+ void setE(const ByteString& inE);
+
+ // Set the bit length
+ void setBitLength(const size_t inBitLen);
+
+ // Get the public exponent
+ const ByteString& getE() const;
+
+ // Get the bit length
+ size_t getBitLength() const;
+
+ // Are the parameters of the given type?
+ virtual bool areOfType(const char* inType);
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+private:
+ ByteString e;
+ size_t bitLen;
+};
+
+#endif // !_SOFTHSM_V2_RSAPARAMETERS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/RSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/RSAPrivateKey.cpp
new file mode 100644
index 0000000..7b3d43d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/RSAPrivateKey.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAPrivateKey.cpp
+
+ RSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "RSAPrivateKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* RSAPrivateKey::type = "Abstract RSA private key";
+
+// Check if the key is of the given type
+bool RSAPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long RSAPrivateKey::getBitLength() const
+{
+ return getN().bits();
+}
+
+// Get the output length
+unsigned long RSAPrivateKey::getOutputLength() const
+{
+ // Also handle odd number of bits (bits % 8 != 0)
+ return (getBitLength() + 7) / 8;
+}
+
+// Setters for the RSA private key components
+void RSAPrivateKey::setP(const ByteString& inP)
+{
+ p = inP;
+}
+
+void RSAPrivateKey::setQ(const ByteString& inQ)
+{
+ q = inQ;
+}
+
+void RSAPrivateKey::setPQ(const ByteString& inPQ)
+{
+ pq = inPQ;
+}
+
+void RSAPrivateKey::setDP1(const ByteString& inDP1)
+{
+ dp1 = inDP1;
+}
+
+void RSAPrivateKey::setDQ1(const ByteString& inDQ1)
+{
+ dq1 = inDQ1;
+}
+
+void RSAPrivateKey::setD(const ByteString& inD)
+{
+ d = inD;
+}
+
+// Setters for the RSA public key components
+void RSAPrivateKey::setN(const ByteString& inN)
+{
+ n = inN;
+}
+
+void RSAPrivateKey::setE(const ByteString& inE)
+{
+ e = inE;
+}
+
+// Getters for the RSA private key components
+const ByteString& RSAPrivateKey::getP() const
+{
+ return p;
+}
+
+const ByteString& RSAPrivateKey::getQ() const
+{
+ return q;
+}
+
+const ByteString& RSAPrivateKey::getPQ() const
+{
+ return pq;
+}
+
+const ByteString& RSAPrivateKey::getDP1() const
+{
+ return dp1;
+}
+
+const ByteString& RSAPrivateKey::getDQ1() const
+{
+ return dq1;
+}
+
+const ByteString& RSAPrivateKey::getD() const
+{
+ return d;
+}
+
+// Getters for the RSA public key components
+const ByteString& RSAPrivateKey::getN() const
+{
+ return n;
+}
+
+const ByteString& RSAPrivateKey::getE() const
+{
+ return e;
+}
+
+// Serialisation
+ByteString RSAPrivateKey::serialise() const
+{
+ return p.serialise() +
+ q.serialise() +
+ pq.serialise() +
+ dp1.serialise() +
+ dq1.serialise() +
+ d.serialise() +
+ n.serialise() +
+ e.serialise();
+}
+
+bool RSAPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dP = ByteString::chainDeserialise(serialised);
+ ByteString dQ = ByteString::chainDeserialise(serialised);
+ ByteString dPQ = ByteString::chainDeserialise(serialised);
+ ByteString dDP1 = ByteString::chainDeserialise(serialised);
+ ByteString dDQ1 = ByteString::chainDeserialise(serialised);
+ ByteString dD = ByteString::chainDeserialise(serialised);
+ ByteString dN = ByteString::chainDeserialise(serialised);
+ ByteString dE = ByteString::chainDeserialise(serialised);
+
+ if ((dD.size() == 0) ||
+ (dN.size() == 0) ||
+ (dE.size() == 0))
+ {
+ return false;
+ }
+
+ setP(dP);
+ setQ(dQ);
+ setPQ(dPQ);
+ setDP1(dDP1);
+ setDQ1(dDQ1);
+ setD(dD);
+ setN(dN);
+ setE(dE);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/RSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/RSAPrivateKey.h
new file mode 100644
index 0000000..3c40c3c
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/RSAPrivateKey.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAPrivateKey.h
+
+ RSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RSAPRIVATEKEY_H
+#define _SOFTHSM_V2_RSAPRIVATEKEY_H
+
+#include "config.h"
+#include "PrivateKey.h"
+
+class RSAPrivateKey : public PrivateKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the RSA private key components
+ virtual void setP(const ByteString& inP);
+ virtual void setQ(const ByteString& inQ);
+ virtual void setPQ(const ByteString& inPQ);
+ virtual void setDP1(const ByteString& inDP1);
+ virtual void setDQ1(const ByteString& inDQ1);
+ virtual void setD(const ByteString& inD);
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& inN);
+ virtual void setE(const ByteString& inE);
+
+ // Getters for the RSA private key components
+ virtual const ByteString& getP() const;
+ virtual const ByteString& getQ() const;
+ virtual const ByteString& getPQ() const;
+ virtual const ByteString& getDP1() const;
+ virtual const ByteString& getDQ1() const;
+ virtual const ByteString& getD() const;
+
+ // Getters for the RSA public key components
+ virtual const ByteString& getN() const;
+ virtual const ByteString& getE() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Private components
+ ByteString p,q,pq,dp1,dq1,d;
+
+ // Public components
+ ByteString n,e;
+};
+
+#endif // !_SOFTHSM_V2_RSAPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/RSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/RSAPublicKey.cpp
new file mode 100644
index 0000000..e0e05cd
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/RSAPublicKey.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAPublicKey.cpp
+
+ RSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "RSAPublicKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* RSAPublicKey::type = "Abstract RSA public key";
+
+// Check if the key is of the given type
+bool RSAPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long RSAPublicKey::getBitLength() const
+{
+ return getN().bits();
+}
+
+// Get the output length
+unsigned long RSAPublicKey::getOutputLength() const
+{
+ // Also handle odd number of bits (bits % 8 != 0)
+ return (getBitLength() + 7) / 8;
+}
+
+// Setters for the RSA public key components
+void RSAPublicKey::setN(const ByteString& inN)
+{
+ n = inN;
+}
+
+void RSAPublicKey::setE(const ByteString& inE)
+{
+ e = inE;
+}
+
+// Getters for the RSA public key components
+const ByteString& RSAPublicKey::getN() const
+{
+ return n;
+}
+
+const ByteString& RSAPublicKey::getE() const
+{
+ return e;
+}
+
+// Serialisation
+ByteString RSAPublicKey::serialise() const
+{
+ return n.serialise() +
+ e.serialise();
+}
+
+bool RSAPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dN = ByteString::chainDeserialise(serialised);
+ ByteString dE = ByteString::chainDeserialise(serialised);
+
+ if ((dN.size() == 0) ||
+ (dE.size() == 0))
+ {
+ return false;
+ }
+
+ setN(dN);
+ setE(dE);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/RSAPublicKey.h b/SoftHSMv2/src/lib/crypto/RSAPublicKey.h
new file mode 100644
index 0000000..9256966
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/RSAPublicKey.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSAPublicKey.h
+
+ RSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RSAPUBLICKEY_H
+#define _SOFTHSM_V2_RSAPUBLICKEY_H
+
+#include "config.h"
+#include "PublicKey.h"
+
+class RSAPublicKey : public PublicKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Setters for the RSA public key components
+ virtual void setN(const ByteString& inN);
+ virtual void setE(const ByteString& inE);
+
+ // Getters for the RSA public key components
+ virtual const ByteString& getN() const;
+ virtual const ByteString& getE() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Public components
+ ByteString n,e;
+};
+
+#endif // !_SOFTHSM_V2_RSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.cpp
new file mode 100644
index 0000000..1db8f50
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricAlgorithm.cpp
+
+ Base class for symmetric algorithm classes
+ *****************************************************************************/
+
+#include "SymmetricAlgorithm.h"
+#include <algorithm>
+#include <string.h>
+
+SymmetricAlgorithm::SymmetricAlgorithm()
+{
+ currentKey = NULL;
+ currentCipherMode = SymMode::Unknown;
+ currentPaddingMode = true;
+ currentCounterBits = 0;
+ currentTagBytes = 0;
+ currentOperation = NONE;
+ currentBufferSize = 0;
+}
+
+bool SymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& /*IV = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& /*aad = ByteString()*/, size_t tagBytes /* = 0 */)
+{
+ if ((key == NULL) || (currentOperation != NONE))
+ {
+ return false;
+ }
+
+ currentKey = key;
+ currentCipherMode = mode;
+ currentPaddingMode = padding;
+ currentCounterBits = counterBits;
+ currentTagBytes = tagBytes;
+ currentOperation = ENCRYPT;
+ currentBufferSize = 0;
+
+ return true;
+}
+
+bool SymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& /*encryptedData*/)
+{
+ if (currentOperation != ENCRYPT)
+ {
+ return false;
+ }
+
+ currentBufferSize += data.size();
+
+ return true;
+}
+
+bool SymmetricAlgorithm::encryptFinal(ByteString& /*encryptedData*/)
+{
+ if (currentOperation != ENCRYPT)
+ {
+ return false;
+ }
+
+ currentKey = NULL;
+ currentCipherMode = SymMode::Unknown;
+ currentPaddingMode = true;
+ currentCounterBits = 0;
+ currentTagBytes = 0;
+ currentOperation = NONE;
+ currentBufferSize = 0;
+
+ return true;
+}
+
+bool SymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& /*IV = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& /*aad = ByteString()*/, size_t tagBytes /* = 0 */)
+{
+ if ((key == NULL) || (currentOperation != NONE))
+ {
+ return false;
+ }
+
+ currentKey = key;
+ currentCipherMode = mode;
+ currentPaddingMode = padding;
+ currentCounterBits = counterBits;
+ currentTagBytes = tagBytes;
+ currentOperation = DECRYPT;
+ currentBufferSize = 0;
+ currentAEADBuffer.wipe();
+
+ return true;
+}
+
+
+bool SymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& /*data*/)
+{
+ if (currentOperation != DECRYPT)
+ {
+ return false;
+ }
+
+ currentBufferSize += encryptedData.size();
+ currentAEADBuffer += encryptedData;
+
+ return true;
+}
+
+bool SymmetricAlgorithm::decryptFinal(ByteString& /*data*/)
+{
+ if (currentOperation != DECRYPT)
+ {
+ return false;
+ }
+
+ currentKey = NULL;
+ currentCipherMode = SymMode::Unknown;
+ currentPaddingMode = true;
+ currentCounterBits = 0;
+ currentTagBytes = 0;
+ currentOperation = NONE;
+ currentBufferSize = 0;
+ currentAEADBuffer.wipe();
+
+ return true;
+}
+
+// Key factory
+void SymmetricAlgorithm::recycleKey(SymmetricKey* toRecycle)
+{
+ delete toRecycle;
+}
+
+bool SymmetricAlgorithm::generateKey(SymmetricKey& key, RNG* rng /* = NULL */)
+{
+ if (rng == NULL)
+ {
+ return false;
+ }
+
+ if (key.getBitLen() == 0)
+ {
+ return false;
+ }
+
+ ByteString keyBits;
+
+ if (!rng->generateRandom(keyBits, key.getBitLen()/8))
+ {
+ return false;
+ }
+
+ return key.setKeyBits(keyBits);
+}
+
+bool SymmetricAlgorithm::reconstructKey(SymmetricKey& key, const ByteString& serialisedData)
+{
+ return key.setKeyBits(serialisedData);
+}
+
+SymMode::Type SymmetricAlgorithm::getCipherMode()
+{
+ return currentCipherMode;
+}
+
+bool SymmetricAlgorithm::getPaddingMode()
+{
+ return currentPaddingMode;
+}
+
+unsigned long SymmetricAlgorithm::getBufferSize()
+{
+ return currentBufferSize;
+}
+
+size_t SymmetricAlgorithm::getTagBytes()
+{
+ return currentTagBytes;
+}
+
+bool SymmetricAlgorithm::isStreamCipher()
+{
+ switch (currentCipherMode)
+ {
+ case SymMode::CFB:
+ case SymMode::CTR:
+ case SymMode::GCM:
+ case SymMode::OFB:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool SymmetricAlgorithm::isBlockCipher()
+{
+ switch (currentCipherMode)
+ {
+ case SymMode::CBC:
+ case SymMode::ECB:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
diff --git a/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.h
new file mode 100644
index 0000000..7e060c4
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricAlgorithm.h
+
+ Base class for symmetric algorithm classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SYMMETRICALGORITHM_H
+#define _SOFTHSM_V2_SYMMETRICALGORITHM_H
+
+#include <string>
+#include "config.h"
+#include "SymmetricKey.h"
+#include "RNG.h"
+
+struct SymAlgo
+{
+ enum Type
+ {
+ Unknown,
+ AES,
+ DES,
+ DES3
+ };
+};
+
+struct SymMode
+{
+ enum Type
+ {
+ Unknown,
+ CBC,
+ CFB,
+ CTR,
+ ECB,
+ GCM,
+ OFB
+ };
+};
+
+struct SymWrap
+{
+ enum Type
+ {
+ Unknown,
+ AES_KEYWRAP,
+ AES_KEYWRAP_PAD
+ };
+};
+
+class SymmetricAlgorithm
+{
+public:
+ // Base constructors
+ SymmetricAlgorithm();
+
+ // Destructor
+ virtual ~SymmetricAlgorithm() { }
+
+ // Encryption functions
+ virtual bool encryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0);
+ virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData);
+ virtual bool encryptFinal(ByteString& encryptedData);
+
+ // Decryption functions
+ virtual bool decryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0);
+ virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data);
+ virtual bool decryptFinal(ByteString& data);
+
+ // Wrap/Unwrap keys
+ virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) = 0;
+
+ virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) = 0;
+
+ // Key factory
+ virtual void recycleKey(SymmetricKey* toRecycle);
+ virtual bool generateKey(SymmetricKey& key, RNG* rng = NULL);
+ virtual bool reconstructKey(SymmetricKey& key, const ByteString& serialisedData);
+
+ // Return cipher information
+ virtual size_t getBlockSize() const = 0;
+ virtual SymMode::Type getCipherMode();
+ virtual bool getPaddingMode();
+ virtual unsigned long getBufferSize();
+ virtual size_t getTagBytes();
+ virtual bool isStreamCipher();
+ virtual bool isBlockCipher();
+ virtual bool checkMaximumBytes(unsigned long bytes) = 0;
+
+protected:
+ // The current key
+ const SymmetricKey* currentKey;
+
+ // The current cipher mode
+ SymMode::Type currentCipherMode;
+
+ // The current padding
+ bool currentPaddingMode;
+
+ // The current counter bits
+ size_t currentCounterBits;
+
+ // The current tag bytes
+ size_t currentTagBytes;
+
+ // The current operation
+ enum
+ {
+ NONE,
+ ENCRYPT,
+ DECRYPT
+ }
+ currentOperation;
+
+ // The current number of bytes in buffer
+ unsigned long currentBufferSize;
+
+ // The current AEAD buffer
+ ByteString currentAEADBuffer;
+};
+
+#endif // !_SOFTHSM_V2_SYMMETRICALGORITHM_H
+
diff --git a/SoftHSMv2/src/lib/crypto/SymmetricKey.cpp b/SoftHSMv2/src/lib/crypto/SymmetricKey.cpp
new file mode 100644
index 0000000..550a144
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/SymmetricKey.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricKey.cpp
+
+ Base class for symmetric key classes
+ *****************************************************************************/
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+#include "SymmetricKey.h"
+#include "CryptoFactory.h"
+
+// Base constructors
+SymmetricKey::SymmetricKey(size_t inBitLen /* = 0 */)
+{
+ bitLen = inBitLen;
+}
+
+SymmetricKey::SymmetricKey(const SymmetricKey& in)
+{
+ keyData = in.keyData;
+ bitLen = in.bitLen;
+}
+
+// Set the key
+bool SymmetricKey::setKeyBits(const ByteString& keybits)
+{
+ if ((bitLen > 0) && ((keybits.size() * 8) != bitLen))
+ {
+ return false;
+ }
+
+ keyData = keybits;
+
+ return true;
+}
+
+// Get the key
+const ByteString& SymmetricKey::getKeyBits() const
+{
+ return keyData;
+}
+
+// Get the key check value
+ByteString SymmetricKey::getKeyCheckValue() const
+{
+ ByteString digest;
+
+ HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA1);
+ if (hash == NULL) return digest;
+
+ if (!hash->hashInit() ||
+ !hash->hashUpdate(keyData) ||
+ !hash->hashFinal(digest))
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ return digest;
+ }
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ digest.resize(3);
+
+ return digest;
+}
+
+// Serialisation
+ByteString SymmetricKey::serialise() const
+{
+ return keyData;
+}
+
+// Set the bit length
+void SymmetricKey::setBitLen(const size_t inBitLen)
+{
+ bitLen = inBitLen;
+}
+
+// Retrieve the bit length
+size_t SymmetricKey::getBitLen() const
+{
+ return bitLen;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/SymmetricKey.h b/SoftHSMv2/src/lib/crypto/SymmetricKey.h
new file mode 100644
index 0000000..593040b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/SymmetricKey.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricKey.h
+
+ Base class for symmetric key classes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SYMMETRICKEY_H
+#define _SOFTHSM_V2_SYMMETRICKEY_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "Serialisable.h"
+
+class SymmetricKey : public Serialisable
+{
+public:
+ // Base constructors
+ SymmetricKey(size_t inBitLen = 0);
+
+ SymmetricKey(const SymmetricKey& in);
+
+ // Destructor
+ virtual ~SymmetricKey() { }
+
+ // Set the key
+ virtual bool setKeyBits(const ByteString& keybits);
+
+ // Get the key
+ virtual const ByteString& getKeyBits() const;
+
+ // Get the key check value
+ virtual ByteString getKeyCheckValue() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+
+ // Set the bit length
+ virtual void setBitLen(const size_t inBitLen);
+
+ // Retrieve the bit length
+ virtual size_t getBitLen() const;
+
+protected:
+ // The key
+ ByteString keyData;
+
+ // The key length in bits
+ size_t bitLen;
+};
+
+#endif // !_SOFTHSM_V2_SYMMETRICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/odd.h b/SoftHSMv2/src/lib/crypto/odd.h
new file mode 100644
index 0000000..0ab2997
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/odd.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ odd.h
+
+ Odd parity table
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ODD_H
+#define _SOFTHSM_V2_ODD_H
+
+const unsigned char odd_parity[256] = {
+ 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07,
+ 0x08, 0x08, 0x0B, 0x0B, 0x0D, 0x0D, 0x0E, 0x0E,
+ 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
+ 0x19, 0x19, 0x1A, 0x1A, 0x1C, 0x1C, 0x1F, 0x1F,
+ 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26,
+ 0x29, 0x29, 0x2A, 0x2A, 0x2C, 0x2C, 0x2F, 0x2F,
+ 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37,
+ 0x38, 0x38, 0x3B, 0x3B, 0x3D, 0x3D, 0x3E, 0x3E,
+ 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
+ 0x49, 0x49, 0x4A, 0x4A, 0x4C, 0x4C, 0x4F, 0x4F,
+ 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57,
+ 0x58, 0x58, 0x5B, 0x5B, 0x5D, 0x5D, 0x5E, 0x5E,
+ 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67,
+ 0x68, 0x68, 0x6B, 0x6B, 0x6D, 0x6D, 0x6E, 0x6E,
+ 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
+ 0x79, 0x79, 0x7A, 0x7A, 0x7C, 0x7C, 0x7F, 0x7F,
+ 0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86,
+ 0x89, 0x89, 0x8A, 0x8A, 0x8C, 0x8C, 0x8F, 0x8F,
+ 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97,
+ 0x98, 0x98, 0x9B, 0x9B, 0x9D, 0x9D, 0x9E, 0x9E,
+ 0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA4, 0xA7, 0xA7,
+ 0xA8, 0xA8, 0xAB, 0xAB, 0xAD, 0xAD, 0xAE, 0xAE,
+ 0xB0, 0xB0, 0xB3, 0xB3, 0xB5, 0xB5, 0xB6, 0xB6,
+ 0xB9, 0xB9, 0xBA, 0xBA, 0xBC, 0xBC, 0xBF, 0xBF,
+ 0xC1, 0xC1, 0xC2, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7,
+ 0xC8, 0xC8, 0xCB, 0xCB, 0xCD, 0xCD, 0xCE, 0xCE,
+ 0xD0, 0xD0, 0xD3, 0xD3, 0xD5, 0xD5, 0xD6, 0xD6,
+ 0xD9, 0xD9, 0xDA, 0xDA, 0xDC, 0xDC, 0xDF, 0xDF,
+ 0xE0, 0xE0, 0xE3, 0xE3, 0xE5, 0xE5, 0xE6, 0xE6,
+ 0xE9, 0xE9, 0xEA, 0xEA, 0xEC, 0xEC, 0xEF, 0xEF,
+ 0xF1, 0xF1, 0xF2, 0xF2, 0xF4, 0xF4, 0xF7, 0xF7,
+ 0xF8, 0xF8, 0xFB, 0xFB, 0xFD, 0xFD, 0xFE, 0xFE
+};
+
+#endif // !_SOFTHSM_V2_ODD_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/AESTests.cpp b/SoftHSMv2/src/lib/crypto/test/AESTests.cpp
new file mode 100644
index 0000000..008560f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/AESTests.cpp
@@ -0,0 +1,1182 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AESTests.cpp
+
+ Contains test cases to test the AES implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "AESTests.h"
+#include "CryptoFactory.h"
+#include "AESKey.h"
+#include <stdio.h>
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AESTests);
+
+void AESTests::setUp()
+{
+ aes = NULL;
+
+ aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
+
+ // Check the return value
+ CPPUNIT_ASSERT(aes != NULL);
+}
+
+void AESTests::tearDown()
+{
+ if (aes != NULL)
+ {
+ CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
+ }
+
+ fflush(stdout);
+}
+
+void AESTests::testBlockSize()
+{
+ CPPUNIT_ASSERT(aes->getBlockSize() == 16);
+}
+
+void AESTests::testCBC()
+{
+ char testKeys128[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "89436760984679018453504364534464",
+ "49587346983643545706904580436731"
+ };
+
+ char testKeys192[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101213141516171819",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "096874395874290867409857496743857632098479834634",
+ "439867439058743095864395348375043296845094854983"
+ };
+
+ char testKeys256[][65] =
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20",
+ "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
+ "4394398576098257436095746985679043867498572406874967416846341641",
+ "4369006859867098670492857409386741095643756930847023587048579014"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testResult[5][4][3][256] = {
+ {
+ {
+ "6CAEC72F5E101C66550215ACAB6B874C62E7BD074C0A09A8EE4562EFCB4E560A3E90FA0F50391087824FC27F57618E5C",
+ "E20E3123AC64FCA5536E0A2DC48DBEBCECB3F260EFF4A0EB99D72F57EF38DED336EB9DD0B968D24C91E63974E7445A21",
+ "C7910B1634DB493998608875A4652B20C64202ED507D9DBA06F62EB20A63C32FB6C9669D42A0AC29D773E6D40A63A2AC"
+ },
+ {
+ "8F48A65BF638FEDB7E6F59BAC8C110FEBA933F106D564119B88569E758B7FB83",
+ "125E1D93DC2C43A6FAFC508DB6F9A4A9F390D102C2300F0A3617CE95027BFAA3",
+ "FACB8DEF1B476400DE9796D5058E9086ECF04C927F5C160161C7A34D8288EB3C"
+ },
+ {
+ "C810E96482F109C9A05D2B1BEBAC7966BB7784F58A5478C1A07EC0DB39F6D87B",
+ "2385391BB8F2DD97280B1FAEFACB6B5C4FE12A2274D6B967509CF18500A640D6",
+ "47549520EADA1A5D931EACCC922F88BA2E386089BF97C790FD2CD38553334AE4"
+ },
+ {
+ "A7D9EAE80224624188CAA7012140E946",
+ "6ECD5C71ECA4AB9C3B71E91721CA2043",
+ "2F77AA438E9259F268985668B00650E5"
+ }
+ },
+ {
+ {
+ "FCB2FB6BF8ED8910F023A934EB9DA550E4D5B469D75B9390F4A207E54F29412450E52E980862DC80B89F6D1D10B68AA5",
+ "7EF0F65513CFE3E0D21305E2ECCBB3554B0DE119720C5A86337E57F74795BC23ED9CB82A951DE3D00D7A0DC8997319DD",
+ "5B83BFDB6EF3AEA5191F2EE3366EDE10480E9459C0DE2994DD9C6408A377DFFF8121A38CFD1AA864559B9A435A3BDD6D"
+ },
+ {
+ "81D667193D42BF19C456F4A1F7070C047D94C7EE8136FA315F938162FDDA20C1",
+ "2EFBA2B689C0F775097F98B569A1F20004F1A75F0C53473969DBE586ABCAE04D",
+ "447326913AA4565951D987F59B48870DD9285EEFCF64B429C2220E4F3E0D9DE2"
+ },
+ {
+ "891DF30BAEA2D24408A9C788D59DBAC7A6F34311813216311E18E9ED7122DB1A",
+ "F1629B62ECDF3CDAA3DA0EBB31EE37691AF4EB2B6F9CF04A9861935B2C167D02",
+ "C7BD348D5E6696CB8BA813B96EA5C42C5C3C3629D18FC9DAF1B50A0AE4843C5B"
+ },
+ {
+ "91C44D109D46C8E8656793680D43BE94",
+ "E68D8E49A19F155B7ED7253120B0D117",
+ "FAED8666F695C85283ECF51C96DB41CE"
+ }
+ },
+ {
+ {
+ "0CCFB49FE2B7E93A556E56B2C616885FBB0515F55A4210FE2F492A4775F078655CB21691CA6A54819C2D885954809D00",
+ "2FC6C785D683FC35304DD161A21FA1B256F9FBB2817F1F3BEBCE7C1E292EC6999641AA6953C0FAB6DFC2942CABD32DFB",
+ "31FAF4E3DA19D2372666AC635FFE361E33AD7865AEF616273D8F3B471F77A0998C6A41497168A65F621D912C54A4AF28"
+ },
+ {
+ "0B3842152A6365ED14AD952ABBBAF0EED2E8F36250DD25DDA301490FDE05219B",
+ "696BF21A887A04E194DCC18719E1BD623D8BD25A0CEF5EC2E21312ACE6C81F40",
+ "A2C8E61471EC80FE39AC0D8F720FEA8F2D23D04596A751C755E51CD357BCA5E0"
+ },
+ {
+ "5E0EA3AFBE191A16854C7960F087958F577EA4F80160F521A12D2211FAC25E16",
+ "F5475B4FD48F969123C9F7FB08C7E902CCA282F167BBAFF1A7C7EDDB7BCBAC76",
+ "380CB860EC6DEF4F9329F4BE826DE1FE61A71629DD978F00BEFB349ACBD0BAD8"
+ },
+ {
+ "BA1452E755E6A43E43B10DD2C1530093",
+ "07CA52926D4E8F2F6055E6E0251CB9E5",
+ "AB99E5FEE195B4433667AD3074A9322E"
+ }
+ },
+ {
+ {
+ "D2D46E577723B30E6B5FC96DC18B2C55E0EACCB07CE07C7F30FD113A987E2A2059AB7DF8985C1AE525EFAD9CE111893C",
+ "CC5B220688AC0231DBC03C8886C0D0109840B9E58FBB1A6B6C261ED9E7979E951818033A25778FF328786D1777790078",
+ "4B4A0B3D6D4E770BECC574BF66CD401942DC4D0DCD0EC65F99B2925B688BB217FCB5C946BE986C440C93279F4670CD43"
+ },
+ {
+ "29C76D62D3C4F7FECCBFD7A73B06E2ECA7AA3B2D4BE79EC945B0B88C813264D8",
+ "B898DCE11F3D6BB2182208E0BBBA7F404FE415D4D6D0772960E7CE3549B9899C",
+ "11E9552009836B51F241E972D680A9F397260163D9D5369BFC1B136FB4206966"
+ },
+ {
+ "539FC6EDAE21EDDC1CC4650367F527467916A6990E540146238AA9CD6B3B4ADE",
+ "2D9DE2BC47DAFCF7867134110C541EBCD72D67B1B23DEF6805DBFF4A4D90EF91",
+ "BF484690835FF61C4A7873A996EEB91F553978A40360E192273D3923E04DFE1E"
+ },
+ {
+ "4910EFFFBF571C98D51802F04A42213E",
+ "EDD1880FC4D41293BC74B98AF3D8A010",
+ "F8BCC258A6CD7FAA4EDF16A3CF5573C4"
+ }
+ },
+ {
+ {
+ "C2061BD0B4274B5CB4E408B492991F4195FDBFCDED1BC57442151B182BA6E8075AAF858F357C262E0034B9B5F839D823",
+ "6EEFEBCC9F8C607D21A158E23980EFA6EC234DC6EA668A446F467F4AE87521F18DC1800D87A5EBC63C444F810557B61D",
+ "00C952BA54614A1F11B0D59F3F469A859F62CCE0D35073B91B461302A7F37BD0B23401482DFCEE66ABD12C05615C9862"
+ },
+ {
+ "B36553D93EEF04AE247DBCBDDB8C039FFAC8AC1B0EF14C2E4BA653F089924451",
+ "90670C9DE58F95431591FA2BE8EA1B4B3F5BDBFC0B5199F94A41E4FC7B6B1645",
+ "A065415413D3A08E4B42A3F2681B8D122167A1E3F92D38C305761D9BF80131F1"
+ },
+ {
+ "12A758F161543F2842138B8C2453C3A05A90BE9F92CB3DD10C40AB9D1D746B49",
+ "DF1F4DDFFE1032C812FC6F35AB2B3A7B0E8D26DA49DEC8F5E08D108DB1283BEA",
+ "FDCB66159E1B5CF1BE9F7271EF2C35D5E9F7485E32D16C6AC865E64619DB8724"
+ },
+ {
+ "1FC224DCB64848B5E8F9FB91C542991F",
+ "1F8C5F65F9205098B47E26894B9154D9",
+ "19763CAC206EDFDEBEDAD9C274DEE1C1"
+ }
+ }
+ };
+
+ char testIV[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "69836472094875029486750948672066",
+ "48670943876904867104398574908554"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+ ByteString keyData128(testKeys128[i]);
+ ByteString keyData192(testKeys192[i]);
+ ByteString keyData256(testKeys256[i]);
+
+ AESKey aesKey128(128);
+ CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128));
+ AESKey aesKey192(192);
+ CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192));
+ AESKey aesKey256(256);
+ CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 128-bit key
+ cipherText = ByteString(testResult[i][j][0]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 192-bit key
+ cipherText = ByteString(testResult[i][j][1]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 256-bit key
+ cipherText = ByteString(testResult[i][j][2]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void AESTests::testECB()
+{
+ char testKeys128[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "89436760984679018453504364534464",
+ "49587346983643545706904580436731"
+ };
+
+ char testKeys192[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101213141516171819",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "096874395874290867409857496743857632098479834634",
+ "439867439058743095864395348375043296845094854983"
+ };
+
+ char testKeys256[][65] =
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20",
+ "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
+ "4394398576098257436095746985679043867498572406874967416846341641",
+ "4369006859867098670492857409386741095643756930847023587048579014"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testResult[5][4][3][256] = {
+ {
+ {
+ "6CAEC72F5E101C66550215ACAB6B874CD26479922B98D9839D7DA729B557ABA00143DB63EE66B0CDFF9F69917680151E",
+ "E20E3123AC64FCA5536E0A2DC48DBEBC0E4E53BDA45FFC97C677951A891A6B7502BB292527E726FD51EB29894D6F0AAD",
+ "C7910B1634DB493998608875A4652B205750B3B761DA7718E120C23A575F7D821F788FE6D86C317549697FBF0C07FA43"
+ },
+ {
+ "8F48A65BF638FEDB7E6F59BAC8C110FE0E5E6370CBEFACFA0D7A5744030A481B",
+ "125E1D93DC2C43A6FAFC508DB6F9A4A933738D14C219340D5F4D7203DEDCA7E1",
+ "FACB8DEF1B476400DE9796D5058E90863A9A8C8BB2420B9A85BA3E8F87BB48F2"
+ },
+ {
+ "C810E96482F109C9A05D2B1BEBAC79660143DB63EE66B0CDFF9F69917680151E",
+ "2385391BB8F2DD97280B1FAEFACB6B5C02BB292527E726FD51EB29894D6F0AAD",
+ "47549520EADA1A5D931EACCC922F88BA1F788FE6D86C317549697FBF0C07FA43"
+ },
+ {
+ "A7D9EAE80224624188CAA7012140E946",
+ "6ECD5C71ECA4AB9C3B71E91721CA2043",
+ "2F77AA438E9259F268985668B00650E5"
+ }
+ },
+ {
+ {
+ "8947CE273536C8A4D1E878F38371B9A8D2B3B45496779386CBA32CA70001D6AA6CC00A66D2AD83FFD76E9A2BCAD89A01",
+ "B151340CFECADA3AE176637D0A78686E2063E1A602C85D03AE648BDF4FA57C36F7F1878D088644BD5FB43D3C0FE1C30C",
+ "C19AE024C8F6B8E3383F675DF463512E273AAD7D0B88F22D5225EF09D2E37118D45D7C5AA26BCA9D6B1D5DDBF68F9EF6"
+ },
+ {
+ "16C30BBAE7CDB2EE1E02275B79A064F6EE69FB37C8E039400435782F550CF86A",
+ "F6C869D28D2D167C50BEE8F605D33021CB9173567B8B4AB3EEC68F0298324B78",
+ "07DB563F7E31F1E670A02F97E8D120C7EE3FCEBBF2FDC2D37FC17D93ED1A778B"
+ },
+ {
+ "52902B599686234833C4D420A9BF17FF6CC00A66D2AD83FFD76E9A2BCAD89A01",
+ "B17FA9EA89D5578A844B3D82891330B1F7F1878D088644BD5FB43D3C0FE1C30C",
+ "74BC55BE85291E0D1FA4A4444051CF65D45D7C5AA26BCA9D6B1D5DDBF68F9EF6"
+ },
+ {
+ "3F00CAAC6FA432A7C1826CA4DA7C55D6",
+ "9C2DBF449FF2C4AC1CFD7C43D200D33A",
+ "E2183AB600A986806D86ADA4EE38E562"
+ }
+ },
+ {
+ {
+ "23741EF993CBA04E5C67B42A16CA4D100BA6DF745E6D90818500DEC1CFC9811DBD3ACBFC853ED5DE825266C3B1883EC4",
+ "F14D0EB7DFDB9B8960B0E47D7F4828E8756C38BA83655AAC466986ECB229A66FA390265A4BF5F50A8DFFAD253701E418",
+ "0AAE579A796C94AF4FFB9D7C71381CB5E68E15465F30D7085A72D0CCEC7030BBC9CB7B3859E1A550BCBF11B624022C56"
+ },
+ {
+ "AFCD6801459845C88548CC337BDD4D8B87E81D9D6AC945E14E3C4E0AC976A4B9",
+ "117129A4775FC84E703F2F2C54B1B55DC4A79241F6CB0A37A8D551D71983D944",
+ "1128250DA7C9A1BBE6A61AC01F28D4D9E3027C3625BD5514AE5DFE4B9132DAFA"
+ },
+ {
+ "B275BDAF14AE286643C533258343F822BD3ACBFC853ED5DE825266C3B1883EC4",
+ "93ACFCCFE2C4736B6492A673A59DACE2A390265A4BF5F50A8DFFAD253701E418",
+ "2C2165E6491662A855FD7A20CDFF23BDC9CB7B3859E1A550BCBF11B624022C56"
+ },
+ {
+ "30BBF52D760BAEA653FD03E5E84E583A",
+ "F5F55DF3FC4D9CF2A2829BACA774A51A",
+ "7EE196D148C11FA4998A90C6C7932395"
+ }
+ },
+ {
+ {
+ "44C2B3344B002BB7A6994E1C74CC7BA70CE55BF44FD96506B553F0EFD3FE02B28329D59D480B0C1714A0DC60EB9FA8CE",
+ "568C7627FD2519BE6031F052DE8F680860F7680460E92A524EA912174BE17B1337D593DEF15FB5BA64F03D1AAE276775",
+ "99E36C0097BCFE41945C064EFA476FF4AA6048F909BEDE32A649F1035A2FB83CD601D09C3FDB36BC61B8CDE5BDD73804"
+ },
+ {
+ "D748E8E93D29775BD8831E3BC1E1ABF75F484C7CC693521A66A5AB1637822E40",
+ "010103778E123E5140F8D0356DA831E1587DB7E416AE9FAD14C6E2F78DC83148",
+ "A8B8926E8FB762A1AB8CD9FA08507D77872C8EAAAFF3527572F49497B8B366C9"
+ },
+ {
+ "CFF3212C7E94C2DD65EC1CDC998D6C4B8329D59D480B0C1714A0DC60EB9FA8CE",
+ "324D16FEEC9DCA75A80F4B80175F8A7537D593DEF15FB5BA64F03D1AAE276775",
+ "850567F4F0200CFBF88F1A6D35CAF6D9D601D09C3FDB36BC61B8CDE5BDD73804"
+ },
+ {
+ "417F142D7609AE701B3D263FFECE4502",
+ "E0DC994D8DC01C4EB2ECD19AD120C3D1",
+ "FB26CC4E48B40EAB755FF65164EFB406"
+ }
+ },
+ {
+ {
+ "048AEE75741BC60D01B512A53FEE97238F294743E7A351FAF589DD9E040BB8AF0F59D8F60E9C700F10025B5E69828819",
+ "67FB10E52640B1E060F3D7868524721AC375DC76628B0D79C5F40ADC653FC001B50C33356548289D3E70EB7FBC0E2B56",
+ "31953FF249D7519D3C39FB21D70A41033286A320193CC938C5ACBBCA2B25340829799212E3CABACE0BFD4424427705AB"
+ },
+ {
+ "8D8D50FA4619F0E1B821DCA4ACBDFD46AE92D76A0B95A0331D61C4A7032D9705",
+ "10685E8F632AC41D92E3A0403BB20C79868BD6F94691226EC54D7220C45E7233",
+ "C5FF99FD1BC2BFDBEA62894B279DE6CBF51CCD00362A557DB9D9102DAF623A50"
+ },
+ {
+ "0330B8FF58E4E6E956B4F81F7A4770200F59D8F60E9C700F10025B5E69828819",
+ "C79BABE5B34B305B05E38013DC5568F7B50C33356548289D3E70EB7FBC0E2B56",
+ "98BEE460FF803288C898A900DD08CE2529799212E3CABACE0BFD4424427705AB"
+ },
+ {
+ "9A4FD3A26DD0D3A12F224E5E7A06EB76",
+ "B86FE6F088C3A6497F21BCB29DB703D1",
+ "313CC604B301DACA48CDB6F405AA7938"
+ }
+ }
+ };
+
+ char testIV[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "69836472094875029486750948672066",
+ "48670943876904867104398574908554"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+ ByteString keyData128(testKeys128[i]);
+ ByteString keyData192(testKeys192[i]);
+ ByteString keyData256(testKeys256[i]);
+
+ AESKey aesKey128(128);
+ CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128));
+ AESKey aesKey192(192);
+ CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192));
+ AESKey aesKey256(256);
+ CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 128-bit key
+
+ // Get the reference for the encrypted data
+ cipherText = ByteString(testResult[i][j][0]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 192-bit key
+ cipherText = ByteString(testResult[i][j][1]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 256-bit key
+ cipherText = ByteString(testResult[i][j][2]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void AESTests::testCTR()
+{
+ // Test vectors from RFC3686
+
+ char testKeys128[][33] =
+ {
+ "AE6852F8121067CC4BF7A5765577F39E",
+ "7E24067817FAE0D743D6CE1F32539163",
+ "7691BE035E5020A8AC6E618529F9A0DC"
+ };
+
+ char testKeys192[][49] =
+ {
+ "16AF5B145FC9F579C175F93E3BFB0EED863D06CCFDB78515",
+ "7C5CB2401B3DC33C19E7340819E0F69C678C3DB8E6F6A91A",
+ "02BF391EE8ECB159B959617B0965279BF59B60A786D3E0FE"
+ };
+
+ char testKeys256[][65] =
+ {
+ "776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104",
+ "F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884",
+ "FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D"
+ };
+
+ char testData[][256] =
+ {
+ "53696E676C6520626C6F636B206D7367",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223"
+ };
+
+ char testResult[3][3][256] =
+ {
+ {
+ "E4095D4FB7A7B3792D6175A3261311B8",
+ "4B55384FE259C9C84E7935A003CBE928",
+ "145AD01DBF824EC7560863DC71E3E0C0"
+ },
+ {
+ "5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28",
+ "453243FC609B23327EDFAAFA7131CD9F8490701C5AD4A79CFC1FE0FF42F4FB00",
+ "F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C"
+ },
+ {
+ "C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F",
+ "96893FC55E5C722F540B7DD1DDF7E758D288BC95C69165884536C811662F2188ABEE0935",
+ "EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8"
+ }
+ };
+
+ char testCB[3][3][33] =
+ {
+ {
+ "00000030000000000000000000000001",
+ "0000004836733C147D6D93CB00000001",
+ "00000060DB5672C97AA8F0B200000001"
+ },
+ {
+ "006CB6DBC0543B59DA48D90B00000001",
+ "0096B03B020C6EADC2CB500D00000001",
+ "00FAAC24C1585EF15A43D87500000001"
+ },
+ {
+ "00E0017B27777F3F4A1786F000000001",
+ "0007BDFD5CBD60278DCC091200000001",
+ "001CC5B751A51D70A1C1114800000001"
+ }
+ };
+
+ for (int i = 0; i < 3; i++)
+ {
+ ByteString keyData128(testKeys128[i]);
+ ByteString keyData192(testKeys192[i]);
+ ByteString keyData256(testKeys256[i]);
+
+ AESKey aesKey128(128);
+ CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128));
+ AESKey aesKey192(192);
+ CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192));
+ AESKey aesKey256(256);
+ CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256));
+
+
+ ByteString plainText(testData[i]), shsmPlainText;
+ ByteString CB;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+ // Test 128-bit key
+ CB = ByteString(testCB[i][0]);
+ cipherText = ByteString(testResult[i][0]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::CTR, CB));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::CTR, CB));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 192-bit key
+ CB = ByteString(testCB[i][1]);
+ cipherText = ByteString(testResult[i][1]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::CTR, CB));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::CTR, CB));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 256-bit key
+ CB = ByteString(testCB[i][2]);
+ cipherText = ByteString(testResult[i][2]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::CTR, CB));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::CTR, CB));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+}
+
+#ifdef WITH_AES_GCM
+void AESTests::testGCM()
+{
+ // Test vectors from NIST via Botan
+
+ char test128[8][6][256] =
+ {
+ {
+ "00000000000000000000000000000000",
+ "000000000000000000000000",
+ "",
+ "",
+ "10",
+ "58E2FCCEFA7E3061367F1D57A4E7455A"
+ },
+ {
+ "00000000000000000000000000000000",
+ "000000000000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "10",
+ "0388DACE60B6A392F328C2B971B2FE78AB6E47D42CEC13BDF53A67B21257BDDF"
+ },
+ {
+ "FEFFE9928665731C6D6A8F9467308308",
+ "CAFEBABEFACEDBADDECAF888",
+ "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B391AAFD255",
+ "",
+ "10",
+ "42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E091473F59854D5C2AF327CD64A62CF35ABD2BA6FAB4"
+ },
+ {
+ "FEFFE9928665731C6D6A8F9467308308",
+ "CAFEBABEFACEDBADDECAF888",
+ "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39",
+ "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2",
+ "10",
+ "42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E0915BC94FBC3221A5DB94FAE95AE7121A47"
+ },
+ {
+ "FEFFE9928665731C6D6A8F9467308308",
+ "CAFEBABEFACEDBAD",
+ "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39",
+ "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2",
+ "10",
+ "61353B4C2806934A777FF51FA22A4755699B2A714FCDC6F83766E5F97B6C742373806900E49F24B22B097544D4896B424989B5E1EBAC0F07C23F45983612D2E79E3B0785561BE14AACA2FCCB"
+ },
+ {
+ "FEFFE9928665731C6D6A8F9467308308",
+ "9313225DF88406E555909C5AFF5269AA6A7A9538534F7DA1E4C303D2A318A728C3C0C95156809539FCF0E2429A6B525416AEDBF5A0DE6A57A637B39B",
+ "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39",
+ "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2",
+ "10",
+ "8CE24998625615B603A033ACA13FB894BE9112A5C3A211A8BA262A3CCA7E2CA701E4A9A4FBA43C90CCDCB281D48C7C6FD62875D2ACA417034C34AEE5619CC5AEFFFE0BFA462AF43C1699D050"
+ },
+ {
+ "FEFFE9928665731C6D6A8F9467308308",
+ "CAFEBABEFACEDBAD",
+ "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39",
+ "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2",
+ "C",
+ "61353B4C2806934A777FF51FA22A4755699B2A714FCDC6F83766E5F97B6C742373806900E49F24B22B097544D4896B424989B5E1EBAC0F07C23F45983612D2E79E3B0785561BE14A"
+ },
+ {
+ "FEFFE9928665731C6D6A8F9467308308",
+ "9313225DF88406E555909C5AFF5269AA6A7A9538534F7DA1E4C303D2A318A728C3C0C95156809539FCF0E2429A6B525416AEDBF5A0DE6A57A637B39B",
+ "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39",
+ "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2",
+ "C",
+ "8CE24998625615B603A033ACA13FB894BE9112A5C3A211A8BA262A3CCA7E2CA701E4A9A4FBA43C90CCDCB281D48C7C6FD62875D2ACA417034C34AEE5619CC5AEFFFE0BFA462AF43C"
+ }
+ };
+
+ char test192[8][6][256] =
+ {
+ {
+ "000000000000000000000000000000000000000000000000",
+ "000000000000000000000000",
+ "",
+ "",
+ "10",
+ "cd33b28ac773f74ba00ed1f312572435"
+ },
+ {
+ "000000000000000000000000000000000000000000000000",
+ "000000000000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "10",
+ "98e7247c07f0fe411c267e4384b0f6002ff58d80033927ab8ef4d4587514f0fb"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "cafebabefacedbaddecaf888",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+ "",
+ "10",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade2569924a7c8587336bfb118024db8674a14"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "cafebabefacedbaddecaf888",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "10",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda27102519498e80f1478f37ba55bd6d27618c"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "cafebabefacedbad",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "10",
+ "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f765dcc57fcf623a24094fcca40d3533f8"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "10",
+ "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373bdcf566ff291c25bbb8568fc3d376a6d9"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "cafebabefacedbaddecaf888",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "C",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda27102519498e80f1478f37ba55bd"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "cafebabefacedbad",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "C",
+ "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f765dcc57fcf623a24094fcca4"
+ }
+ };
+
+ char test256[8][6][256] =
+ {
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "000000000000000000000000",
+ "",
+ "",
+ "10",
+ "530f8afbc74536b9a963b4f1c4cb738b"
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "000000000000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "10",
+ "cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "cafebabefacedbaddecaf888",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+ "",
+ "10",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015adb094dac5d93471bdec1a502270e3cc6c"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "cafebabefacedbaddecaf888",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "10",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853bb2d551b"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "cafebabefacedbad",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "10",
+ "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913fe2ea8f2",
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "10",
+ "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3fa44a8266ee1c8eb0c8b5d4cf5ae9f19a"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "cafebabefacedbaddecaf888",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "C",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853"
+ },
+ {
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "cafebabefacedbad",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "C",
+ "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913"
+ }
+ };
+
+ for (int i = 0; i < 8; i++)
+ {
+ ByteString keyData128(test128[i][0]);
+ ByteString keyData192(test192[i][0]);
+ ByteString keyData256(test256[i][0]);
+
+ AESKey aesKey128(128);
+ CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128));
+ AESKey aesKey192(192);
+ CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192));
+ AESKey aesKey256(256);
+ CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256));
+
+ ByteString IV;
+ ByteString plainText;
+ ByteString AAD;
+ size_t tagBits;
+ ByteString cipherText;
+
+ ByteString shsmPlainText;
+ ByteString shsmCipherText;
+ ByteString OB;
+
+ // Test 128-bit key
+ IV = ByteString(test128[i][1]);
+ plainText = ByteString(test128[i][2]);
+ AAD = ByteString(test128[i][3]);
+ tagBits = ByteString(test128[i][4]).long_val();
+ cipherText = ByteString(test128[i][5]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::GCM, IV, true, 0, AAD, tagBits));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::GCM, IV, true, 0, AAD, tagBits));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ CPPUNIT_ASSERT(OB.size() == 0);
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 192-bit key
+ IV = ByteString(test192[i][1]);
+ plainText = ByteString(test192[i][2]);
+ AAD = ByteString(test192[i][3]);
+ tagBits = ByteString(test192[i][4]).long_val();
+ cipherText = ByteString(test192[i][5]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::GCM, IV, true, 0, AAD, tagBits));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::GCM, IV, true, 0, AAD, tagBits));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ CPPUNIT_ASSERT(OB.size() == 0);
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 256-bit key
+ IV = ByteString(test256[i][1]);
+ plainText = ByteString(test256[i][2]);
+ AAD = ByteString(test256[i][3]);
+ tagBits = ByteString(test256[i][4]).long_val();
+ cipherText = ByteString(test256[i][5]);
+
+ // Now, do the same thing using our AES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::GCM, IV, true, 0, AAD, tagBits));
+
+ CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(aes->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::GCM, IV, true, 0, AAD, tagBits));
+
+ CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB));
+ CPPUNIT_ASSERT(OB.size() == 0);
+
+ CPPUNIT_ASSERT(aes->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+}
+#endif
+
+void AESTests::testWrap(const char testKeK[][128], const char testKey[][128], const char testCt[][128], const int testCnt, SymWrap::Type mode)
+{
+ for (int i = 0; i < testCnt; i++)
+ {
+ ByteString kekData(testKeK[i]);
+ ByteString keyData(testKey[i]);
+
+ AESKey aesKeK(kekData.size() * 8);
+ CPPUNIT_ASSERT(aesKeK.setKeyBits(kekData));
+
+ ByteString wrapped;
+ ByteString expectedCt(testCt[i]);
+ CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, mode, keyData, wrapped));
+ CPPUNIT_ASSERT(wrapped.size() == expectedCt.size());
+ CPPUNIT_ASSERT(wrapped == expectedCt);
+
+ ByteString unwrapped;
+ CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, mode, wrapped, unwrapped));
+ CPPUNIT_ASSERT(unwrapped.size() == keyData.size());
+ CPPUNIT_ASSERT(unwrapped == keyData);
+/*
+ #ifdef HAVE_AES_KEY_WRAP_PAD
+ keyData.resize(20);
+ ByteString padwrapped;
+ CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, keyData, padwrapped));
+ CPPUNIT_ASSERT(padwrapped.size() == 32);
+
+ ByteString padunwrapped;
+ CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, padwrapped, padunwrapped));
+ CPPUNIT_ASSERT(padunwrapped == keyData);
+ #endif
+*/
+ }
+}
+
+// RFC 3394 tests
+void AESTests::testWrapWoPad()
+{
+ char testKeK[][128] = {
+ "000102030405060708090A0B0C0D0E0F", // section 4.1
+ "000102030405060708090A0B0C0D0E0F1011121314151617", // section 4.2
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.3
+ "000102030405060708090A0B0C0D0E0F1011121314151617", // section 4.4
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.5
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.6
+ };
+ char testKey[][128] = {
+ "00112233445566778899AABBCCDDEEFF",
+ "00112233445566778899AABBCCDDEEFF",
+ "00112233445566778899AABBCCDDEEFF",
+ "00112233445566778899AABBCCDDEEFF0001020304050607",
+ "00112233445566778899AABBCCDDEEFF0001020304050607",
+ "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F"
+ };
+ char testCt[][128] = {
+ "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5",
+ "96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D",
+ "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7",
+ "031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2",
+ "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1",
+ "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21"
+ };
+
+ testWrap(testKeK, testKey, testCt, sizeof(testKeK) / 128, SymWrap::AES_KEYWRAP);
+}
+
+// RFC 5649 tests
+void AESTests::testWrapPad()
+{
+ char testKeK[][128] = {
+ "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8", // section 6 example 1
+ "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8", // section 6 example 2
+ };
+ char testKey[][128] = {
+ "C37B7E6492584340BED12207808941155068F738",
+ "466F7250617369"
+ };
+ char testCt[][128] = {
+ "138BDEAA9B8FA7FC61F97742E72248EE5AE6AE5360D1AE6A5F54F373FA543B6A",
+ "AFBEB0F07DFBF5419200F2CCB50BB24F"
+ };
+
+ testWrap(testKeK, testKey, testCt, sizeof(testKeK) / 128, SymWrap::AES_KEYWRAP_PAD);
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/AESTests.h b/SoftHSMv2/src/lib/crypto/test/AESTests.h
new file mode 100644
index 0000000..3a50b11
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/AESTests.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AESTests.h
+
+ Contains test cases to test the AES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_AESTESTS_H
+#define _SOFTHSM_V2_AESTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "SymmetricAlgorithm.h"
+
+class AESTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(AESTests);
+ CPPUNIT_TEST(testBlockSize);
+ CPPUNIT_TEST(testCBC);
+ CPPUNIT_TEST(testECB);
+ CPPUNIT_TEST(testCTR);
+#ifdef WITH_AES_GCM
+ CPPUNIT_TEST(testGCM);
+#endif
+#ifdef HAVE_AES_KEY_WRAP
+ CPPUNIT_TEST(testWrapWoPad);
+#endif
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ CPPUNIT_TEST(testWrapPad);
+#endif
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testBlockSize();
+ void testCBC();
+ void testECB();
+ void testCTR();
+#ifdef WITH_AES_GCM
+ void testGCM();
+#endif
+ void testWrapWoPad();
+ void testWrapPad();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // AES instance
+ SymmetricAlgorithm* aes;
+ void testWrap(const char testKeK[][128], const char testKey[][128], const char testCt[][128], const int testCnt, SymWrap::Type mode);
+};
+
+#endif // !_SOFTHSM_V2_AESTESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/DESTests.cpp b/SoftHSMv2/src/lib/crypto/test/DESTests.cpp
new file mode 100644
index 0000000..bcb1c6b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/DESTests.cpp
@@ -0,0 +1,1164 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DESTests.cpp
+
+ Contains test cases to test the DES implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DESTests.h"
+#include "CryptoFactory.h"
+#include "DESKey.h"
+#include <stdio.h>
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DESTests);
+
+void DESTests::setUp()
+{
+ des = NULL;
+
+ des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES);
+
+ // Check the return value
+ CPPUNIT_ASSERT(des != NULL);
+}
+
+void DESTests::tearDown()
+{
+ if (des != NULL)
+ {
+ CryptoFactory::i()->recycleSymmetricAlgorithm(des);
+ }
+
+ fflush(stdout);
+}
+
+void DESTests::testBlockSize()
+{
+ CPPUNIT_ASSERT(des->getBlockSize() == 8);
+}
+
+void DESTests::testCBC()
+{
+#ifndef WITH_FIPS
+ char testKeys56[][17] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4698436794236871",
+ "0940278947239572"
+ };
+
+ char testKeys112[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "64398647034486943598534703463870",
+ "87406984068406984607412103517413"
+ };
+#endif
+
+ char testKeys168[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "643906874509874309687459084769847562436043696747",
+ "430135460496813044639085714376487549490586439575"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testResult[5][4][3][256] = {
+ {
+ {
+ "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7",
+ "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7",
+ "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7"
+ },
+ {
+ "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64",
+ "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64",
+ "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64"
+ },
+ {
+ "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588",
+ "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588",
+ "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588"
+ },
+ {
+ "B81DA29972385E55CB453A17B6D88D22",
+ "B81DA29972385E55CB453A17B6D88D22",
+ "B81DA29972385E55CB453A17B6D88D22"
+ }
+ },
+ {
+ {
+ "EE16FFE3CC4D4589766FA0957FB728A75D44A00D9BEBE2D43C4D4F3A5AFDB49730CFD4DF46D3AEF6",
+ "A070EE9DED89EE198E0E9B3CEB4879BB0244AB7FCD3450ED044BB5EE0AC8F7797383FDB8AAEF77B8",
+ "E7C594590C9CA00B376B702CE3B92C3F699B3EEEB2CEA08FA551350C837BF031FCAF4E1E97450327"
+ },
+ {
+ "D4142C47C700069F3E71EA6B1EF301B9B97261543ED75B32242C05A253B077B8",
+ "102BBE7D93CD0EF66280D3FA1F2A3976FB9C4D1B155D19E4985ADB86015DDE8C",
+ "600C3A75AC6EB4C4609BA6B7ED273ED56E59CD49FC911C33DD8DFCA384BAA462"
+ },
+ {
+ "47452120CD84CC32FC72F3B8600E5C43EEE192A29BC6BCB7",
+ "ADCF4292A32E51A7843CC8590E6934083A2CC847082FF2B4",
+ "D0FA596AC00BDA870999FD3FA2494C3C8B40B261EB3066F6"
+ },
+ {
+ "6BD20CDBE6E6ECAD6ED829FB43E92751",
+ "AE4379E371E295F63423F861B59111F0",
+ "2757FC58EDEEB8499EA9B49AB2729BAD"
+ }
+ },
+ {
+ {
+ "298621D5237F6230067DE7871DDBA6991E85CA14AD661D21357240923604D23A6A4119277B75B331",
+ "2C9F4FC0ACE7C8A4847472A0D5DDD42F36D3B2C46144B5A0ECDBB59806472E6257952DFD4DB9EBE5",
+ "679A832C630207E76BC1FF8371C61CA2518E37FE97EDED1B171E3E11807250145736949368AC822B"
+ },
+ {
+ "80FFD37B545675BB8C7CD317A73AB48CC0A39D3D9C11474EC3FD1220A066C034",
+ "F9228036718792EE86A85626AB1BC05E17F9CE21FF5D1723D0442CE852F004C3",
+ "D5F5F1EA7D8C2038FEDCBEDF157A5D2469A941FEC696D74DB8359CA5AECDD4CE"
+ },
+ {
+ "1ABB1CC10F589D993030A978B1B7F44AD52FFFEBF23638CA",
+ "D2423F54FA4978C95E4B13EF4DD6AA82DFD772F0FDAF5AD1",
+ "8128EC49D71F5711E5304E7C4423C63AD0EFC45453B66583"
+ },
+ {
+ "B9EE976AB97396047510C1DEA5C86A4B",
+ "46BA1930042146B31BD8FAF3AE6F3414",
+ "46EF3BCCA73E33C03D81BFE0DFFA7ABD"
+ }
+ },
+ {
+ {
+ "30D1B2556D516F20C2FD117FE0355845FBB0B11ABE5922A7EAA19C3A48E30207218321B3F0F30A6D",
+ "CBFA560297901DD691CDFDF98675BD7FF3A64FDCC0EF02F29C81105D3ECAC4E2803E2279F4476B35",
+ "4A30EC10433BE3695DC2B064E6240419C7BF81F1EE7640D5E2FFFA106666A2CEBF18DB954A992B5E"
+ },
+ {
+ "61FFB2E5A73170603E48F9823E6DF7105C9A909CC2F5CEDBEA7E60C076355B37",
+ "8408BD722B12031D17A1645AA59B05E2A50F7002B19877D6EB1C9BB7107C523F",
+ "97EF5791017B10CF07FB8144C19633522CBBE55DC63EF608F8734EE6484C0B0E"
+ },
+ {
+ "7205DC463B3D5EC858C8E7A13844A1A8FF21C0D615CA56AF",
+ "D5D08C1DC728A47CD55A2ACBB811294962022E745F4BCDF4",
+ "7761189D73039A3F06BDDF00B308D7A43BE7BEA1CE9D042E"
+ },
+ {
+ "1702428661BA4CFE686CFDEDFFAA6A27",
+ "9218A89B0A7AEC7E6E2AF1CA493B2829",
+ "6EEB9F7DDF66CED3DB74F7E8DE0CB2CD"
+ }
+ },
+ {
+ {
+ "4FD3A4C759827F6E188E542B83A858026C17FD1DEF21477A964D122B62EE55FA9DB3CCF05A768C83",
+ "F2C8B52652970805EE60ECECC8369C98443463F1C3A5A6357DFDFEE6B7F1EF0CF05523B5469E4555",
+ "21FCBDC92C07F112D19742F5100F2A995E27CB282D73DF5CFEC802C629A279BD4E498C98D170003E"
+ },
+ {
+ "3FD4C32A44DC0A9605A5A793C57E94826E80FC9E8E9620BBC2E02FE41A62A2D3",
+ "4FC88F1E88C3B5A76CF6BE5FA8205BA6F7FA201F7C40E8F0F9CA156E140A4EC5",
+ "CCE31260C967F4B9BB3D2D31F82320715E434C1313D911C58CE7E42AA78DA831"
+ },
+ {
+ "714766BE5CB60DA99DC0BD4E7E655ADE7F26E45F372EF1BF",
+ "00064542E2B4821B4E9173DA6FD1ABAE45C5E5CF26DB506D",
+ "4D88D531C20E63A39372F275329BDBEBE15E7D2C32F2A98F"
+ },
+ {
+ "4933917C9B56124914D2B76DE221BA13",
+ "7F2D1CA9D942630FE1E954E4176E84A5",
+ "9A46902F3997F0EB121981DAEC6D89C4"
+ }
+ }
+ };
+
+ char testIV[][33] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4693867334098764",
+ "6209876098547207"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+#ifndef WITH_FIPS
+ ByteString keyData56(testKeys56[i]);
+ CPPUNIT_ASSERT(keyData56.size() == 8);
+ ByteString keyData112(testKeys112[i]);
+ CPPUNIT_ASSERT(keyData112.size() == 16);
+#endif
+ ByteString keyData168(testKeys168[i]);
+ CPPUNIT_ASSERT(keyData168.size() == 24);
+
+#ifndef WITH_FIPS
+ DESKey desKey56(56);
+ CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56));
+ DESKey desKey112(112);
+ CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112));
+#endif
+ DESKey desKey168(168);
+ CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+#ifndef WITH_FIPS
+ // Test 56-bit key
+ cipherText = ByteString(testResult[i][j][0]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 112-bit key
+ cipherText = ByteString(testResult[i][j][1]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+#endif
+
+ // Test 168-bit key
+ cipherText = ByteString(testResult[i][j][2]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::CBC, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void DESTests::testECB()
+{
+#ifndef WITH_FIPS
+ char testKeys56[][17] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4698436794236871",
+ "0940278947239572"
+ };
+
+ char testKeys112[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "64398647034486943598534703463870",
+ "87406984068406984607412103517413"
+ };
+#endif
+
+ char testKeys168[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "643906874509874309687459084769847562436043696747",
+ "430135460496813044639085714376487549490586439575"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testResult[5][4][3][256] = {
+ {
+ {
+ "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0",
+ "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0",
+ "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0"
+ },
+ {
+ "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0",
+ "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0",
+ "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0"
+ },
+ {
+ "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0",
+ "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0",
+ "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0"
+ },
+ {
+ "B81DA29972385E55EA1F3677CDC02D27",
+ "B81DA29972385E55EA1F3677CDC02D27",
+ "B81DA29972385E55EA1F3677CDC02D27"
+ }
+ },
+ {
+ {
+ "278B2CA6259C30E180CCB62E69F0841F235507E2FB3404FC2BC223E37E32B3A78207EA5D3E19A5FD",
+ "417579E3ABEF6F0D620B4FF88E2220457466420803140BFEFBA062A2A41D7C15061019377C6BFD8A",
+ "A676D0404F0F105B2073B9DD19C8C434428098BFC5AF1292FE12477340395F118F45B5BE23F16C4E"
+ },
+ {
+ "7D004390E5638E54077E2551B01BD52BFA1B98403ECE1AEF8207EA5D3E19A5FD",
+ "391B84593FEA836450318A6E943F1C3A4A6BD74E5001EB7A061019377C6BFD8A",
+ "DEAF58111ECCCB449F0C2564B52E360E4AACC8672ABBDF1A8F45B5BE23F16C4E"
+ },
+ {
+ "A6947F9EF4159BAE636A70B904059BC38207EA5D3E19A5FD",
+ "14ADFE212E27BF7F409395B45577F2C8061019377C6BFD8A",
+ "FF87BF761FC159F4442B3B4593233BC48F45B5BE23F16C4E"
+ },
+ {
+ "3A1777DAAAC85389EE0B499A90AE1739",
+ "376E61DF2EAFE5B523964A03885AD085",
+ "E4D81EE64FE8FB187EB7B5E80E075C73"
+ }
+ },
+ {
+ {
+ "F105809DF621715F4D3492E1EEC4A7DE0775A0632ECC13429DF0DC695A60882FA47F93E855A1445B",
+ "77C85215179312315997B4D0E997DB413176C80A8ED9F5EB9B726200224CE97C20A8A19F543BCCBD",
+ "AF1477E32B5BB1CA46D26B6020B3B48DB0A90A97B1BA60F032ADA648296EC92DEE924AA617423FD1"
+ },
+ {
+ "0FB3C3D9D93E0025F87909CD351D0116C0F684A204015E2CA47F93E855A1445B",
+ "67A66DB3209C406D2FE31AF6C36D24C7B32D0F8F1EAFA90020A8A19F543BCCBD",
+ "F85B1F07D788C59CD3DE6D562A175725DF596847ADEA8764EE924AA617423FD1"
+ },
+ {
+ "243A34CD70CE3819B9510980B6EFF3EAA47F93E855A1445B",
+ "997E145467B88D9D4C923797F539AC1620A8A19F543BCCBD",
+ "836788D7AD1F879B405438775FFD6D76EE924AA617423FD1"
+ },
+ {
+ "70856D6B67EE353F27EBB96462DACE63",
+ "D02F2A92C175A58001D89C4AEC476384",
+ "4ED379A40187826CAA90D2D6A05D5A9B"
+ }
+ },
+ {
+ {
+ "C79F67ABCE6F741CF6D5B7B4870397779AEB89F48805DD1A28305E804A4A2B91114E1CF0C7FA91DA",
+ "42956EA3B9415E8FE75B667A7C6B1ADF64D08E53C38DE733A776A97C7A8FC27E32945078552FA3E2",
+ "3685365AD0F07609E13CCDE69CEDC8CCA0C37262A87B734286B9119643AC3BABE435BDA25919BE86"
+ },
+ {
+ "09B882774309CC2B117586F5FA8BF7E4A5DA2A65E137665B114E1CF0C7FA91DA",
+ "0E52A9ABE753758D3C4F6326A8F689282D1DAB8AF6FC8CFF32945078552FA3E2",
+ "8DB6B9D50B5B8CE7DA56546CFF36C16BA3159E0EB7BD649AE435BDA25919BE86"
+ },
+ {
+ "025F9704F6ACD844BCFC6EBA809CD871114E1CF0C7FA91DA",
+ "1692C6A1DF9192C6D4125991EA9A9CBE32945078552FA3E2",
+ "6B848E67225EDDCCD7E8EC89ACDAA0AFE435BDA25919BE86"
+ },
+ {
+ "9D01CD89916AEE48AFE528A376E07AE9",
+ "6FA6A689405048060D65E1B1240B76B7",
+ "7EADEB7073D2EA995C5ED613C978817F"
+ }
+ },
+ {
+ {
+ "A98D0E8E72C589D80D240F192CF65C30FF3A1AB9D8CE54B09AA249C72E395AC3B40F19A649C1B237",
+ "33AC43C7A936665859431D18C089EE45F1356C34F5DF462D81BBFA42380A7E4F6732A473091A3673",
+ "FD4F2F77CCE20147CD0932B2E2D8D5978523F6A03D59E31E1F678A5DA4C350132E94F199555C371E"
+ },
+ {
+ "39453F3BF3C0CAE54279D96F4592359A5AEE6DD04D5F6162B40F19A649C1B237",
+ "E2AFCEEFF2317C520D890D7F2CB91ACD99D5DCAEC9C409016732A473091A3673",
+ "CB19BF88B2DEDDE981E048379A47BDF77ED5F815034CB07A2E94F199555C371E"
+ },
+ {
+ "9D466BACFA69266F7CC26D2C8B8CD203B40F19A649C1B237",
+ "265FDBCCF5F2325B3C8770ABEEECA4166732A473091A3673",
+ "C61E9B86A8A663AE1566CFFCF2046D6B2E94F199555C371E"
+ },
+ {
+ "380091B24160152B63EF067F6C189385",
+ "548EB237B455CBA0100A5C52A6F28C2B",
+ "066C3B0C5E6AF1E9BDD3DDAE5040F809"
+ }
+ }
+ };
+
+ char testIV[][33] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4693867334098764",
+ "6209876098547207"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+#ifndef WITH_FIPS
+ ByteString keyData56(testKeys56[i]);
+ CPPUNIT_ASSERT(keyData56.size() == 8);
+ ByteString keyData112(testKeys112[i]);
+ CPPUNIT_ASSERT(keyData112.size() == 16);
+#endif
+ ByteString keyData168(testKeys168[i]);
+ CPPUNIT_ASSERT(keyData168.size() == 24);
+
+#ifndef WITH_FIPS
+ DESKey desKey56(56);
+ CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56));
+ DESKey desKey112(112);
+ CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112));
+#endif
+ DESKey desKey168(168);
+ CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+#ifndef WITH_FIPS
+ // Test 56-bit key
+ cipherText = ByteString(testResult[i][j][0]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 112-bit key
+ cipherText = ByteString(testResult[i][j][1]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+#endif
+
+ // Test 168-bit key
+ cipherText = ByteString(testResult[i][j][2]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::ECB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void DESTests::testOFB()
+{
+#ifndef WITH_FIPS
+ char testKeys56[][17] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4698436794236871",
+ "0940278947239572"
+ };
+
+ char testKeys112[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "64398647034486943598534703463870",
+ "87406984068406984607412103517413"
+ };
+#endif
+
+ char testKeys168[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "643906874509874309687459084769847562436043696747",
+ "430135460496813044639085714376487549490586439575"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testResult[5][4][3][256] = {
+ {
+ {
+ "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846",
+ "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846",
+ "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846"
+ },
+ {
+ "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F",
+ "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F",
+ "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F"
+ },
+ {
+ "E89FCA8099D6B1FF6795867965624526",
+ "E89FCA8099D6B1FF6795867965624526",
+ "E89FCA8099D6B1FF6795867965624526"
+ },
+ {
+ "CA253BAC45D205E236",
+ "CA253BAC45D205E236",
+ "CA253BAC45D205E236"
+ }
+ },
+ {
+ {
+ "3E9FB188FC11138D05109EA396CA48E1681DF27A857C3C4A9E92D3DC85A5F313",
+ "3440BEFCF35DC87716D8440F71BAF9ACD0441E10B9E5B525F0584499620086E2",
+ "DDB35281888DF064195C42D45E4E2571AD62113A228B5107D1AC849861C199C0"
+ },
+ {
+ "233FC5D8B6F005B02500727078E84ED16C1B0474D7277E45",
+ "29E0CAACB9BCDE4A36C8A8DC9F98FF9CD442E81EEBBEF72A",
+ "C01326D1C26CE659394CAE07B06C2341A964E73470D01308"
+ },
+ {
+ "139E51D5AD1EF0E10AC3809975FF4DFE",
+ "19415EA1A2522B1B190B5A35928FFCB3",
+ "F0B2B2DCD9821308168F5CEEBD7B206E"
+ },
+ {
+ "3124A0F9711A44FC5B",
+ "3BFBAF8D7E569F0648",
+ "D20843F00586A71547"
+ }
+ },
+ {
+ {
+ "E376288A10BD52CB7162ADA9A732D24B574B1E7CB4FF5C791FFEA2E481AD3049",
+ "FD82CFAE85B8581FFCF489F467D94B1B4FAAAEDDE4EC531ABD30D7EA235896AA",
+ "24D9411BA456571900244AEA3EA7159BAA96522B6F891606A8D9A559FE218A9B"
+ },
+ {
+ "FED65CDA5A5C44F65172417A4910D47B534DE872E6A41E76",
+ "E022BBFECF594E22DCE4652789FB4D2B4BAC58D3B6B71115",
+ "3979354BEEB741242034A639D08513ABAE90A4253DD25409"
+ },
+ {
+ "CE77C8D741B2B1A77EB1B3934407D754",
+ "D0832FF3D4B7BB73F32797CE84EC4E04",
+ "09D8A146F559B4750FF754D0DD921084"
+ },
+ {
+ "ECCD39FB9DB605BA2F",
+ "F239DEDF08B30F6EA2",
+ "2B62506A295D00685E"
+ }
+ },
+ {
+ {
+ "740A4786C73A7C6B52DAF270161895E13B4437C56B9837827C2FE237532F4C19",
+ "581B63C58404AEBECFDFD51D74A79836C11514685B47F3B02A2419AF0AA8C625",
+ "D5FCB196868673D136D480E0B6EFC33C589131D87A4AC004A6E0DE8ADC8DE611"
+ },
+ {
+ "69AA33D68DDB6A5672CA1EA3F83A93D13F42C1CB39C3758D",
+ "45BB1795CEE5B883EFCF39CE9A859E06C513E266091CB1BF",
+ "C85CC5C6CC6765EC16C46C3358CDC50C5C97C7D62811820B"
+ },
+ {
+ "590BA7DB96359F075D09EC4AF52D90FE",
+ "751A8398D50B4DD2C00CCB2797929D29",
+ "F8FD51CBD78990BD39079EDA55DAC623"
+ },
+ {
+ "7BB156F74A312B1A0C",
+ "57A072B4090FF9CF91",
+ "DA47A0E70B8D24A068"
+ }
+ },
+ {
+ {
+ "0855A84EAD2176C3F10B9DCFC8D1A379AF616FC5C5CD4E6D434353C52832F9F6",
+ "A8420E97462B0215AAC1DB0835D4064C6A8B123327FC396C9520BEA70B59B412",
+ "3461DEDF1B4893E16706900E1DDBE351E90C1300B9B01E8A518A01AD56E9AC8C"
+ },
+ {
+ "15F5DC1EE7C060FED11B711C26F3A549AB6799CB97960C62",
+ "B5E27AC70CCA14288AD137DBDBF6007C6E8DE43D75A77B63",
+ "29C1AA8F51A985DC47167CDDF3F9E561ED0AE50EEBEB5C85"
+ },
+ {
+ "25544813FC2E95AFFED883F52BE4A666",
+ "8543EECA1724E179A512C532D6E10353",
+ "19603E824A47708D68D58E34FEEEE64E"
+ },
+ {
+ "07EEB93F202A21B2AF",
+ "A7F91FE6CB205564F4",
+ "3BDACFAE9643C49039"
+ }
+ }
+ };
+
+ char testIV[][33] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4693867334098764",
+ "6209876098547207"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+#ifndef WITH_FIPS
+ ByteString keyData56(testKeys56[i]);
+ CPPUNIT_ASSERT(keyData56.size() == 8);
+ ByteString keyData112(testKeys112[i]);
+ CPPUNIT_ASSERT(keyData112.size() == 16);
+#endif
+ ByteString keyData168(testKeys168[i]);
+ CPPUNIT_ASSERT(keyData168.size() == 24);
+
+#ifndef WITH_FIPS
+ DESKey desKey56(56);
+ CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56));
+ DESKey desKey112(112);
+ CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112));
+#endif
+ DESKey desKey168(168);
+ CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+#ifndef WITH_FIPS
+ // Test 56-bit key
+ cipherText = ByteString(testResult[i][j][0]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::OFB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::OFB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 112-bit key
+ cipherText = ByteString(testResult[i][j][1]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::OFB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::OFB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+#endif
+
+ // Test 168-bit key
+ cipherText = ByteString(testResult[i][j][2]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::OFB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::OFB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
+
+void DESTests::testCFB()
+{
+#ifndef WITH_FIPS
+ char testKeys56[][17] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4698436794236871",
+ "0940278947239572"
+ };
+
+ char testKeys112[][33] =
+ {
+ "00000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F10",
+ "404142434445464748494A4B4C4D4E4F",
+ "64398647034486943598534703463870",
+ "87406984068406984607412103517413"
+ };
+#endif
+
+ char testKeys168[][49] =
+ {
+ "000000000000000000000000000000000000000000000000",
+ "0102030405060708090A0B0C0D0E0F101112131415161718",
+ "404142434445464748494A4B4C4D4E4F5051525354555657",
+ "643906874509874309687459084769847562436043696747",
+ "430135460496813044639085714376487549490586439575"
+ };
+
+ char testData[][256] =
+ {
+ "4938673409687134684698438657403986439058740935874395813968496846",
+ "549813644389670948567490687546098245665626527788",
+ "64398769586792586795867965624526",
+ "468376458463264536"
+ };
+
+ char testResult[5][4][3][256] = {
+ {
+ {
+ "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F",
+ "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F",
+ "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F"
+ },
+ {
+ "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B",
+ "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B",
+ "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B"
+ },
+ {
+ "E89FCA8099D6B1FFB3A24C435B847A73",
+ "E89FCA8099D6B1FFB3A24C435B847A73",
+ "E89FCA8099D6B1FFB3A24C435B847A73"
+ },
+ {
+ "CA253BAC45D205E270",
+ "CA253BAC45D205E270",
+ "CA253BAC45D205E270"
+ }
+ },
+ {
+ {
+ "3E9FB188FC11138D49C438ABB98A3846671A4DB257AA62C7929CD55A43E46D88",
+ "3440BEFCF35DC8773DD631A9C8CCF222009D45E301BBF6432A78E99416CE87D8",
+ "DDB35281888DF06446772085E3DE849298B4BE0089979260DDC59FACB17AD0BE"
+ },
+ {
+ "233FC5D8B6F005B0966FB313EA0DDFBECF19CBC937445A56",
+ "29E0CAACB9BCDE4AB219A19AA77E2C9A407C98A18BD56FDF",
+ "C01326D1C26CE6592FA4E9909D93A85BE005431046661C73"
+ },
+ {
+ "139E51D5AD1EF0E1E74DD9919AE65DB6",
+ "19415EA1A2522B1B5972F5DCBEEF4E01",
+ "F0B2B2DCD9821308815ADB01F0A16B76"
+ },
+ {
+ "3124A0F9711A44FC92",
+ "3BFBAF8D7E569F06CF",
+ "D20843F00586A715DB"
+ }
+ },
+ {
+ {
+ "E376288A10BD52CB06B42B4582A425907D2DF490EC14B478507BCDE58CE95B02",
+ "FD82CFAE85B8581F1409EB62D06A98E05C401607619DE1235822E2DEB74737E1",
+ "24D9411BA4565719BE9FF1A4D91F23B3BF8980A706747077583C8EB84AF63745"
+ },
+ {
+ "FED65CDA5A5C44F619325429C78F464D271807342B10F899",
+ "E022BBFECF594E22ABC22FA25024B6FD8F61337CBD1F023D",
+ "3979354BEEB741241F0D219B5521A488F870C849275FF8B9"
+ },
+ {
+ "CE77C8D741B2B1A7E488B94EB32C96FD",
+ "D0832FF3D4B7BB73AEC7646A3686ABCF",
+ "09D8A146F559B475A6258D03BC6F8BD3"
+ },
+ {
+ "ECCD39FB9DB605BAB2",
+ "F239DEDF08B30F6EE4",
+ "2B62506A295D00687E"
+ }
+ },
+ {
+ {
+ "740A4786C73A7C6B435071A654DA8FCC75BA3299969E327A2ABC7024378CF3AA",
+ "581B63C58404AEBE49FA5FA4032918813075279E836DFE9BAEDF37D9B21ABEE1",
+ "D5FCB196868673D1FA9C8A67E6A2449354B292E1A76BA11C416A394116857B29"
+ },
+ {
+ "69AA33D68DDB6A561FB6D6218FAC0E812514782FC6059E46",
+ "45BB1795CEE5B883232EBCCB672FC9C4803C6B827825FE94",
+ "C85CC5C6CC6765EC466B8F8AC8DFC91CB916F617873AF187"
+ },
+ {
+ "590BA7DB96359F07DB2F2CE68748425C",
+ "751A8398D50B4DD24E4681B6D0E880FC",
+ "F8FD51CBD78990BD5D088ECA798DA0E6"
+ },
+ {
+ "7BB156F74A312B1A8C",
+ "57A072B4090FF9CF1B",
+ "DA47A0E70B8D24A043"
+ }
+ },
+ {
+ {
+ "0855A84EAD2176C3D2C3DE4FB868CA2C1B0DF550E187E29808C45594C070FBF4",
+ "A8420E97462B02158D2CABD1574D072F8D83123CED9BA7CEDD7C2799E168F32D",
+ "3461DEDF1B4893E182BE36017DEBC6669B15269DFA4435A31EB1A0CE6A845176"
+ },
+ {
+ "15F5DC1EE7C060FEDC9B1B43A20588E7A073A300BEFC4CAD",
+ "B5E27AC70CCA142857CB807226DC1EA9B31BE81C0FDCD3FB",
+ "29C1AA8F51A985DC7E530E6EB7AEAC246F2ED097D09851CC"
+ },
+ {
+ "25544813FC2E95AF817E0897D4E22ECD",
+ "8543EECA1724E179543979F02103C150",
+ "19603E824A47708D80E29D3A61BAE5EA"
+ },
+ {
+ "07EEB93F202A21B250",
+ "A7F91FE6CB205564F2",
+ "3BDACFAE9643C49027"
+ }
+ }
+ };
+ char testIV[][33] =
+ {
+ "0000000000000000",
+ "0102030405060708",
+ "4041424344454647",
+ "4693867334098764",
+ "6209876098547207"
+ };
+
+ for (int i = 0; i < 5; i++)
+ {
+#ifndef WITH_FIPS
+ ByteString keyData56(testKeys56[i]);
+ CPPUNIT_ASSERT(keyData56.size() == 8);
+ ByteString keyData112(testKeys112[i]);
+ CPPUNIT_ASSERT(keyData112.size() == 16);
+#endif
+ ByteString keyData168(testKeys168[i]);
+ CPPUNIT_ASSERT(keyData168.size() == 24);
+
+#ifndef WITH_FIPS
+ DESKey desKey56(56);
+ CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56));
+ DESKey desKey112(112);
+ CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112));
+#endif
+ DESKey desKey168(168);
+ CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168));
+
+ ByteString IV(testIV[i]);
+
+ for (int j = 0; j < 4; j++)
+ {
+ ByteString plainText(testData[j]), shsmPlainText;
+ ByteString cipherText;
+ ByteString shsmCipherText, OB;
+
+#ifndef WITH_FIPS
+ // Test 56-bit key
+ cipherText = ByteString(testResult[i][j][0]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::CFB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::CFB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+
+ // Test 112-bit key
+ cipherText = ByteString(testResult[i][j][1]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::CFB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::CFB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+#endif
+
+ // Test 168-bit key
+ cipherText = ByteString(testResult[i][j][2]);
+
+ // Now, do the same thing using our DES implementation
+ shsmCipherText.wipe();
+ CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::CFB, IV));
+
+ CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(des->encryptFinal(OB));
+ shsmCipherText += OB;
+
+ CPPUNIT_ASSERT(shsmCipherText == cipherText);
+
+ // Check that we can get the plain text
+ shsmPlainText.wipe();
+ CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::CFB, IV));
+
+ CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(des->decryptFinal(OB));
+ shsmPlainText += OB;
+
+ CPPUNIT_ASSERT(shsmPlainText == plainText);
+ }
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/DESTests.h b/SoftHSMv2/src/lib/crypto/test/DESTests.h
new file mode 100644
index 0000000..0834462
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/DESTests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DESTests.h
+
+ Contains test cases to test the DES implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DESTESTS_H
+#define _SOFTHSM_V2_DESTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "SymmetricAlgorithm.h"
+
+class DESTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DESTests);
+ CPPUNIT_TEST(testBlockSize);
+ CPPUNIT_TEST(testCBC);
+ CPPUNIT_TEST(testECB);
+ CPPUNIT_TEST(testOFB);
+ CPPUNIT_TEST(testCFB);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testBlockSize();
+ void testCBC();
+ void testECB();
+ void testOFB();
+ void testCFB();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // DES instance
+ SymmetricAlgorithm* des;
+};
+
+#endif // !_SOFTHSM_V2_DESTESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/DHTests.cpp b/SoftHSMv2/src/lib/crypto/test/DHTests.cpp
new file mode 100644
index 0000000..354cdac
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/DHTests.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DHTests.cpp
+
+ Contains test cases to test the DH class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <vector>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DHTests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricAlgorithm.h"
+#include "DHParameters.h"
+#include "DHPublicKey.h"
+#include "DHPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DHTests);
+
+void DHTests::setUp()
+{
+ dh = NULL;
+
+ dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
+
+ // Check the DH object
+ CPPUNIT_ASSERT(dh != NULL);
+}
+
+void DHTests::tearDown()
+{
+ if (dh != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
+ }
+
+ fflush(stdout);
+}
+
+void DHTests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(1024);
+
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ // Generate parameters
+ DHParameters* p;
+ AsymmetricParameters** ap = (AsymmetricParameters**) &p;
+
+ CPPUNIT_ASSERT(dh->generateParameters(ap, (void*) *k));
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p));
+
+ DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey();
+ DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getBitLength() == *k);
+ CPPUNIT_ASSERT(priv->getBitLength() == *k);
+
+ dh->recycleKeyPair(kp);
+
+ // Generate key-pair with a fixed private value length
+ p->setXBitLength(128);
+ CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p));
+
+ priv = (DHPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(priv->getX().bits() == 128);
+
+ dh->recycleParameters(p);
+ dh->recycleKeyPair(kp);
+ }
+}
+
+void DHTests::testSerialisation()
+{
+ // Generate 1024-bit parameters for testing
+ DHParameters* p;
+ AsymmetricParameters** ap = (AsymmetricParameters**) &p;
+
+ CPPUNIT_ASSERT(dh->generateParameters(ap, (void*) 1024));
+
+ // Set a fixed private value length
+ p->setXBitLength(128);
+
+ // Serialise the parameters
+ ByteString serialisedParams = p->serialise();
+
+ // Deserialise the parameters
+ AsymmetricParameters* dP;
+
+ CPPUNIT_ASSERT(dh->reconstructParameters(&dP, serialisedParams));
+
+ CPPUNIT_ASSERT(dP->areOfType(DHParameters::type));
+
+ DHParameters* ddP = (DHParameters*) dP;
+
+ CPPUNIT_ASSERT(p->getP() == ddP->getP());
+ CPPUNIT_ASSERT(p->getG() == ddP->getG());
+ CPPUNIT_ASSERT(p->getXBitLength() == ddP->getXBitLength());
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(dh->generateKeyPair(&kp, dP));
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(dh->reconstructKeyPair(&dKP, serialisedKP));
+
+ // Check the deserialised key-pair
+ DHPrivateKey* privKey = (DHPrivateKey*) kp->getPrivateKey();
+ DHPublicKey* pubKey = (DHPublicKey*) kp->getPublicKey();
+
+ DHPrivateKey* dPrivKey = (DHPrivateKey*) dKP->getPrivateKey();
+ DHPublicKey* dPubKey = (DHPublicKey*) dKP->getPublicKey();
+
+ CPPUNIT_ASSERT(privKey->getP() == dPrivKey->getP());
+ CPPUNIT_ASSERT(privKey->getG() == dPrivKey->getG());
+ CPPUNIT_ASSERT(privKey->getX() == dPrivKey->getX());
+
+ CPPUNIT_ASSERT(pubKey->getP() == dPubKey->getP());
+ CPPUNIT_ASSERT(pubKey->getG() == dPubKey->getG());
+ CPPUNIT_ASSERT(pubKey->getY() == dPubKey->getY());
+
+ dh->recycleParameters(p);
+ dh->recycleParameters(dP);
+ dh->recycleKeyPair(kp);
+ dh->recycleKeyPair(dKP);
+}
+
+void DHTests::testPKCS8()
+{
+ // Generate 1024-bit parameters for testing
+ AsymmetricParameters* p;
+
+ CPPUNIT_ASSERT(dh->generateParameters(&p, (void*) 1024));
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p));
+ CPPUNIT_ASSERT(kp != NULL);
+
+ DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
+ CPPUNIT_ASSERT(priv != NULL);
+
+ // Encode and decode the private key
+ ByteString pkcs8 = priv->PKCS8Encode();
+ CPPUNIT_ASSERT(pkcs8.size() != 0);
+
+ DHPrivateKey* dPriv = (DHPrivateKey*) dh->newPrivateKey();
+ CPPUNIT_ASSERT(dPriv != NULL);
+
+ CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8));
+
+
+ CPPUNIT_ASSERT(priv->getP() == dPriv->getP());
+ CPPUNIT_ASSERT(priv->getG() == dPriv->getG());
+ CPPUNIT_ASSERT(priv->getX() == dPriv->getX());
+
+ dh->recycleParameters(p);
+ dh->recycleKeyPair(kp);
+ dh->recyclePrivateKey(dPriv);
+}
+
+void DHTests::testDerivation()
+{
+ AsymmetricKeyPair* kpa;
+ AsymmetricKeyPair* kpb;
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(1024);
+
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ // Generate parameters
+ AsymmetricParameters* p;
+
+ CPPUNIT_ASSERT(dh->generateParameters(&p, (void*) *k));
+
+ // Generate key-pairs
+ CPPUNIT_ASSERT(dh->generateKeyPair(&kpa, p));
+ CPPUNIT_ASSERT(dh->generateKeyPair(&kpb, p));
+
+ // Derive secrets
+ SymmetricKey* sa;
+ CPPUNIT_ASSERT(dh->deriveKey(&sa, kpb->getPublicKey(), kpa->getPrivateKey()));
+ SymmetricKey* sb;
+ CPPUNIT_ASSERT(dh->deriveKey(&sb, kpa->getPublicKey(), kpb->getPrivateKey()));
+
+ // Must be the same
+ CPPUNIT_ASSERT(sa->getKeyBits() == sb->getKeyBits());
+
+ // Clean up
+ dh->recycleSymmetricKey(sa);
+ dh->recycleSymmetricKey(sb);
+ dh->recycleKeyPair(kpa);
+ dh->recycleKeyPair(kpb);
+ dh->recycleParameters(p);
+ }
+}
+
+void DHTests::testDeriveKnownVector()
+{
+ // TODO
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/test/DHTests.h b/SoftHSMv2/src/lib/crypto/test/DHTests.h
new file mode 100644
index 0000000..e2a58ac
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/DHTests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DHTests.h
+
+ Contains test cases to test the DH class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DHTESTS_H
+#define _SOFTHSM_V2_DHTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+
+class DHTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DHTests);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testPKCS8);
+ CPPUNIT_TEST(testDerivation);
+ CPPUNIT_TEST(testDeriveKnownVector);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testKeyGeneration();
+ void testSerialisation();
+ void testPKCS8();
+ void testDerivation();
+ void testDeriveKnownVector();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // DH instance
+ AsymmetricAlgorithm* dh;
+};
+
+#endif // !_SOFTHSM_V2_DHTESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/DSATests.cpp b/SoftHSMv2/src/lib/crypto/test/DSATests.cpp
new file mode 100644
index 0000000..80f2514
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/DSATests.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSATests.cpp
+
+ Contains test cases to test the RNG class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <vector>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DSATests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricAlgorithm.h"
+#include "DSAParameters.h"
+#include "DSAPublicKey.h"
+#include "DSAPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DSATests);
+
+void DSATests::setUp()
+{
+ dsa = NULL;
+
+ dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
+
+ // Check the DSA object
+ CPPUNIT_ASSERT(dsa != NULL);
+}
+
+void DSATests::tearDown()
+{
+ if (dsa != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
+ }
+
+ fflush(stdout);
+}
+
+void DSATests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+#ifndef WITH_FIPS
+ keySizes.push_back(1024);
+ keySizes.push_back(1536);
+#else
+ keySizes.push_back(1024);
+#endif
+#ifndef WITH_BOTAN
+ keySizes.push_back(2048);
+#endif
+
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ // Generate parameters
+ DSAParameters* p;
+ AsymmetricParameters** ap = (AsymmetricParameters**) &p;
+
+ CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) *k));
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p));
+
+ DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
+ DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getBitLength() == *k);
+ CPPUNIT_ASSERT(priv->getBitLength() == *k);
+
+ dsa->recycleParameters(p);
+ dsa->recycleKeyPair(kp);
+ }
+}
+
+void DSATests::testSerialisation()
+{
+ // Generate 1024-bit parameters for testing
+ DSAParameters* p;
+ AsymmetricParameters** ap = (AsymmetricParameters**) &p;
+
+ CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) 1024));
+
+ // Serialise the parameters
+ ByteString serialisedParams = p->serialise();
+
+ // Deserialise the parameters
+ AsymmetricParameters* dP;
+
+ CPPUNIT_ASSERT(dsa->reconstructParameters(&dP, serialisedParams));
+
+ CPPUNIT_ASSERT(dP->areOfType(DSAParameters::type));
+
+ DSAParameters* ddP = (DSAParameters*) dP;
+
+ CPPUNIT_ASSERT(p->getP() == ddP->getP());
+ CPPUNIT_ASSERT(p->getQ() == ddP->getQ());
+ CPPUNIT_ASSERT(p->getG() == ddP->getG());
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, dP));
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(dsa->reconstructKeyPair(&dKP, serialisedKP));
+
+ // Check the deserialised key-pair
+ DSAPrivateKey* privKey = (DSAPrivateKey*) kp->getPrivateKey();
+ DSAPublicKey* pubKey = (DSAPublicKey*) kp->getPublicKey();
+
+ DSAPrivateKey* dPrivKey = (DSAPrivateKey*) dKP->getPrivateKey();
+ DSAPublicKey* dPubKey = (DSAPublicKey*) dKP->getPublicKey();
+
+ CPPUNIT_ASSERT(privKey->getP() == dPrivKey->getP());
+ CPPUNIT_ASSERT(privKey->getQ() == dPrivKey->getQ());
+ CPPUNIT_ASSERT(privKey->getG() == dPrivKey->getG());
+ CPPUNIT_ASSERT(privKey->getX() == dPrivKey->getX());
+
+ CPPUNIT_ASSERT(pubKey->getP() == dPubKey->getP());
+ CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ());
+ CPPUNIT_ASSERT(pubKey->getG() == dPubKey->getG());
+ CPPUNIT_ASSERT(pubKey->getY() == dPubKey->getY());
+
+ dsa->recycleParameters(p);
+ dsa->recycleParameters(dP);
+ dsa->recycleKeyPair(kp);
+ dsa->recycleKeyPair(dKP);
+}
+
+void DSATests::testPKCS8()
+{
+ // Generate 1024-bit parameters for testing
+ AsymmetricParameters* p;
+
+ CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) 1024));
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p));
+ CPPUNIT_ASSERT(kp != NULL);
+
+ DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
+ CPPUNIT_ASSERT(priv != NULL);
+
+ // Encode and decode the private key
+ ByteString pkcs8 = priv->PKCS8Encode();
+ CPPUNIT_ASSERT(pkcs8.size() != 0);
+
+ DSAPrivateKey* dPriv = (DSAPrivateKey*) dsa->newPrivateKey();
+ CPPUNIT_ASSERT(dPriv != NULL);
+
+ CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8));
+
+ CPPUNIT_ASSERT(priv->getP() == dPriv->getP());
+ CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ());
+ CPPUNIT_ASSERT(priv->getG() == dPriv->getG());
+ CPPUNIT_ASSERT(priv->getX() == dPriv->getX());
+
+ dsa->recycleParameters(p);
+ dsa->recycleKeyPair(kp);
+ dsa->recyclePrivateKey(dPriv);
+}
+
+void DSATests::testSigningVerifying()
+{
+ AsymmetricKeyPair* kp;
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+#ifndef WITH_FIPS
+ keySizes.push_back(1024);
+ keySizes.push_back(1536);
+#else
+ keySizes.push_back(1024);
+#endif
+#ifndef WITH_BOTAN
+ keySizes.push_back(2048);
+#endif
+
+ // Mechanisms to test
+ std::vector<AsymMech::Type> mechanisms;
+ mechanisms.push_back(AsymMech::DSA_SHA1);
+ mechanisms.push_back(AsymMech::DSA_SHA224);
+ mechanisms.push_back(AsymMech::DSA_SHA256);
+
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ // Generate parameters
+ AsymmetricParameters* p;
+
+ CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) *k));
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p));
+
+ // Generate some data to sign
+ ByteString dataToSign;
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));
+
+ // Test mechanisms that perform internal hashing
+ for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++)
+ {
+ ByteString blockSignature, singlePartSignature;
+
+ // Sign the data in blocks
+ CPPUNIT_ASSERT(dsa->signInit(kp->getPrivateKey(), *m));
+ CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(0, 134)));
+ CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134, 289)));
+ CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134 + 289)));
+ CPPUNIT_ASSERT(dsa->signFinal(blockSignature));
+
+ // Sign the data in one pass
+ CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m));
+
+ // Now perform multi-pass verification
+ CPPUNIT_ASSERT(dsa->verifyInit(kp->getPublicKey(), *m));
+ CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(0, 125)));
+ CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125, 247)));
+ CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125 + 247)));
+ CPPUNIT_ASSERT(dsa->verifyFinal(blockSignature));
+
+ // And single-pass verification
+ CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m));
+ }
+
+ // Test mechanisms that do not perform internal hashing
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, *k >= 2048 ? 32 : 20));
+
+ // Sign the data
+ ByteString signature;
+ CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::DSA));
+
+ // Verify the signature
+ CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::DSA));
+
+ dsa->recycleKeyPair(kp);
+ dsa->recycleParameters(p);
+ }
+}
+
+void DSATests::testSignVerifyKnownVector()
+{
+ DSAPublicKey* pubKey1 = (DSAPublicKey*) dsa->newPublicKey();
+ DSAPublicKey* pubKey2 = (DSAPublicKey*) dsa->newPublicKey();
+ DSAPrivateKey* privKey1 = (DSAPrivateKey*) dsa->newPrivateKey();
+ DSAPrivateKey* privKey2 = (DSAPrivateKey*) dsa->newPrivateKey();
+
+ // Reconstruct public and private key #1
+ ByteString p1 = "e0a67598cd1b763bc98c8abb333e5dda0cd3aa0e5e1fb5ba8a7b4eabc10ba338fae06dd4b90fda70d7cf0cb0c638be3341bec0af8a7330a3307ded2299a0ee606df035177a239c34a912c202aa5f83b9c4a7cf0235b5316bfc6efb9a248411258b30b839af172440f32563056cb67a861158ddd90e6a894c72a5bbef9e286c6b";
+ ByteString q1 = "e950511eab424b9a19a2aeb4e159b7844c589c4f";
+ ByteString g1 = "d29d5121b0423c2769ab21843e5a3240ff19cacc792264e3bb6be4f78edd1b15c4dff7f1d905431f0ab16790e1f773b5ce01c804e509066a9919f5195f4abc58189fd9ff987389cb5bedf21b4dab4f8b76a055ffe2770988fe2ec2de11ad92219f0b351869ac24da3d7ba87011a701ce8ee7bfe49486ed4527b7186ca4610a75";
+ ByteString x1 = "d0ec4e50bb290a42e9e355c73d8809345de2e139";
+ ByteString y1 = "25282217f5730501dd8dba3edfcf349aaffec20921128d70fac44110332201bba3f10986140cbb97c726938060473c8ec97b4731db004293b5e730363609df9780f8d883d8c4d41ded6a2f1e1bbbdc979e1b9d6d3c940301f4e978d65b19041fcf1e8b518f5c0576c770fe5a7a485d8329ee2914a2de1b5da4a6128ceab70f79";
+
+ pubKey1->setP(p1);
+ pubKey1->setQ(q1);
+ pubKey1->setG(g1);
+ pubKey1->setY(y1);
+ privKey1->setP(p1);
+ privKey1->setQ(q1);
+ privKey1->setG(g1);
+ privKey1->setX(x1);
+
+ // Test with key #1
+ ByteString data1 = "616263"; // "abc"
+ ByteString goodSignature1 = "636155ac9a4633b4665d179f9e4117df68601f346c540b02d9d4852f89df8cfc99963204f4347704";
+ ByteString badSignature1 = "636155ac9a4633b4665d179f9e4117df68601f346c540b02d9d4852f89df8cfc99963204f4347705";
+
+ // Reconstruct public and private key #2
+ ByteString p2 = "f56c2a7d366e3ebdeaa1891fd2a0d099436438a673fed4d75f594959cffebca7be0fc72e4fe67d91d801cba0693ac4ed9e411b41d19e2fd1699c4390ad27d94c69c0b143f1dc88932cfe2310c886412047bd9b1c7a67f8a25909132627f51a0c866877e672e555342bdf9355347dbd43b47156b2c20bad9d2b071bc2fdcf9757f75c168c5d9fc43131be162a0756d1bdec2ca0eb0e3b018a8b38d3ef2487782aeb9fbf99d8b30499c55e4f61e5c7dcee2a2bb55bd7f75fcdf00e48f2e8356bdb59d86114028f67b8e07b127744778aff1cf1399a4d679d92fde7d941c5c85c5d7bff91ba69f9489d531d1ebfa727cfda651390f8021719fa9f7216ceb177bd75";
+ ByteString q2 = "c24ed361870b61e0d367f008f99f8a1f75525889c89db1b673c45af5867cb467";
+ ByteString g2 = "8dc6cc814cae4a1c05a3e186a6fe27eaba8cdb133fdce14a963a92e809790cba096eaa26140550c129fa2b98c16e84236aa33bf919cd6f587e048c52666576db6e925c6cbe9b9ec5c16020f9a44c9f1c8f7a8e611c1f6ec2513ea6aa0b8d0f72fed73ca37df240db57bbb27431d618697b9e771b0b301d5df05955425061a30dc6d33bb6d2a32bd0a75a0a71d2184f506372abf84a56aeeea8eb693bf29a640345fa1298a16e85421b2208d00068a5a42915f82cf0b858c8fa39d43d704b6927e0b2f916304e86fb6a1b487f07d8139e428bb096c6d67a76ec0b8d4ef274b8a2cf556d279ad267ccef5af477afed029f485b5597739f5d0240f67c2d948a6279";
+ ByteString x2 = "0caf2ef547ec49c4f3a6fe6df4223a174d01f2c115d49a6f73437c29a2a8458c";
+ ByteString y2 = "2828003d7c747199143c370fdd07a2861524514acc57f63f80c38c2087c6b795b62de1c224bf8d1d1424e60ce3f5ae3f76c754a2464af292286d873a7a30b7eacbbc75aafde7191d9157598cdb0b60e0c5aa3f6ebe425500c611957dbf5ed35490714a42811fdcdeb19af2ab30beadff2907931cee7f3b55532cffaeb371f84f01347630eb227a419b1f3f558bc8a509d64a765d8987d493b007c4412c297caf41566e26faee475137ec781a0dc088a26c8804a98c23140e7c936281864b99571ee95c416aa38ceebb41fdbff1eb1d1dc97b63ce1355257627c8b0fd840ddb20ed35be92f08c49aea5613957d7e5c7a6d5a5834b4cb069e0831753ecf65ba02b";
+
+ pubKey2->setP(p2);
+ pubKey2->setQ(q2);
+ pubKey2->setG(g2);
+ pubKey2->setY(y2);
+ privKey2->setP(p2);
+ privKey2->setQ(q2);
+ privKey2->setG(g2);
+ privKey2->setX(x2);
+
+ // Test with key #2
+ ByteString data2 = "616263"; // "abc"
+ ByteString goodSignature2 = "315c875dcd4850e948b8ac42824e9483a32d5ba5abe0681b9b9448d444f2be3c89718d12e54a8d9ed066e4a55f7ed5a2229cd23b9a3cee78f83ed6aa61f6bcb9";
+ ByteString badSignature2 = "315c875dcd4850e948b8ac42824e9483a32d5ba5abe0681b9b9448d444f2be3c89718d12e54a8d9ed066e4a55f7ed5a2229cd23b9a3cee78f83ed6aa61f6bcb8";
+
+ CPPUNIT_ASSERT(dsa->verify(pubKey1, data1, goodSignature1, AsymMech::DSA_SHA1));
+ CPPUNIT_ASSERT(!dsa->verify(pubKey1, data1, badSignature1, AsymMech::DSA_SHA1));
+ CPPUNIT_ASSERT(dsa->verify(pubKey2, data2, goodSignature2, AsymMech::DSA_SHA256));
+ CPPUNIT_ASSERT(!dsa->verify(pubKey2, data2, badSignature2, AsymMech::DSA_SHA256));
+
+ dsa->recyclePublicKey(pubKey1);
+ dsa->recyclePublicKey(pubKey2);
+ dsa->recyclePrivateKey(privKey1);
+ dsa->recyclePrivateKey(privKey2);
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/DSATests.h b/SoftHSMv2/src/lib/crypto/test/DSATests.h
new file mode 100644
index 0000000..446733a
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/DSATests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DSATests.h
+
+ Contains test cases to test the DSA class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DSATESTS_H
+#define _SOFTHSM_V2_DSATESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+
+class DSATests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DSATests);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testPKCS8);
+ CPPUNIT_TEST(testSigningVerifying);
+ CPPUNIT_TEST(testSignVerifyKnownVector);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testKeyGeneration();
+ void testSerialisation();
+ void testPKCS8();
+ void testSigningVerifying();
+ void testSignVerifyKnownVector();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // DSA instance
+ AsymmetricAlgorithm* dsa;
+};
+
+#endif // !_SOFTHSM_V2_DSATESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp b/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp
new file mode 100644
index 0000000..1646fd8
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECDHTests.cpp
+
+ Contains test cases to test the ECDH class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <vector>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ECDHTests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricAlgorithm.h"
+#ifdef WITH_ECC
+#include "ECParameters.h"
+#include "ECPublicKey.h"
+#include "ECPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ECDHTests);
+
+void ECDHTests::setUp()
+{
+ ecdh = NULL;
+
+ ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
+
+ // Check the ECDH object
+ CPPUNIT_ASSERT(ecdh != NULL);
+}
+
+void ECDHTests::tearDown()
+{
+ if (ecdh != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
+ }
+
+ fflush(stdout);
+}
+
+void ECDHTests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+
+ // Curves to test
+ std::vector<ByteString> curves;
+ // Add X9.62 prime256v1
+ curves.push_back(ByteString("06082a8648ce3d030107"));
+ // Add secp384r1
+ curves.push_back(ByteString("06052b81040022"));
+
+ for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++)
+ {
+ // Set domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(*c);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(ecdh->generateKeyPair(&kp, p));
+
+ ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
+ ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getEC() == *c);
+ CPPUNIT_ASSERT(priv->getEC() == *c);
+
+ ecdh->recycleParameters(p);
+ ecdh->recycleKeyPair(kp);
+ }
+}
+
+void ECDHTests::testSerialisation()
+{
+ // Get prime256v1 domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(ByteString("06082a8648ce3d030107"));
+
+ // Serialise the parameters
+ ByteString serialisedParams = p->serialise();
+
+ // Deserialise the parameters
+ AsymmetricParameters* dEC;
+
+ CPPUNIT_ASSERT(ecdh->reconstructParameters(&dEC, serialisedParams));
+
+ CPPUNIT_ASSERT(dEC->areOfType(ECParameters::type));
+
+ ECParameters* ddEC = (ECParameters*) dEC;
+
+ CPPUNIT_ASSERT(p->getEC() == ddEC->getEC());
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(ecdh->generateKeyPair(&kp, dEC));
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(ecdh->reconstructKeyPair(&dKP, serialisedKP));
+
+ // Check the deserialised key-pair
+ ECPrivateKey* privKey = (ECPrivateKey*) kp->getPrivateKey();
+ ECPublicKey* pubKey = (ECPublicKey*) kp->getPublicKey();
+
+ ECPrivateKey* dPrivKey = (ECPrivateKey*) dKP->getPrivateKey();
+ ECPublicKey* dPubKey = (ECPublicKey*) dKP->getPublicKey();
+
+ CPPUNIT_ASSERT(privKey->getEC() == dPrivKey->getEC());
+ CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD());
+
+ CPPUNIT_ASSERT(pubKey->getEC() == dPubKey->getEC());
+ CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ());
+
+ ecdh->recycleParameters(p);
+ ecdh->recycleParameters(dEC);
+ ecdh->recycleKeyPair(kp);
+ ecdh->recycleKeyPair(dKP);
+}
+
+void ECDHTests::testPKCS8()
+{
+ // Get prime256v1 domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(ByteString("06082a8648ce3d030107"));
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(ecdh->generateKeyPair(&kp, p));
+ CPPUNIT_ASSERT(kp != NULL);
+
+ ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
+ CPPUNIT_ASSERT(priv != NULL);
+
+ // Encode and decode the private key
+ ByteString pkcs8 = priv->PKCS8Encode();
+ CPPUNIT_ASSERT(pkcs8.size() != 0);
+
+ ECPrivateKey* dPriv = (ECPrivateKey*) ecdh->newPrivateKey();
+ CPPUNIT_ASSERT(dPriv != NULL);
+
+ CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8));
+
+ CPPUNIT_ASSERT(priv->getEC() == dPriv->getEC());
+ CPPUNIT_ASSERT(priv->getD() == dPriv->getD());
+
+ ecdh->recycleParameters(p);
+ ecdh->recycleKeyPair(kp);
+ ecdh->recyclePrivateKey(dPriv);
+}
+
+void ECDHTests::testDerivation()
+{
+ AsymmetricKeyPair* kpa;
+ AsymmetricKeyPair* kpb;
+ ECParameters* p;
+
+ // Curves to test
+ std::vector<ByteString> curves;
+ // Add X9.62 prime256v1
+ curves.push_back(ByteString("06082a8648ce3d030107"));
+ // Add secp384r1
+ curves.push_back(ByteString("06052b81040022"));
+
+ for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++)
+ {
+ // Get parameters
+ p = new ECParameters;
+ CPPUNIT_ASSERT(p != NULL);
+ p->setEC(*c);
+
+ // Generate key-pairs
+ CPPUNIT_ASSERT(ecdh->generateKeyPair(&kpa, p));
+ CPPUNIT_ASSERT(ecdh->generateKeyPair(&kpb, p));
+
+ // Derive secrets
+ SymmetricKey* sa;
+ CPPUNIT_ASSERT(ecdh->deriveKey(&sa, kpb->getPublicKey(), kpa->getPrivateKey()));
+ SymmetricKey* sb;
+ CPPUNIT_ASSERT(ecdh->deriveKey(&sb, kpa->getPublicKey(), kpb->getPrivateKey()));
+
+ // Must be the same
+ CPPUNIT_ASSERT(sa->getKeyBits() == sb->getKeyBits());
+
+ // Clean up
+ ecdh->recycleSymmetricKey(sa);
+ ecdh->recycleSymmetricKey(sb);
+ ecdh->recycleKeyPair(kpa);
+ ecdh->recycleKeyPair(kpb);
+ ecdh->recycleParameters(p);
+ }
+}
+
+void ECDHTests::testDeriveKnownVector()
+{
+ ECPublicKey* pubKeya = (ECPublicKey*) ecdh->newPublicKey();
+ ECPublicKey* pubKeyb = (ECPublicKey*) ecdh->newPublicKey();
+ ECPrivateKey* privKeya = (ECPrivateKey*) ecdh->newPrivateKey();
+ ECPrivateKey* privKeyb = (ECPrivateKey*) ecdh->newPrivateKey();
+
+ // Reconstruct public and private key for Alice
+ ByteString ec = "06082a8648ce3d030107"; // X9.62 prime256v1
+ ByteString da = "c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433";
+ // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front!
+ ByteString qa = "044104dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3";
+
+ pubKeya->setEC(ec);
+ pubKeya->setQ(qa);
+ privKeya->setEC(ec);
+ privKeya->setD(da);
+
+ // Reconstruct public and private key for Bob
+ ByteString db = "c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0b283ab46476bee53";
+ ByteString qb = "044104d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab";
+
+ pubKeyb->setEC(ec);
+ pubKeyb->setQ(qb);
+ privKeyb->setEC(ec);
+ privKeyb->setD(db);
+
+ // Test
+ ByteString expected = "d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de";
+ SymmetricKey* sa;
+ CPPUNIT_ASSERT(ecdh->deriveKey(&sa, pubKeya, privKeyb));
+ CPPUNIT_ASSERT(sa->getKeyBits() == expected);
+ SymmetricKey* sb;
+ CPPUNIT_ASSERT(ecdh->deriveKey(&sb, pubKeyb, privKeya));
+ CPPUNIT_ASSERT(sb->getKeyBits() == expected);
+
+ ecdh->recyclePublicKey(pubKeya);
+ ecdh->recyclePublicKey(pubKeyb);
+ ecdh->recyclePrivateKey(privKeya);
+ ecdh->recyclePrivateKey(privKeyb);
+ ecdh->recycleSymmetricKey(sa);
+ ecdh->recycleSymmetricKey(sb);
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/test/ECDHTests.h b/SoftHSMv2/src/lib/crypto/test/ECDHTests.h
new file mode 100644
index 0000000..81cf6d5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/ECDHTests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECDHTests.h
+
+ Contains test cases to test the ECDH class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ECDHTESTS_H
+#define _SOFTHSM_V2_ECDHTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+
+class ECDHTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ECDHTests);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testPKCS8);
+ CPPUNIT_TEST(testDerivation);
+ CPPUNIT_TEST(testDeriveKnownVector);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testKeyGeneration();
+ void testSerialisation();
+ void testPKCS8();
+ void testDerivation();
+ void testDeriveKnownVector();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // ECDH instance
+ AsymmetricAlgorithm* ecdh;
+};
+
+#endif // !_SOFTHSM_V2_ECDHTESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp b/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp
new file mode 100644
index 0000000..3c29d06
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECDSATests.cpp
+
+ Contains test cases to test the ECDSA class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <utility>
+#include <vector>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ECDSATests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricAlgorithm.h"
+#ifdef WITH_ECC
+#include "ECParameters.h"
+#include "ECPublicKey.h"
+#include "ECPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ECDSATests);
+
+void ECDSATests::setUp()
+{
+ ecdsa = NULL;
+
+ ecdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
+
+ // Check the ECDSA object
+ CPPUNIT_ASSERT(ecdsa != NULL);
+}
+
+void ECDSATests::tearDown()
+{
+ if (ecdsa != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdsa);
+ }
+
+ fflush(stdout);
+}
+
+void ECDSATests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+
+ // Curves to test
+ std::vector<ByteString> curves;
+ // Add X9.62 prime256v1
+ curves.push_back(ByteString("06082a8648ce3d030107"));
+ // Add secp384r1
+ curves.push_back(ByteString("06052b81040022"));
+ // Add secp521r1
+ curves.push_back(ByteString("06052b81040023"));
+
+ for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++)
+ {
+ // Set domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(*c);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, p));
+
+ ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
+ ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getEC() == *c);
+ CPPUNIT_ASSERT(priv->getEC() == *c);
+
+ ecdsa->recycleParameters(p);
+ ecdsa->recycleKeyPair(kp);
+ }
+}
+
+void ECDSATests::testSerialisation()
+{
+ // Get prime256v1 domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(ByteString("06082a8648ce3d030107"));
+
+ // Serialise the parameters
+ ByteString serialisedParams = p->serialise();
+
+ // Deserialise the parameters
+ AsymmetricParameters* dEC;
+
+ CPPUNIT_ASSERT(ecdsa->reconstructParameters(&dEC, serialisedParams));
+
+ CPPUNIT_ASSERT(dEC->areOfType(ECParameters::type));
+
+ ECParameters* ddEC = (ECParameters*) dEC;
+
+ CPPUNIT_ASSERT(p->getEC() == ddEC->getEC());
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, dEC));
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(ecdsa->reconstructKeyPair(&dKP, serialisedKP));
+
+ // Check the deserialised key-pair
+ ECPrivateKey* privKey = (ECPrivateKey*) kp->getPrivateKey();
+ ECPublicKey* pubKey = (ECPublicKey*) kp->getPublicKey();
+
+ ECPrivateKey* dPrivKey = (ECPrivateKey*) dKP->getPrivateKey();
+ ECPublicKey* dPubKey = (ECPublicKey*) dKP->getPublicKey();
+
+ CPPUNIT_ASSERT(privKey->getEC() == dPrivKey->getEC());
+ CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD());
+
+ CPPUNIT_ASSERT(pubKey->getEC() == dPubKey->getEC());
+ CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ());
+
+ ecdsa->recycleParameters(p);
+ ecdsa->recycleParameters(dEC);
+ ecdsa->recycleKeyPair(kp);
+ ecdsa->recycleKeyPair(dKP);
+}
+
+void ECDSATests::testPKCS8()
+{
+ // Get prime256v1 domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(ByteString("06082a8648ce3d030107"));
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, p));
+ CPPUNIT_ASSERT(kp != NULL);
+
+ ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
+ CPPUNIT_ASSERT(priv != NULL);
+
+ // Encode and decode the private key
+ ByteString pkcs8 = priv->PKCS8Encode();
+ CPPUNIT_ASSERT(pkcs8.size() != 0);
+
+ ECPrivateKey* dPriv = (ECPrivateKey*) ecdsa->newPrivateKey();
+ CPPUNIT_ASSERT(dPriv != NULL);
+
+ CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8));
+
+ CPPUNIT_ASSERT(priv->getEC() == dPriv->getEC());
+ CPPUNIT_ASSERT(priv->getD() == dPriv->getD());
+
+ ecdsa->recycleParameters(p);
+ ecdsa->recycleKeyPair(kp);
+ ecdsa->recyclePrivateKey(dPriv);
+}
+
+void ECDSATests::testSigningVerifying()
+{
+ AsymmetricKeyPair* kp;
+ ECParameters *p;
+
+ // Curves/Hashes to test
+ std::vector<std::pair<ByteString, HashAlgo::Type> > totest;
+ // Add X9.62 prime256v1
+ totest.push_back(std::make_pair(ByteString("06082a8648ce3d030107"), HashAlgo::SHA256));
+ // Add secp384r1
+ totest.push_back(std::make_pair(ByteString("06052b81040022"), HashAlgo::SHA384));
+ // Add secp521r1
+ totest.push_back(std::make_pair(ByteString("06052b81040023"), HashAlgo::SHA384));
+
+ for (std::vector<std::pair<ByteString, HashAlgo::Type> >::iterator k = totest.begin(); k != totest.end(); k++)
+ {
+ // Get parameters
+ p = new ECParameters;
+ CPPUNIT_ASSERT(p != NULL);
+ p->setEC(k->first);
+ HashAlgorithm *hash;
+ hash = CryptoFactory::i()->getHashAlgorithm(k->second);
+ CPPUNIT_ASSERT(hash != NULL);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, p));
+
+ // Generate some data to sign
+ ByteString dataToSign;
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+ CPPUNIT_ASSERT(rng != NULL);
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));
+
+ // Sign the data
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(dataToSign));
+ ByteString hResult;
+ CPPUNIT_ASSERT(hash->hashFinal(hResult));
+ ByteString sig;
+ CPPUNIT_ASSERT(ecdsa->sign(kp->getPrivateKey(), hResult, sig, AsymMech::ECDSA));
+
+ // And verify it
+ CPPUNIT_ASSERT(ecdsa->verify(kp->getPublicKey(), hResult, sig, AsymMech::ECDSA));
+
+ ecdsa->recycleKeyPair(kp);
+ ecdsa->recycleParameters(p);
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ }
+}
+
+void ECDSATests::testSignVerifyKnownVector()
+{
+ ECPublicKey* pubKey1 = (ECPublicKey*) ecdsa->newPublicKey();
+ ECPublicKey* pubKey2 = (ECPublicKey*) ecdsa->newPublicKey();
+ ECPrivateKey* privKey1 = (ECPrivateKey*) ecdsa->newPrivateKey();
+ ECPrivateKey* privKey2 = (ECPrivateKey*) ecdsa->newPrivateKey();
+ HashAlgorithm* hash1 = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA256);
+ HashAlgorithm* hash2 = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA384);
+
+ // Reconstruct public and private key #1
+ ByteString ec1 = "06082a8648ce3d030107"; // X9.62 prime256v1
+ ByteString d1 = "dc51d3866a15bacde33d96f992fca99da7e6ef0934e7097559c27f1614c88a7f";
+ // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front!
+ ByteString q1 = "0441042442a5cc0ecd015fa3ca31dc8e2bbc70bf42d60cbca20085e0822cb04235e9706fc98bd7e50211a4a27102fa3549df79ebcb4bf246b80945cddfe7d509bbfd7d";
+
+ pubKey1->setEC(ec1);
+ pubKey1->setQ(q1);
+ privKey1->setEC(ec1);
+ privKey1->setD(d1);
+ CPPUNIT_ASSERT(hash1 != NULL);
+
+ // Test with key #1
+ ByteString data1 = "616263"; // "abc"
+ ByteString goodSignature1 = "cb28e0999b9c7715fd0a80d8e47a77079716cbbf917dd72e97566ea1c066957c86fa3bb4e26cad5bf90b7f81899256ce7594bb1ea0c89212748bff3b3d5b0315";
+ ByteString badSignature1 = "cb28e0999b9c7715fd0a80d8e47a77079716cbbf917dd72e97566ea1c066957c86fa3bb4e26cad5bf90b7f81899256ce7594bb1ea0c89212748bff3b3d5b0316";
+
+ // Reconstruct public and private key #2
+ ByteString ec2 = "06052b81040022"; // secp384r1
+ ByteString d2 = "0beb646634ba87735d77ae4809a0ebea865535de4c1e1dcb692e84708e81a5af62e528c38b2a81b35309668d73524d9f";
+ // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front!
+ ByteString q2 = "04610496281bf8dd5e0525ca049c048d345d3082968d10fedf5c5aca0c64e6465a97ea5ce10c9dfec21797415710721f437922447688ba94708eb6e2e4d59f6ab6d7edff9301d249fe49c33096655f5d502fad3d383b91c5e7edaa2b714cc99d5743ca";
+
+ pubKey2->setEC(ec2);
+ pubKey2->setQ(q2);
+ privKey2->setEC(ec2);
+ privKey2->setD(d2);
+ CPPUNIT_ASSERT(hash2 != NULL);
+
+ // Test with key #2
+ ByteString data2 = "616263"; // "abc"
+ ByteString goodSignature2 = "fb017b914e29149432d8bac29a514640b46f53ddab2c69948084e2930f1c8f7e08e07c9c63f2d21a07dcb56a6af56eb3b263a1305e057f984d38726a1b46874109f417bca112674c528262a40a629af1cbb9f516ce0fa7d2ff630863a00e8b9f";
+ ByteString badSignature2 = "fb017b914e29149432d8bac29a514640b46f53ddab2c69948084e2930f1c8f7e08e07c9c63f2d21a07dcb56a6af56eb3b263a1305e057f984d38726a1b46874109f417bca112674c528262a40a629af1cbb9f516ce0fa7d2ff630863a00e8b9e";
+
+ CPPUNIT_ASSERT(hash1->hashInit());
+ CPPUNIT_ASSERT(hash1->hashUpdate(data1));
+ ByteString hResult1;
+ CPPUNIT_ASSERT(hash1->hashFinal(hResult1));
+ CPPUNIT_ASSERT(ecdsa->verify(pubKey1, hResult1, goodSignature1, AsymMech::ECDSA));
+ CPPUNIT_ASSERT(!ecdsa->verify(pubKey1, hResult1, badSignature1, AsymMech::ECDSA));
+ CPPUNIT_ASSERT(hash2->hashInit());
+ CPPUNIT_ASSERT(hash2->hashUpdate(data2));
+ ByteString hResult2;
+ CPPUNIT_ASSERT(hash2->hashFinal(hResult2));
+ CPPUNIT_ASSERT(ecdsa->verify(pubKey2, hResult2, goodSignature2, AsymMech::ECDSA));
+ CPPUNIT_ASSERT(!ecdsa->verify(pubKey2, hResult2, badSignature2, AsymMech::ECDSA));
+
+ ecdsa->recyclePublicKey(pubKey1);
+ ecdsa->recyclePublicKey(pubKey2);
+ ecdsa->recyclePrivateKey(privKey1);
+ ecdsa->recyclePrivateKey(privKey2);
+ CryptoFactory::i()->recycleHashAlgorithm(hash1);
+ CryptoFactory::i()->recycleHashAlgorithm(hash2);
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/test/ECDSATests.h b/SoftHSMv2/src/lib/crypto/test/ECDSATests.h
new file mode 100644
index 0000000..70b3345
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/ECDSATests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ECDSATests.h
+
+ Contains test cases to test the ECDSA class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ECDSATESTS_H
+#define _SOFTHSM_V2_ECDSATESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+
+class ECDSATests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ECDSATests);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testPKCS8);
+ CPPUNIT_TEST(testSigningVerifying);
+ CPPUNIT_TEST(testSignVerifyKnownVector);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testKeyGeneration();
+ void testSerialisation();
+ void testPKCS8();
+ void testSigningVerifying();
+ void testSignVerifyKnownVector();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // ECDSA instance
+ AsymmetricAlgorithm* ecdsa;
+};
+
+#endif // !_SOFTHSM_V2_ECDSATESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp b/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp
new file mode 100644
index 0000000..91f6876
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ GOSTTests.cpp
+
+ Contains test cases to test the GOST implementations
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "GOSTTests.h"
+#include "CryptoFactory.h"
+#include <stdio.h>
+#include "AsymmetricAlgorithm.h"
+#include "AsymmetricKeyPair.h"
+#include "HashAlgorithm.h"
+#include "MacAlgorithm.h"
+#include "RNG.h"
+#ifdef WITH_GOST
+#include "ECParameters.h"
+#include "GOSTPublicKey.h"
+#include "GOSTPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(GOSTTests);
+
+void GOSTTests::setUp()
+{
+ hash = NULL;
+ mac = NULL;
+ gost = NULL;
+ rng = NULL;
+
+ gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
+
+ // Check the GOST object
+ CPPUNIT_ASSERT(gost != NULL);
+}
+
+void GOSTTests::tearDown()
+{
+ if (hash != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ }
+
+ if (mac != NULL)
+ {
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+ }
+
+ if (gost != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
+ }
+
+ fflush(stdout);
+}
+
+void GOSTTests::testHash()
+{
+ char testData[4096] = "FE5A773751EAB2F18921C04806D6907444557B4469CDA7C822288E5065DA58F448A27FA0B4C8786853F246B093E3DBFDC332759D7764B6D057895184D9B82E626DF70AEB99B969EA35E5BE4D50C7406EA4A7450AC063933F96F77960EE711A445593119CF69061702CB4797F214FA440C94127E3DCD92F2C71B39D354C6F4284E030DCBFCB91EA5E543E0E3560ECD355091850BA080287BD87B74BB84A8892E0F2172F136D187305179F23EB8296BF1798405BAB52E201F22BCA5B793C5BA6F2CA15F154598EEC73E7E61B405262F6FE5FDC0F9AE0528801C3F965956C79A6C6805EDD0C6515AEA27D1DB9D70A56B0F13A544429C448FB6DB390C0E367EDF997E0B681ADE3846D77D1898F06FB60CB2384015F3749BD1E8163E532529E4D3BB8B200BBE79DA76D4865621FF2E583A1A1F8EBFB7A51B65DC9152B173A7DF91C6943F2FE497CDBC306827146199ADA925DD42B8A48429F5B6E3670AA85A44BDFAB3D273EA6711B996B5C27E04949BE61ED9ECB932F429ADCF31A2E0E9F83FCB1CE6BC0EE81627D1F9D08ECD599F16A1D68B256B002E90A8B4E5830A049ECE9ADF1D50C027EC537DD5412AA1509E91CEF358B2D495D3B37651987F51D9643A5AF2E0EF3D8C02E6023BB76FF8F1EB5CD018FA32BD7886A1A46A7D5CA15E4E0CDB793F0C1986EF4480305801A518B1D4596AAA741C093FC7AD075B637B1B2CC4DA33B6EB6D549001B33E1753C9C4358FB541FDE6541238BD011CD8ACAFB4CFF15B289872956DFBCC732593E838B6300E48ED3455CD101920114640A5B7C1250E419B7D771EC65934F53176BBD7A61A36D6D3D64A1F29C3D41745993636F812930E2936E9ED34E92A3C31239176ED3F78461EE80C54D92CBD9EF9F5746F8069809A38549FC7A8FD99FB350C27230966D6001D3136114A7BDCDEE495B72E4A633845BC88400DEDADC2FA2CD8640049CDB4F8F695C45EACF24FD573E1FB1670F688C9D7706A9AE9EB30E0DFDD54C7F3F3EE6F9BBFBBED6DB6E7C7B979E677DCD8457949DC271BD6ACB445B16247D8DAC1B59D45B8FFBBFDAEA20A5C450E0F93B399AE69887E1C721B0EF86C8CD37FC7514C4F2B70AA1E757DE95DCC3B74C6E18E51D272D433330826435B7CBA6C099558B51E408B1BFE60E876141A74195A00BF914F2536D92170FB43E078D98F784E6F150ED2B16DB5B629EBABF16444639C87A544050E03FB7CCD538DA29C45CE764F68682B48BF8AE5ED43064E833338A88605B1743FEB025D5F5607BB13A2078A99924A2D4818CD582ACDC1556FAEBA70959DE8498F3FCBF85BD269A7DF23A3AD5704908978031667C7BF4A85D1EF42F3ED144670E6EEB5D8213DB43B0B7B43767FD4277EF0EC52B5718A7D187A003DE8E5DFF9C3A3CD520615FB9B52281506E5BB033818E0912980A8BCAA54E21C5630B9E863C83";
+ char testResult[512] = "3EC65819A084AD30712C4B3EB69CE130A8C7221EA3D8A9996D4BA6F298BC39F9";
+
+ // Get a GOST R 34.11-94 hash instance
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::GOST)) != NULL);
+
+ ByteString b(testData);
+ ByteString osslHash(testResult), gostHash;
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(gostHash));
+
+ CPPUNIT_ASSERT(osslHash == gostHash);
+
+ // Now recreate the hash in a single part operation
+ gostHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(gostHash));
+
+ CPPUNIT_ASSERT(osslHash == gostHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void GOSTTests::testHmac()
+{
+ char testData[4096] = "1450414E94B2CEA9E202B8ACC9C358EBA5334C20CF1B7D13E8B79BE63A0A938A340CF710D539262F406787AF7188990C7D75780C265E37750510FA6AAA742D01C753548219C20B1283CCA9D30AA5A8650D0C5EE63FE10268F9CD5996F8DB0158C6FAD147AE41C0E565F6FBC85115E17BB0B448208075D1CF79CF70574098E7116A5C5EFFDB05DCD83E71DB4860B3AEC2612FB9DE1B010229A413055724AB07F4131B04800286D3C4895A158E7B1301F8010E718C76CC69B34C643D2B1EACC00F9CD0DEBC83425256B2524B34D61EBA32FE5F79FE0A1F9360E3CFB4C88CE7CC3C36E969A37827AD5FD79BFAC08CCA1786F30F34ADC605545F04BA96CA4A4E3DF7FEC36E43406E9CD68D708CBAC4C54B2E18E38535BD1A8029FD7393B5462AB688F8146445295E5473B15B26EC129A24C78B7198D558209E827C38426D747FB0D2B04F1EE7B142B7B736EFF4B819B5420F4642E77181617BEC8074109B463F4C53A6F3507A0B4419B2D7CC0B6CF89FAA2CAEAC17BF19E6A94E0BF346D0F77C47EDB29CBD204483E53853401779AEA0998B993E39EA4C5003326C017A5A3BD0C5591D4F822641FAE9DBDF78B15DC5BA326150F89C864774A8DBF6464B259A29C00D9BCC63F61B3B45FF19E6FD0CDA2BE17608488B0E5C6CC5C596F035C8E580C30FC7C6FE2428F3509511B9D7FE77CF53C5B0E8E66BB573B3D467B74B5493A4E8EA49A79B7E2D36A6C0A600C6B13DC617C3FAF927B2CB251279CFF4228254CB6022AE9D97A36894EBCB305B179284E5D2F330266B2B600E248D3C4B8121A8D698183A38BFB5A40C5E85CB08EF0BFB0242E418D11DD648B9B84E072A70D3FBA8A9B0CEE05BFD71AC945543E306824F9A4DCBA05BBE0027B475A020BD764B53AA5A187C089A2DEF8F3A96D38491A61CE5F3DA625F7F4EF38130B0F5DAA14E2236F4CD95FF0C31E7D6C1CC15CDE7D9D4F95326AE721812458D413CD6C758671C9A85D10F7692CE31A600483F6444F45E74C45B7CF886E63D0158E19C0B87BE6CD9FC4B74D72CB004D3BD7ADF60E162F4967E5EF3BCA0AF2DD7ED1DDE4097B5BA250281DB7E46C22A25A49ABDB1B2D148710128DC1F1A18CD0D762A1D2EB5D5D602336EE3F0A0095592E938A79BDEE72CF801015AD5871A8D907298E13F960A1417FDFA87C3FE3DA9490B73B45326C3161D9DE6460E37208665FDC90CF894A0301198F5FAA5A315FC562B2837194662A58DA13065760571172D42306BB57ECCFA578E9C927C211A1F7C1983DE1AE1EAB0A264AFDC18CD56F14E0429E80B0DDE9A5AF527952A7B6ABECFCB64CBDA3C3E7A024FC5CA3B655FAF5A2787FDB22C1DD3160827C886A119FD2833DA87E60F18B6A969916D35F559BCEA40D6E5E53F84FA5C46DD5DD09D0802A21F64F00EA755F95234AF913DBFB380CC370754448E46EDFC7CCC";
+ char testResult[512] = "8D9D660D7BCAB705F14A90CB9A31F7B5206F9936E1B56F2489DA188A90C49CA3";
+
+ // Get an HMAC GOST R34.11-94 instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_GOST)) != NULL);
+
+ // Key
+ char pk[] = "a_key_for_HMAC-GOST_R-34.11-94_test";
+ ByteString k((unsigned char *)pk, sizeof(pk));
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+
+ ByteString b(testData);
+ ByteString osslMac(testResult), shsmMac;
+
+ // Now verify the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(osslMac));
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->verifyFinal(osslMac));
+
+ // Now recreate the MAC in a single part operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac == shsmMac);
+
+ // Now recreate the MAC in a multiple part operation
+ shsmMac.wipe();
+
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac == shsmMac);
+
+ // Check if bad key is refused
+ osslMac[10] ^= 0x11;
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(!mac->verifyFinal(osslMac));
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+}
+
+void GOSTTests::testHashKnownVector()
+{
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::GOST)) != NULL);
+
+ // Message to hash for test #1
+ ByteString msg = "6d65737361676520646967657374"; // "message digest"
+ ByteString expected = "bc6041dd2aa401ebfa6e9886734174febdb4729aa972d60f549ac39b29721ba0";
+ ByteString result;
+
+ // Test #1
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(msg));
+ CPPUNIT_ASSERT(hash->hashFinal(result));
+
+ CPPUNIT_ASSERT(result == expected);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ hash = NULL;
+}
+
+void GOSTTests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+
+ // Set domain parameters
+ ByteString curve = "06072a850302022301";
+ ECParameters* p = new ECParameters;
+ p->setEC(curve);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(gost->generateKeyPair(&kp, p));
+
+ GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey();
+ GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getQ().size() == 64);
+ CPPUNIT_ASSERT(priv->getD().size() == 32);
+
+ gost->recycleParameters(p);
+ gost->recycleKeyPair(kp);
+}
+
+void GOSTTests::testSerialisation()
+{
+ // Get GOST R 34.10-2001 params-A domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(ByteString("06072a850302022301"));
+
+ // Serialise the parameters
+ ByteString serialisedParams = p->serialise();
+
+ // Deserialise the parameters
+ AsymmetricParameters* dEC;
+
+ CPPUNIT_ASSERT(gost->reconstructParameters(&dEC, serialisedParams));
+
+ CPPUNIT_ASSERT(dEC->areOfType(ECParameters::type));
+
+ ECParameters* ddEC = (ECParameters*) dEC;
+
+ CPPUNIT_ASSERT(p->getEC() == ddEC->getEC());
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(gost->generateKeyPair(&kp, dEC));
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(gost->reconstructKeyPair(&dKP, serialisedKP));
+
+ // Check the deserialised key-pair
+ GOSTPrivateKey* privKey = (GOSTPrivateKey*) kp->getPrivateKey();
+ GOSTPublicKey* pubKey = (GOSTPublicKey*) kp->getPublicKey();
+
+ GOSTPrivateKey* dPrivKey = (GOSTPrivateKey*) dKP->getPrivateKey();
+ GOSTPublicKey* dPubKey = (GOSTPublicKey*) dKP->getPublicKey();
+
+ CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD());
+ CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ());
+
+ gost->recycleParameters(p);
+ gost->recycleParameters(dEC);
+ gost->recycleKeyPair(kp);
+ gost->recycleKeyPair(dKP);
+}
+
+void GOSTTests::testSigningVerifying()
+{
+ AsymmetricKeyPair* kp;
+ ECParameters *p;
+ ByteString curve = "06072a850302022301";
+
+ // Get parameters
+ p = new ECParameters;
+ CPPUNIT_ASSERT(p != NULL);
+ p->setEC(curve);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(gost->generateKeyPair(&kp, p));
+
+ // Generate some data to sign
+ ByteString dataToSign;
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+ CPPUNIT_ASSERT(rng != NULL);
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));
+
+ // Sign the data
+ ByteString sig;
+ CPPUNIT_ASSERT(gost->sign(kp->getPrivateKey(), dataToSign, sig, AsymMech::GOST_GOST));
+
+ // And verify it
+ CPPUNIT_ASSERT(gost->verify(kp->getPublicKey(), dataToSign, sig, AsymMech::GOST_GOST));
+
+ gost->recycleKeyPair(kp);
+ gost->recycleParameters(p);
+}
+
+void GOSTTests::testSignVerifyKnownVector()
+{
+ // TODO
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/test/GOSTTests.h b/SoftHSMv2/src/lib/crypto/test/GOSTTests.h
new file mode 100644
index 0000000..f243392
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/GOSTTests.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ GOSTTests.h
+
+ Contains test cases to test the GOST implementations
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HASHTESTS_H
+#define _SOFTHSM_V2_HASHTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+#include "HashAlgorithm.h"
+#include "MacAlgorithm.h"
+#include "RNG.h"
+
+class GOSTTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(GOSTTests);
+ CPPUNIT_TEST(testHash);
+ CPPUNIT_TEST(testHmac);
+ CPPUNIT_TEST(testHashKnownVector);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testSigningVerifying);
+ CPPUNIT_TEST(testSignVerifyKnownVector);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testHash();
+ void testHmac();
+ void testHashKnownVector();
+ void testKeyGeneration();
+ void testSerialisation();
+ void testSigningVerifying();
+ void testSignVerifyKnownVector();
+
+ void setUp();
+ void tearDown();
+
+private:
+ HashAlgorithm* hash;
+
+ MacAlgorithm* mac;
+
+ AsymmetricAlgorithm* gost;
+
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_HASHTESTS_H
diff --git a/SoftHSMv2/src/lib/crypto/test/HashTests.cpp b/SoftHSMv2/src/lib/crypto/test/HashTests.cpp
new file mode 100644
index 0000000..f02adbc
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/HashTests.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HashTests.cpp
+
+ Contains test cases to test the hash implementations
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "HashTests.h"
+#include "CryptoFactory.h"
+#include <stdio.h>
+#include "HashAlgorithm.h"
+#include "RNG.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HashTests);
+
+void HashTests::setUp()
+{
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::tearDown()
+{
+ if (hash != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+ }
+
+ fflush(stdout);
+}
+
+#ifndef WITH_FIPS
+void HashTests::testMD5()
+{
+ char testData[4096] = "EDB39CC3CB5E8FD23A2182FAE8781F4E8E8534C8FE10BDC7ACDB34C4E22E4B60872E51AD092950771E475FB97B05D6203A0D1B3326D9678E44FB40787D8CF16BD3BBE4D4786F60BD8E9766EF1C30B22301FA8F7232358B3C5BE644342499622A5153B29D2E5F8F509771E8A5DE3B3737D30F2AB035262B8D83EC55F683E9B62BBB31E2E1F5E142A13ACB9701E1DE8752ACD492A943C2DB57CF4035BDA9D0519B86847CF74DB2F43CC23016D88EF44BA422710C00AEBB2ABDDED89D92E4BD132CEB87581644198B0D4AF82F3CE161ED03A4E189BE8276243243817F91159BDE294E61400041537618703754C609709846C3EDAE6922B498D24FDC6B9AE702A034BB3A2C6C230E58EE5759DC84AD0B960B111153F6D619E850E36833A26689B4718719EFF3A407B77B0BAD24A17E29B6A29E9125B4CF0DFFEB8D0B03D533ADA43D1F20CFFE0A067E0F6FFF28510148DD72AE33D8B72227523497B84082B682A480FA3B2FE42AAFF49883DAA4DC6826C9593D38002D73FA7AA91B41E828CC34FF12ECC1452B73709696A440CCDF3E6116DA36CB7A01C9E168C3518304721D2CDBC077F4D4B7E8D1A59F954872862F72AC12CB16E33BED8EC3CFD912E36BBF4DA86E31F5F45BE9294550965C7CBC03518AD7C5637A97F7470EDD6E359E82815230CE03AEE9512939A214D017719E5F6B2487E3B468D50DC8EA41EEE94360E77E0EAA9C27DFE2C28D63B7699406E2E6620FE23F96584EEA04034270A2A44096B70017CC2CB197CE8DA3B1924D8D2E86FB40FF59CCFC78B3A4F543068F08C3406DEF52413F95B2BE2AD5DA1ADBB7D95F2133F61AD5518A1BEA018E3C3C0C154EAE56B0B0F4A8818AE47DC618D138245192D055CE4EF8BD1A75030EABAFD66E45B204BA6B123FF54D78F51B6A7DB9B08BEE93E923F9DE553EC0BE4B8BE222998BC792002005ED66C0218902E7DDF6C6D5043A8A9790E438D5BDE37791CDC0DB6C974638884270D4F379DF845281C5F1F8A20978086A9444779D59423B6CEF8175E0BC2C517FA921EC66BE3F11ECEE078553F610D5B65FD293E37717C0CB323A2760646AD56C77A4B96940CF5AD1154A642043E40788C2D367123399FA6015422F5EFEC851EF558ACD4BC31EF3D3EF912241A586E54B97FAE083EE45FBBBED74BC9E3887795FC2EBC5354ACA358EC509F4AB8B2967488D5E5B77DD44EB72E66694A1F490ADEB2848918531B6FA7216C51CDB507598F1AA0985626482D3546BEF5CA3BB409934D11AECBAD47389F2CBCD85FB4DD1A8A6F4D0C28920671A31FFC14FC00FC51296A6182D5A05B16B33232798F0993C78BCC662932E2F57626D639DD00E39B206C1F8A15A19B5DCA9F8B015611AFA47A10A30527F552A22574E15E3577EAD9C7B89782F82D7082D747B50CEFD38C6F17D6269A696F518EE6EAFE1E1EA96FB4D";
+ char testResult[512] = "7299FE513582D71A3B9EA1E9F45F95FD";
+
+ // Get a MD5 hash instance
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::MD5)) != NULL);
+
+ ByteString b(testData);
+ ByteString osslHash(testResult), shsmHash;
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a multiple part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+#endif
+
+void HashTests::testSHA1()
+{
+ char testData[4096] = "0583243FDEDEBF8C9EA4017808B490A2581A5A06B8C2CCA4F2259B7FABDE4BECA9F80C3EFBFEC436CF5F252568CDF55C7D31002456F6FE711D404F9A274037E8D55EC6C55077E4900EEAF6524C44FBFCC1C5C1C6AF962CE22106610A7C8DE7D725BF924B81EA566B952C8723E0EAFA21EB2C6E6F5528A89FC24C478C0600CB4FD482FAFF8507284C5F1E8AEBA9CDBFB3E71D77B775DD7C09E65049423BBAA70499450AE3B46703A4A44AE281C1F0341EDF0473B079C44E0F9EFB4C3683ED706E480C901A16E77B52030A7E46E31991131AED9C98DCA1850A4BD6F35DBCF5A894A8843EE656EF0DC617D923EB38426855FAA2E77E70CE9A8AC81D0F14259A748F9227F732420CDAE5A1CFEA9B541F0B12ADD5D966EBF66613D7FBAF5FFCAC8D625CFA536DBCA8E54B01B237211656F165A8114CD157E82870BCCE6AE8AF5334105B4E50B0A4E4AE5D0A3CC5CD8FF85F7C4D20D2627694B168CB48DB81B5B78C620C7559B2043C268F5D7351256D41FE892ED8EF6F7B5DD8E193EDCD268C55C209DCD0E827FCF76D6951CEBD0065826FBF044ED5818FEE4ECB99973FDB6826BF92488652E804C40D07D4CE43FCB31481667EE637721B91FD38331A98A6E8969D5B1D0690CFA0B500D72BF2D42AD6471FE064496C91126EFCC46B8CD093BCBB70D21FDE1937A888CA08DF3068A858280ABEAF71608BC9229E8E5EFF1814C4887E3A26782A110F347560DAB6B07DB8D063E8343A3FCD99B34C3C3F649096339CA7D39DA6F7B2E489A9EE6CE01C923D45C50350AC57247838E323F1B2A284606E45D60938A6F492545C5EBA0C7396702C0F4E77F36AC9ECE7ADD32FA4EEF7B38F9FF3F8BFB4E05F1025AAB52FB1B4777A4FC4B881EFA484D04397DE4312B7EE2BCEAD0ABAC0513D9C1819F59996AB5E94D48C098634D9907A4CA41B5A900F7CC299937B089A52C221333BF6B35242CA8D552A9CAA3BB18944D5CCEF69E752FA74A8BA3DD58159BAE375944B26A636457C30C451A58984BD6F028C8CBD3ED893ECD2F1536AFF3A97DB92C0E2FC93B9CC3837FDF56E4E3065D10B15F9A5A8925A5F772E4521CDC885180ACE49D98719BCE6770604C11E6DF090C199A5BBF1D695E1D55E2C9E135E89AB26446F6FED3FBD7DFE58EB75CA61B2D3DA4974908C7183E62FDD79C233387C78EDFF8AAC412EA36AD929808023EF04B8C9B7F980CC3FFD50E7356F51FBDC3DE8551C4F5B283D41E861E5604155E81748BF017268D4FBA8D253CA695300F5FB9A51190B24E2B17653519A3FE500B27DFF90A9FDF8404AFA8FAA1C4F738EB45969846E0A18693C06CA5FE2F2B5F7A33974A9453383E558317468B47DDAEE7A2AB90AA2446155CBF5B6473628C1D6BDA9044D4D96D1E3846AA7A65046C680BB173670FC04E5AC7D8CF41C6F233BD6945C0EA90958E9DBFE67D0EBCD";
+ char testResult[512] = "9A5BD96DC0CD3B0089FBB6BE7D56BEE638431F5A";
+
+ // Get a SHA1 hash instance
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA1)) != NULL);
+
+ ByteString b(testData);
+ ByteString osslHash(testResult), shsmHash;
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a multiple part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA224()
+{
+ char testData[4096] = "8F300FA699500CA5E1E22B38EC06B2EADCE7738CF6A55CB241577D53ED68BD017517C83AEB9CD3A25536FE999B7CD61D9E2BA85C39A7D27CE2CAAC8FE7C12FA1B2905DB85ABF230A813C1A72D2BD93BE0C5A79842FE35C5EF4B2E94524FB9594E3CCC63FE2A4E21D91C25DED832FE8BC9788697051C2042094585187394BD0AFD64FB627F3CCB350874FD0D454BF0254A72DD99ED211F68DC15B94A5682B73B89BF533746E8EEC5CCE45DF55466D7026A95A062EFD49FA270751A8D427095D38FB757FD4D1395B5DC7D302D9CF28C2E2D09796B9E0FC2D1F56BDE005FCD266B097822C170981DE2DB5E92582A612019823A3A062E228AB99AD6A0E47C1DEAC0078460252D83FA11253A3EFD374B2B392F0E27079F9FCACBB8EE6320C7A06327335AB34B757057E6C7FEC5004C4F675D2C4ACC6B359CC13D6F9FBE7E12EA7F6FF753CA8FB68059DB06D9804CBE08AAA55E0F20EFB7094695C1BF0D8E504EAD0836C0E6BB491E1691FDEB9ADFE0C92CED19A612DBCA01FF5A515E32B4EC06BDA00482DE721B6A85F00CAB264B34C5F3749D35603D0216C5AA426BBFF15637D1AE7805ACA572337232C27BDFC9D17D5D129242FD883E3C33250BA089EA03BD794C03D8DB9F57F87DC0A30E37F063B9C4C43518DC9F94E7BB18718D1DC79474CFAF60CBCD5CAA8AAA9FF573E26BB8B722C522ACF561FF34A0716FB7C1217050AD6E8323889B47D7551BC7554909651A9BAFCF5F0FEFD100D35B2E06D89C46E572E3EB5A07FEA702DF10BBCD2CAF2F2A62A9BC162F6369D0DBD9A6D6368ECDAFF4246DEE682C2B20EF4D7BBCCABBE0CD44CFBB531F2190E55C1A650B4D16DB2DA0453B23C4F056C1F791336A7266742976653B2E9377F500AAEFA1EA5FEE3469F4A85A484F69FBFFC1C163F78872AFB79231D9E5B4F8EFE2A9E8487BC33E4EC462F9E451BFEB306964D1F02873EEABCAB0F06361DD463398717537C7C255E3DEF1E9EC1567A600CFEB63F822A3C24B3524225A40F0CE948B0284AEF1F9BBE7618D18839725087DD6BFEE15653B981D6F57ED6685388F3B510140F437E93B92583609D4B873BBA3641B2DB56AB26D3DC27A85866D8F66C4A33D82932ECE277387E583BB20A689BE12B597C6199799A3A53B970596355A46F7F94B9D5E07B09B8C47355CE19D7D2EC1F1DA8F382F7C90ABABDED1D82C8BD673C008E16102025B8C8AD33832953B9E28A1C01353C513D55F4E38C0FBC1FE7C1FB6B93D10B464F851BFE26426BC09C599708CA1CA3413BC4B147CD69A761E688E3846949AC3F455CCDC0DDB4FDBC91D880B38C73B7AD4C8633598F4570E3BCBA3C5E785686E38D2926187CDF0479DF5B818EBDDFDA757C31DF009ED234B3C0F2BC1ADC700FD715AFEE46AE5CBAD02ED086912BE45BE2D61097F008E45067C4ADC4FDFE29220E6CF0C6F7F8";
+ char testResult[512] = "A4E71A239CED53E936011DF80B516A07DFF13BB5B05BE43C46C05CCD";
+
+ // Get a SHA224 hash instance
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA224)) != NULL);
+
+ ByteString b(testData);
+ ByteString osslHash(testResult), shsmHash;
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a multiple part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA256()
+{
+ char testData[4096] = "C75FF0C53CB345524BF9800FDF53CE448F3369F9CA08C817F8F07AEF0689274527F0AF1EE7FB5AE99B37456765F39880640BF6C5582111753758DF49A9A13B52379DA0C7AE930B03BC57CD819D2EBA0E38AD33D10876608B99A69D0A73F001065276055C4B659F62F77E7232B021BC085A2472293D2D1875028444902AB29D78C9919EC52B33C9F839B1F839C7FF39B68669C925F53AFC865C93D3694E2FD3F29FF0B7773BB412D0FDB1B506A4D501F840D01AE9BF18D7558109B10A6E55CD8CF9A5279D559810A0B08C84C2C8C294AFEC06C6219EB1647A51488BCDDAACE7C652BB0D3F1DC552E4B42BAFF52FD17239F4C08DDDA1BBA97D8D35D3A3DA32D66858B2D320A62AAA7C3909C3A34DCF9DAA69BEC13B7B3EAAEA8A56E2C6DB2507C43BE8990ADC4A281B8BFC6C76FAED50217F109594902FF7E0EDFF5C018B0FC76CACFF84FB9EA97D6D543EDA732089E82FDE3B9D087320014680E5EA2B21B534125806B650F3268DB7951460A9E32F2EEAAF69300E6F0B7F846ECBC2904E93E8D0423FBDCC3E34C5085A97636EA9961B00880BC381E37C3A6E3115256B1A9E1A915A401A8E507F97A09BF3881E852FEA614DF76D709DE6DC0FE54500E0C42132E9ACFFE4A4A98654190FC6C14FC3E5F42CDCCAE0DE05DEF5F6961D7D13DE15376F35142C5846013B7D4A8A6AB363EC7932415C556B83787C86491820AA29C2FE31E39A3D73D710C490D1AF863C4166C2301ECF6967506DCFF6F97CAE63245634153072FE27E9C4B5F90B3C42E4BDB4FB0E85A548CDE2D3B480ABFB1ED6F054017B120E41529909AC055A9F5A29E25D0E5D1A8E8550B9C85C300BBAAE030B22BB646B1FD3A90FA1C242A26071423B3E239EF65BE8B347663B6BF63436AFFD311D10FD24C8E8D05CA99A808C41E6C9C7B283FE5FE9E311642349D2799B6D0CACD5826CC6CC5DDA22FB8BBDD6C66BB722697E4558A75B6D24FDD55631C17FCB591CA3CBA180CEC241B0555A91DF4D47A648A7D901B02C1AB557C4E1CF33E277AFE008D586857203FD6CE695C8EDD446F74056B173D6A0B07A2A58B39366B58BB76AF96DF9C37A5A5E1F8419163CEAA304D451DC38B8F142C422FB475869667D55D88F7C2624FC0B29A958BB4A44C6B0439542AAB02319D46B7E482149DC9A7C7BEBE651C7E8404140601CDB3742F58B6EEDA137FA083BA9D297F91B41B34C3535230841F18B672ED0FD817B7E4E3CD1FC018CDA63C21C3C3ED68228DF85B8C26572D1B14EF10D5D0BAF6F3ED4B9A8C3DFEB4EDEA00CE2DB5903D510432BCBA791C1BBDD2770F2616AF855941E1BD710CEE4F17C4C7A9E283B12DE901A88D634E4ADE69ED529328D64F8069033A6B4DA5D8E0E1C0150DB862AAD54F2827B41CE1F21E3F890033FD46E438615DDC527D6D1260BDB79478D6A0BE2B58174648A2387E3AE";
+ char testResult[512] = "3902802C215A5271439FE3E81AC7F21DA55545F71193A8DA8BEB0EAC8046A43B";
+
+ // Get a SHA256 hash instance
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA256)) != NULL);
+
+ ByteString b(testData);
+ ByteString osslHash(testResult), shsmHash;
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a multiple part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA384()
+{
+ char testData[4096] = "11FCD8770F582C2D9C860D1EB4FDBFE40C551C6F3AF41A2540A39BA3A121BFEF995F1727A8703C29D0A44EB85B339F27955E1C679796A72980BB1D1BEF4D51A73174A983D36CDAD56BC1EEBA5DDD642094996531EEC94DE2FB6E0ED4F23BCB2F1D0B25505EB16306473DA17F809BD994FD9A737D29819BCCF94CA225D2EBB9D89DDA6E03E80A9DE87E44B72EFD397F9F344122B6591CED9BFDE8C0C42D8C17223A93F33B7D569291F91B619297F233C1454A168AAE126E89B0ED32B0B69AB095A1BB24BB7F1AAF8EE0BDBB43025EF3339F96C9EA352E78BA0661DE896E8F4DFAA7EF623F2B5305AD338448C5FCBDD6CC1F1222ED1D8F4C634B82591F8906DA8DDA9A0FFB0F1499B5BD08239F7EB3A02ACEC60FB76754D0AC5077C3B733D346F0BDE654CD612F60E2284115297A1557679901A911C2AC7323DA2FF3CD57895D7D181AD43AB7068609CE046B96B445EA08CDF50C40DFAFBA9F7082707A813B9C8E4E9D7F0230D5AFE40174693512DE96E3FAB1C8F6548880823645A0AD811694B293F788D0D523EBD81851594733EF45FC763B956044E29B29C195BDB317FBF97F41C601A2873C25557C3149F648424380FE79E4DC407A9CECD8F14B843C642FD9921F12786C8A1C6F8514C99672038693C5CF1FBE91F903E4ABC9E55B967B2F72FDF1A2EC09C14C94C001BAC47A0C36E9E6F34431381069CFD64D85F11285391A4DC7419B2EE8062F344538413E757EC258192B90F2CCC1186AB9A4ED5CE1290644CDEDAF03A4BF3E94B9F9D132ED159CE03586C5A69EF0A471146378BCCE799A3CD8D627B688BB28C9288F44D1218BC34A05BEAA398371ADC60CA8A2557AB69BE7B737F84BFFA93A1E1115F498600F52144E0D61055A2FC0CD45E20962CB2FF475896D733C74C2E95986389ED74B1497A35E73FEE0F36270CC65D76C1FE27A35E8F1FA0C5CA7F2C6003E21BD6677502CE268EB55B16DA863FA291AA111F338F10592AF86DFC297718365C04839748195E20A64BF42020846A46C94F1728549B8310A7FBCBA2C1441B033639CE52B6DBDA69F6ACC57F2DE6BAC57755734AFE4B77869C4D9B0DC56B115476A86A82F816CB148CDFD2B1DCCBEFCD4559B59AA88C6429F4A9EBB43B641144752A5E6F8BE1B739AA69FEBCB8D7439E5D917CA759982146E627FF81E80CEBC37BE0CF2A6C12A3E84A389FFD25013C491AE90A395D4DBCA81340E86848217AC426603CCAC981B5ED701CE9AB2851DC5F2ED72484FE99767C0FDB6F122B0C67926A637B57EC4F047804BC3A9BD55CBD78B83154BC27B6F8A66085EF02A206F329F3B1531ED657C75E29DF4276070AE5054F484A12990A9DD13C112FB6D3D57AE42E6A048870FDAABA48F73E03344C0E13832BAFCA2AF81AF19E5C28983F7BAAA5135803E78FBDDF7FB53C9B9B709274F05C774C77F0B84";
+ char testResult[512] = "753659D55E4198325A3FED0A35761EC45038E8963B7525BF00D5A6A5D904DD9FA3FC80AB020185E08B14992ECC36A744";
+
+ // Get a SHA384 hash instance
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA384)) != NULL);
+
+ ByteString b(testData);
+ ByteString osslHash(testResult), shsmHash;
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a multiple part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
+
+void HashTests::testSHA512()
+{
+ char testData[4096] = "B9D5BD978E1B4A0268331AE4F0C4494EBA71125ED75B9B4244407271A29D93BF5BA0D6641EBF7A210A0905B5EBE675F7B900B89542D0DA6A3952DF9DC5430ECE31F4A5834CCF132724963A088DE43966DC9F46011F2AD458E8FCDBA18F6D183235687A6145401E9FA2EDF60F47F3835D953B5856B1F8308457D9CEC29246DC51F5B42BD5DE38BD89945667579C05756D1C47BB58C2C3D049C58C014C1F6D962BF5EBA1D273F5A7FD6D9291E293CD30B8D8B489E79E54A7A11953EAF4FB6AC7F99910ECE05B511E098B6AD33A599F5A8FA43692FDD9F2A26F316427A2ED1F231E328864CDF9BA2879E0A711F48038E653520C74B7EEA8858F17AC332B87EF4C70A838263C8B17B373161A5A15293D1A7991F0EEAAE0BB69C95DEC22A1CD6808122489703770B5E276735F9D149067A7F3E6A7D10A790253C81778BB79C06D1F98A2CA9C2E8C4BAC0A96F0F9736B85E7BB4F090C5BEB25F087AC037517A9599D94E072D03D9C48665DD17649E001E45966AB8F2C7D24E38AE4F0519F056B034E0ED2CA133F108105BE4823758543791225144AB0B9609F0F861B69EEA8707D6DB9046910F28C6F8E1D47F59DFE9B59F81242FCBE5A71669B90F7B4050E517CF6D3F2FB8759FB7300F12C786D36183FA64692F379D030D0EA90859D9D8E00F27500B41FD716E325E695E3D8EBB40A4E32AFA75F6F21013C8A3261E9C18291DC99142FFF91EAB6C2B55FF5DE03B1DCC88C79635B96F13B66CE6E26A1D5F6154F3C6E5F22AF4B0334FD4521AE57B6B13E2D3B777AF66742635740ED4FF5FC752B908A079A6BBE8499344096549E6FC6FEDBE57AAF2992E7CBB19931F43360415C39D65D2A92775C78DE97C712022460E48651EBDDB9E0527C7EE59F6C817499100C11E884633DC66EF85B176D7A529894CA8F364F559D97DC7CF1769813FB36F8F738E77354C14A560CB98DF92BB5BB16A5A3EDFB75CB78A718C070BE5D37A6F742F88B51BC633FA9E309311BCA908F4D5EE381FB593B7A53E4CE3A529160A2965D0C4CEDC6548D036A1A4FE4576DA9D35E0CDDE9567E792D5C77EFAC17E531F402E0BE99957A7D378E90C009F3231FEE6E3898B5D2C4291EAD396CA748AB0A39469B921BDC5F8066AB7F0D28EE0C502EBC95C2A39DB4241886736F17DE1F33BD384EFDEA951BF775A0D41A499E85D0488016D7A281A9F7C715EBB7CD6AFBA59C1A93A5AEA66D71C3058C5A293141EE4D2C3E65853EFBEFC55912F5C08B9990A66C313F3199C0769CDCA711E877766ECA773EF2FDBC0656B8427CA6442062D911B13F1C2E92D3F0C608B1D8F12914953720021D5648364F953F93CC49946E44FBAF154A2FE3A8055922F784FF9B56D5FAC35B65266A248794101C12750DB8C107D048E551E52EB3952CFA26345B4E21652F5F3B8F85DE04AF9731B75C79DDBD6FE1A5";
+ char testResult[512] = "E1483A8525CE39705D14D60D8B19BD89087AED5FE6D8913AF8FC3F6F4EA2C1BB5957E205294B1EFAF20AE5EE39A9522F38B4514C3C15ED70BCBBD5821E385F95";
+
+ // Get a SHA512 hash instance
+ CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA512)) != NULL);
+
+ ByteString b(testData);
+ ByteString osslHash(testResult), shsmHash;
+
+ // Now recreate the hash using our implementation in a single operation
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ // Now recreate the hash in a multiple part operation
+ shsmHash.wipe();
+
+ CPPUNIT_ASSERT(hash->hashInit());
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(hash->hashFinal(shsmHash));
+
+ CPPUNIT_ASSERT(osslHash == shsmHash);
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ hash = NULL;
+ rng = NULL;
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/HashTests.h b/SoftHSMv2/src/lib/crypto/test/HashTests.h
new file mode 100644
index 0000000..dd6566d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/HashTests.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HashTests.h
+
+ Contains test cases to test the hash implementations
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HASHTESTS_H
+#define _SOFTHSM_V2_HASHTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "HashAlgorithm.h"
+#include "RNG.h"
+
+class HashTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(HashTests);
+#ifndef WITH_FIPS
+ CPPUNIT_TEST(testMD5);
+#endif
+ CPPUNIT_TEST(testSHA1);
+ CPPUNIT_TEST(testSHA224);
+ CPPUNIT_TEST(testSHA256);
+ CPPUNIT_TEST(testSHA384);
+ CPPUNIT_TEST(testSHA512);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+#ifndef WITH_FIPS
+ void testMD5();
+#endif
+ void testSHA1();
+ void testSHA224();
+ void testSHA256();
+ void testSHA384();
+ void testSHA512();
+
+ void setUp();
+ void tearDown();
+
+private:
+ HashAlgorithm* hash;
+
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_HASHTESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/MacTests.cpp b/SoftHSMv2/src/lib/crypto/test/MacTests.cpp
new file mode 100644
index 0000000..8a3db1e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/MacTests.cpp
@@ -0,0 +1,687 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ MacTests.cpp
+
+ Contains test cases to test the MAC implementations
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "MacTests.h"
+#include "CryptoFactory.h"
+#include <stdio.h>
+#include "MacAlgorithm.h"
+#include "RNG.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(MacTests);
+
+void MacTests::setUp()
+{
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::tearDown()
+{
+ if (mac != NULL)
+ {
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+ }
+
+ fflush(stdout);
+}
+
+#ifndef WITH_FIPS
+void MacTests::testHMACMD5()
+{
+ char testData[4096] = "B64CCFF0DC038F4B4B6C77677B1E89774028CFB6F94EE920ABFABC8C389F7DE287D558664FD05836E854458940A486A367C9B771A7938BE7DFFF2C695BB99CB96F946707FB405A0FA94116FC4002FAD47F813C4DAF6F39B579A2C1E607AF0F80E55FC6742ABB46CF25EFBAEF820DACAE925532E0F2AAAD64D23D0E5682DC38FA47F230EAA299C4D87EB76D45D4B4A08BB47AC873A428708F9D236CF9B11831BC713DB5C8F58A4A4DD228B7A370154CCDB92420B01D0B4141B2CBF05E51D364F7A4D7EE20F1299A697AEAE7341EB6C2F5C458D8AA9A33CE6B2C87B42A9C8EABB3A3311E3828935B8743604895A37D0E9717266872B51CBAB50E9399A0E54457F88DB022CD1859D704FE07C2B530BE14A11072133A9D3A8CD94FCA2B22A320EA08D0292DEADAC4BF705B2CDF71CDC13EC72918F2BD8697BA42AA0AAD62E2D549AC639095EFD2EF606414207CD3770A14FA14AAD7EED197A1A61EBF1FCA89CFE2B69E709C98F4299CF6E1DCF34A98F3C89C6357B5DCDCB335C98EA8DBBA64700EFF9B79CCB875FA49C0C8FA8AA98D6B7B83C3818C4078A8433EEEC71423D9B476029C190ECF1552CF59E1BB2ACDB08663FA792D806E5FF5A6D3E4E09C3F6276663A09D5730A9AAB456D4863F2EDEFEF156A7809AA16D3202AA03C64359BAC628EA1D9ABE2D99999C2891ED49C6081DEA6907C93C5873B4D7880DE271D6016075AFF330FDF221790258A99564F1B51B979DE7997F5FD6676F679B4B14222753547C06960ADCC287EDC29E627FB88BD0E73EBC4E631A58DCA425FADFFEE9DBA177EC182CABA803EEE16636599A88C39A828A5FB206F6DDFD6023F560A421FF3D93B6C4A2A27B78283280C2FD5D249C35270EAE8F8947FA07189BB3A03184C1D8DDB12038184C467EE7DA6CD62F1775F316BE3C2FAB947D49DA19B480E8E4CB4C7818D7769351107386311E5EE411DAC5136869C147DA8E782FA60ED69B13C2DE18CF11FD75CE5F8F16993A026FC3441EE3B23DD6002B8F015E5CC336B5559A427864338C098F4857AA40399916614E061BB176AE4457CA72625A37F08F179A14C39B065CF3283E9425355B6504784C0F4FC1D7932F5C14B43A9CE3604935DE695CDB60B1ED58BD71AB540EEDDF9337B0743D8E624E1A932A69FB1FCA21CFE7F6D2FFDA78F2B8D5BCE01C59BC0A3981BB3BBECF345F43ACD571432B742F80491B490FD71F947480FF9D215EC21237F5AF28C31608DA7A6230CAD24EA799506C8C0B1298E9FD09DA496C6B63710920CC0DC14C00944A7D9B9B751D741A828AB35A5926D3653D45531A4D233DE198439D1946633FF6B91DF0744073CC6E3EC3B177414D8ED2AF30515D8688914667F507667776634A2A11BB68F65B363BD56E8CCF957EB4BB0147862D4C17268AFCE5685C8346E1917B8E8618D3888355CE401AAC5D2DF";
+ char testResult[512] = "1026862877813E17E4371095271E1B56";
+
+ // Get a HMAC-MD5 instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_MD5)) != NULL);
+
+ // Key
+ char pk[] = "a_key_for_HMAC-MD5_test";
+ ByteString k((unsigned char *)pk, sizeof(pk));
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+
+ ByteString b(testData);
+ ByteString osslMac(testResult), shsmMac;
+
+ // Now recreate the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac == shsmMac);
+
+ // Now recreate the MAC in a multiple part operation
+ shsmMac.wipe();
+
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac == shsmMac);
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+#endif
+
+void MacTests::testHMACSHA1()
+{
+ char testData[4096] = "EA9E200DE69522895F516F1380536406D205D72B31ACB902CC582B12696579826B5AF47892C4831D8AEBBAE039D87F82096364782B49E2E896AB8077E773AB61E05A8223BF17CBF37AB1BDDA70C9B10D9943AF4109571ECFB029156889249B309EC45A34E2D701F1F4093610A7064B69E7FAE5FB39E39EEF3CAA9D64E50DA8822DF4C8DFA064B165ECA4C9CD2A6AF1A251A1F5D4004123B67A7CC3FAB7462AD43535018479BDFD24A2C4A1C4271F907E40E2057A6271BB2BC9740F753CA3692E7ACACE547E64B9FAE79A96DF3DDFCDA7FDCCC7612E41B0B9BBFA3BDE2102F322E8EC42DA2679531782920FD2E7385F6AC887D578B9D844F6A7288EDF613F3663EB538DBFF14EA29AC8D2F58C703303CD370F55BAF02532A0BCB2F80673F6D84B04A5C3EF9E05B640B4CFFD903272089B9960B54197CB5D10C23BAFEA72EFF79C65E0EABEC628EEB5850AC4A23DC80E857EBA5EC5EDB9DD0A5F391B7F8BD354EC976881C157BD5735AD894F020164A9DF214150C5788BC1CF73C15437DBF21D791C75074DF4B51B5C0ABDC79063AB7B7CEDEDC6412F9FB1F6CA171BE6814E033F32CF1F08236A3DD657DB96CCF7A35434C4D0ACFCA81546B4138A6EF6987A874111946010F78074E69BA83E3F395D1C239A122B259F48140E4B80157738A5D443E1762C55EBB67791D5297B3E900B0B53CA7433FB61D2D03C3B34772C5DF77711437003C6DFF4B03DC0B713491F526F9AE3260F903EF9A1BED641E1B262103D395ACAC3FE6F6F1436F0CB3A13AC69C60101EC394DAFFCAD8EED23893C4BC30485FC68854447A9930C0F4FB9AC5B72EF6512278F09F5A024C7CF5C5617461751CE193E54051AE93DF136725642E1DB98842BAA8B8F6231181F0BAA8393FC2EDB7CF0832BA1FDB76A46C8059732B7492711AD1A12BA584D49885E263789E27664B3893EF2DE5C010C093DE1A735D806E4D48C36A0995EADF011FB50D0CA97AFF26B4698524B9F75386897940434A0A38EAF513845BF0F024014001180C651F76B9E0ECA6499F177A1079395C1785B856D5762550EAD2B47B15AF0A6BFBB1B597E72B9E5E6F61769C27AFC29E4D8A523C89D1D2E5E59B57DE89BE04BDC1DCDA0476A157BCB4DA2F7AC0CAF9351772652E2E5B6261501BDF42C23EA9726CB6C258EE9511684CFEECA1C0598D372808002E250EDD4019F85630FD499C35016B8A99C6BF78E69053B4AE7BE6B84009B505594603B363037212DAFCC669F7482995C74A7CC225245DC2E7D4CACC8A59F67513E1D788F0218DA902F440CD2FEB6C2A90A653B0C2DBE45CC67B47863C1090F3F41AFEA9C53CE5C61A7E6B7212EE3BBE67ED91EB1BA006A931055512046779935F84D7CA306C7F9F3894F91F51EFF6005F5A8BD9DD8828BCEA1C4CC6E5F22CE7F14C0A942243C1205FD7697F09C333AE0B263";
+ char testResult[512] = "C2FFE4BF83A6FE299CA4A187157F2442EC1527CE";
+
+ // Get a HMAC-SHA1 instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA1)) != NULL);
+
+ // Key
+ char pk[] = "a_key_for_HMAC-SHA1_test";
+ ByteString k((unsigned char *)pk, sizeof(pk));
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+
+ ByteString b(testData);
+ ByteString osslMac(testResult), shsmMac;
+
+ // Now verify the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(osslMac));
+
+ // Now recreate the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac == shsmMac);
+
+ // Now recreate a wrong MAC
+ b[5] ^= 0x28;
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac != shsmMac);
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testHMACSHA224()
+{
+ char testData[4096] = "83E369A9F34D645B7E1F2F7BB676A4DFD36C411D5472A9AC6F3945EF5C9A561BB040C38F2F321C582882820C7F44D48CDC5BB84F41818F4AEB226F63078CE131481D26F26C61EE52BD1BFB60EDEDE1E03A8656E87D5662EE0C0AE085E56E488325512467DAC43E99484A16FA419D6704922C1ADE06F7D1188DBEC88384CDBFDCD2E74787AE247A8027EF60383B3B0A7D0D3ADA95BB3AA5F0821AF050A9709C75673F3926CF9AE029158D684F470DE3EE6B00BBC90F85CD6E634E86B67E4D8EB4251B472B02D167790C6E6C38BA9FE39880544EA66EB4C0BFF8AFEB9AFC40ADC24DF191744482F70793CB4A802CF1AB58562CC26D1CAA2E80375BA45507C3E9F7D99223E0E7FE93CAC58B7B0C69231162D2D7DA75EEFD59452642CDC5AA4A118B6D4AD00E8368A44988201C6286CAA8612BCFFF714855DE1E053AFD2EEED9737459540E45AEAB26999C0951228716AF02F0D35264E3411B03D222F331A4695D6DF4E9EE35D5B1015FF0BE46081D7CEC9137824217A711F015639BE76223845F1C2A25A10D29B637C5124CF50AB0CAA1E33D75843D00EAE69C3A189D463377731C3197BF44523936C4F84F143759E3D58891F7B3B51C858EE29BC1DF214AF09C93148172E842A7FC0078D4E106324AAF8862B845F290FE831037B2EFEF2528DF070DD7B1ACD67762CF1071B96FB95C5AA14F7AE13103AF45A1CF3C42C5D53CB5B954F97BA223E70E0098E224BEF8F5430D027B510DFBBC35EE5F9170E4A43BDDFCBAE8B82240DB870B6C7C7E21E21234EFA62F1582A9D150CCE1B8822BD77ED8288B20883AAEEB5BDF9D0EBB8D3FF47DD51B99E9BDB8B8A87D0536CC25D4939ECB13F7B4F7DF5F0BE8231CF3F53CE52D16A29825739B26BA4082975583967180F787ECF98AD956A9CE53759E20960752938C142DF80E57DDCA236A1F596031942016442002683865EDB210073797547D83CE77D3D6C39E2B9034E685BD28D365992E821BECAFC6DF2B60EAE9777FEE7879B176CC602501BA0B0BCB434DFA5517F8D6172647364F235B3C9BA0B1B90FE0FD67CF6650C2D8D2BC08D127DF0AB887F69CDD81D03B4CC7F44A4362C90BB38556D081E51EABD9CA3AA6C877C42FD1B001C030D0B281590696B5BB9C6A78CBE356F7AC72F525300FD13E24755294712DDF48D1AD19F844120306DC99D8CC18516A23BD022CF9DC9CACC168ADDE1C15337F15B3FBEDE4BFA498F2F963E14B7E66CD737A5485227BA1BAA7668D97C58DCE40EE7A843A5E6EB591FF91D6A6292C8A3E95A0B23C1F0B8815BE526EE7C49B5153264BC1207013EA85E9DA37F19BD50DDC9F0A5B9AB4FCFFAD2840B5A8856882E8DF95362DCA13C15328137A2A8318884FCF4D05236CEE9985DB1BA873A9AF5B33E317FA2C0CB94E7C18E46744A374C19D8C9B2788FE50C9E4D237D290555E1077";
+ char testResult[512] = "4B089658FF932CA07BF7C42E6EC46BFF560BCAF295826D9D3C0BAE1C";
+
+ // Get a HMAC-SHA224 instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA224)) != NULL);
+
+ // Key
+ char pk[] = "a_key_for_HMAC-SHA224_test";
+ ByteString k((unsigned char *)pk, sizeof(pk));
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+
+ ByteString b(testData);
+ ByteString osslMac(testResult), shsmMac;
+
+ // Now recreate the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac == shsmMac);
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->verifyFinal(osslMac));
+
+ // Now don't verify a MAC with different input
+ b[600] ^= 0xff;
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(!mac->verifyFinal(osslMac));
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testHMACSHA256()
+{
+ char testData[4096] = "FF7E669D7764FABF6E3550E192E660DF1EE237B49F9473D757DEFA1400534F57C81E8B0E99458F74E6F57A5BB71A50D1EF61EDB3B3FB4BCA57896DFBA50C6C55B04D4C8C804DB8EB2A273E25F49AE2742D2AE430BE9A3A07715AF6816E818B63BB1FF8C876A921CF931F693E624CDAD4B54F3ABBEE4A09BF39E0FE3A313B20CD3A36B0EBD677D9D4D7C576B5EA244CF0436110D9D66110C95BE187D6EDA1E81A4456231BE32A1B5F4CDC02B2DA679322AEBAE0B795763888F07F0222ADBF824F31AEC7B80625DC36DA1F0C3DD20C6E8F79A7FA2D286119894E611EE550364428723E9C33A573F18D02F9DC90ED215EF08C95DB1CED68DA864732BC9A56B8B191815BCC12075641E3E87F46EFD3726BC1D6F47AF7BC573C554279C041C7FD5E924093241855507EE2A837E2CE62E7A9898712EDF593217B6425B3EB855D53D31F38E5A0736E34844AFCAD58A15B06D357697DC921C2FCA77091BFC207B0B4F1FA94F923B05817211462104287B43CA72986D9E6E393C9A075C267B2C1706CAD136E9F549A83E58315DE8D0B67852006EFE8B6E0773519FE6DB316EA596E1998B79C19152AADDDF8E025E7EDCB16B5CCBA2C9F990605A6969D3C667D6EDA1DA5AFF476661349712CD73F707BB0FD6F8BF0C13A90DE9C1C5CE9FB696C22849C1205C8435C818E2EE03F2235B502E0C24068B8687AF9ED065910535072DABB83F651FC60E005BEF909F6EE308B37E43DA01366C062168007D733D5EA4A610D1307BA087E8F883864140BBB02E523997A0D83E9BF289B8EC9F83F57FF553485409B0D82E77F32BD2D06A130103B9F3915730EE8BC3FB099B74AE8B32C478A83D0BAD2281C279D6B802F42A80E179F4ABB69AD485BBAE348C6F774285870F53699500CEC045B9521CF22826FAFFBC4EABE9D856B28DDBC6D2A0F318AE9475E82DE2CA6704B743397EFE45F825019B58D9E671181512D780B1BA34D059BFBF8B9B232E337335C1045682635CEF8D3CB1C744D3A7791F5DB323EF8DE768C63931266EAB0DFACAB0F99BC9C5DA234FE48ECDB23A5FDA2E92EC10AF7476B07C4BB85BDD0600B49F41585F9E0DB2B276BBE0FA7C5792B65012B6564561E4814E8D1EE706935A45F969C9AA110A630E354C7243E21436A180046605FE5D31008045A5C4AB4FF5C23585D77D6C839875CC2E960436A3D90F9664D5522EAB08867B95F9641DF0C81D59DCA8ECE8709A3F521532041BDCF7A7535F940BD3569FD2145A1B34E955E04F66E0CA809BA3FA6A347FD0CB69DADBA93DC03CDF547A96CD3159ACA61EFE20F9A566316BB9C746EB851CE51F04823667CDA0D898253BB10C1C5220B2C30461A49C5FF0DEC38264786C6125720B3768629ADABCF694E01795F618FBD0ADE5C91CB5A981BBA581A9664F51DF758D7300E081E57CE20C8A7210BC3558AD240B7";
+ char testResult[512] = "90A49F8EB80D8ED405EFC8D658FCB9102314598939DCAA090756668056B0228A";
+
+ // Get a HMAC-SHA256 instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA256)) != NULL);
+
+ // Key
+ char pk[] = "a_key_for_HMAC-SHA256_test";
+ ByteString k((unsigned char *)pk, sizeof(pk));
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+
+ ByteString b(testData);
+ ByteString osslMac(testResult);
+
+ // Now verify the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(osslMac));
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->verifyFinal(osslMac));
+
+ // Check if bad key is refused
+ osslMac[10] ^= 0x11;
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(!mac->verifyFinal(osslMac));
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testHMACSHA384()
+{
+ char testData[4096] = "7D4C4274CFAFABE3605DE7E35B43F10251A441A6F4B03EE142B9EAE3DEC2E30E1A47FBE779D716427B108CCB2A2C2D7561B879B1C021E00E0498D91859BA3E7851EF3FC25A1BC6EADA8524EAEEDCC0E752AD90DFD0EA2F04B71B8ABF56DA85E4D070C91EC4B7723A02C3B52DAE31EEAF8E397CC3E92FA31E5F3292D8C9F45D459D8D1105E539D3979ADC01EB4E0C90BC33351295628BD0C2E1B4B13764EDD66BE9AD67AA7B4A7780264B0A3DBE099B190D25649B692401E0B758AB2A281B2E1AC9B4F7EE051C1B98BE92463F314A86A7FD40A4683A82457699F514563C70F1231C0B667C7B8CAD5910334CF894A9810D7C7C6DFC1E904D8512813A84911580C2AC56BB005A4FFB512A1290501AE795C832C0BF7DEBCD9B1D84CC0BB5B5F19D02FDBAB01F7B7CA47C99F3CB7D4F0D35622C267EBDADB2D089D0DA73FEA15A25C873C27EF72A84F99EC4E6980695BA6468B34B5AEC0746219468FEE88277739123FB51CEBF264140FFF27B94D6F751F26F0BC27387A2EFD038EEE43013AFC8FE94BE8E272B28ABFE2160BA81416113CBC2A1ADD96DD23F7107F4771CF2016501A8918A9A71C476CEDC10BB355BC144C818FD620301793CB16372A80881C5DFE387619ED651626CF44C8EDA8DA5BA8A6895148EE36037D4ADDBC13C5681935EDC5BD9B35F8E91B84C1F593B3E89614879CAE4DF4413E13655079F3CE21449CCA19E0963C925A75BC294F343016518D2F8FCB13ED38D574232602AD2416E94ED7735680439CE042145552F352156FCA722B31BFAA289C3711F170A845143ADFEF49CA53278358A7FECBD605AE9899192990D728CA37218B65DD9978EC4345100E174F3D04A0C8A5611263DABF7DA0BC6CE50BCD338830688B697FEB71909D1A2E09B62C5C4A8C1069C50C8DD6A432ED2B429F6BBFC304D0F0A35167BBDDCBC7F78959058393BC812820AF4917C56EA9233A1567608534F93857EA783B537CE294B4778E4B5D30D5836AE1F0D25B663A62512D2488E959D7FF000F8A70F31CC4CABB51D6F57A842AEABD707122935690F78F1F8BD7EC8544F1E70B9D6D53C50632F4DF5F0BC75630B427B28BAF2249C72F5864A3CE17627BA4F16F8FF13FA19DDF83736B171C024C95EFBC5D90615C495C2B02685C24C6E64E19C804B1DC138B5BC52A6969C4332F6113ED8C38F03A0107513C611A6FF013D2FC0B00859A6A5DFB8626002EA0126D477B5F9C7B5BEAB61A13AA8841A4C11E9DFB6A7164BBC2D40E940D9D10C56D58FBC76B92EA68425C2FF48BAE0CA2AF6F1CFBFFBBD855688C3960538E2D87088472CD73AB6D0FB86D9411310F5311EFCA3B89949A87D408B86B96C29C89A0180AF8957944E2A385A221081870CECC995FFDDD6994B0856ED0DC6303F7FDE5072F0B3D68BB132B0C5D3113939D614677720186052F4F90DD60A1CFD";
+ char testResult[512] = "AC387A4BB1E4E078C43C69087C206F49F56EC63CE244A429DA56B8EC3CAFBC987090DA7A8F6470874CA6049D20AC5154";
+
+ // Get a HMAC-SHA384 instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA384)) != NULL);
+
+ // Key
+ char pk[] = "a_key_for_HMAC-SHA384_test";
+ ByteString k((unsigned char *)pk, sizeof(pk));
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+
+ ByteString b(testData);
+ ByteString osslMac(testResult), shsmMac;
+
+ // Now recreate the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac == shsmMac);
+
+ // Now recreate the MAC in a multiple part operation
+ shsmMac.wipe();
+
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac == shsmMac);
+
+ // Now recreate a different MAC
+ b[100] ^= 0x42;
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+
+ CPPUNIT_ASSERT(osslMac != shsmMac);
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testHMACSHA512()
+{
+ char testData[4096] = "A7A3B0B40CBAAB9B58F6946D9D15870B56E6832DECB708949EBF98DC4EC9C0AF477216C542A98A3646B6ABB72D89E6B3F18201CC75E93B37C2E8EADAD6827FBBFFD220642A92CABB587B27590ED204F8B2C926777C3DC9E5273CBB38582C103905C074002DAA2D8D16DD907BEFB4C51B49C464FF22B93269274291D1254889E3F677FBA6929AF472AECC02DECF822EABB2F05311E0BA8600B58075D4E49837F81C9565E37EAC96B9C2F3C08E3D818DD507D0CC8064C8CC7553D5A17204F4B92B74E5A441CF9142ED059DB1ADA76C799B10178FB3E76E4E3CAC6B1AD8648D522DCA6C93200E706D947E15422E1CC47742CCBF8E2C1E50492AFFA49BE22D5E34B0ACA62744626E2EF7014EAB17D8E538324D9A764501428A53593D23E3785831C1262F220883E2DEEFC66584A3AEC1F35998F842C5298A5E28653CF40F21C6E2383086C266E2902272198D45B38308904F5D2F614A6857E027D133C5455E75B16B9DB124755ADF06B16F04872D74D1A90F36709D8263B1190D625849F017930763AC1EA548DEC56BFD46D09F32D6ABAE96A778B39FBF22B1D6B3CA43F8E7ED32DB2254018FB1999ED0C4C3CDE710899CB20AB5E1CA706DA3E4E8E65253782379B49B7DEFE4E26DD498A935057E91B8FFB8B110336A554A6C61C26C2DDEEE8631926F8A706171B309B99E3B24030C17609340EBB82C4129B172B64CE6249FED00F05DCD624969BC1E4A29ED028C9821A812CDC310A974B959B29E30888887D9A8688E92F85E2A1683C5E993BCC584979F0B3F7DBE34295E2D852B6444EC4152A0C40F3113B402027E323231FC2EDD8078D6661F598588F68FB83DE9C2CA1491107E1F7B676BE16AA6C62B2FF86056905CFCE1FA57065B20A87B15BF1EADAC5FD94F5368451CE8CC2D363BC184A6E87D3D088CBCDE259845E4046D314660B1C1D4AFC7CCC37C7B1B8BBC7A54B63FE61FCD082966425AC3795F08BE7AFD6F9C66F2C3C50DD1EB6B8F8FC3C1A6A298A442EB6FC14AA906A7DA7854B53205E0A8F91C8D6CC3C41F4795FA70E14BA876548022733E61972F0351BC4187FFDE18E776BD68C5E947D2F0B19206D34770BA8ED63874639BBCEAA8D59771A02AEE654D20C69ACD8D16C42BAED6BD1AC51134F49C2A1D685B045527D4A86A7656439A2587F48F5AC43C5094DC680ECE19EBDD53B39F3B84F36D363D8CE464A20DE7ED50C6E32D5C7A9C3868D9823DF0E0A5FD824D239F67C41BC5AD3615AB51EA8B1A2C50B6D4C8F196F1278D9747B8C0B941509850052E63467950EBCE7B56D5E5C481D39E3958C51AE1267C075D8E62EC7F15400A5B4B91B15789015FBCCCC8186DC888CC0BC70326F1800FF56B01BC39DD1C2421BE6E142627B24822790DA36AD9CEA0661FAA03074FAA6F9EBC243DDCB249334B13D31DC19C0F03C6923CBFFEC6FAA29255";
+ char testResult[512] = "93E3A4336693965FEEC902F3BDDB064DD63D83EA1E46AA13DA209F8F000C15F366D3F9BE4F8AF189EA96D191D0BDE4CF0FC6C462C214B55ABF78F33BD6DF3DD0";
+
+ // Get a HMAC-SHA512 instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA512)) != NULL);
+
+ // Key
+ char pk[] = "a_key_for_HMAC-SHA512_test";
+ ByteString k((unsigned char *)pk, sizeof(pk));
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+
+ ByteString b(testData);
+ ByteString osslMac(testResult);
+
+ // Now verify the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(osslMac));
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989)));
+ CPPUNIT_ASSERT(mac->verifyFinal(osslMac));
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testCMACDES2()
+{
+ // Test vectors from NIST SP 800-38B
+ char pk[33] = "4cf15134a2850dd58a3d10ba80570d38";
+ char testData[4][2][256] = {
+ {
+ "",
+ "bd2ebf9a3ba00361"
+ },
+ {
+ "6bc1bee22e409f96",
+ "4ff2ab813c53ce83"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a57",
+ "62dd1b471902bd4e"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
+ "31b1e431dabc4eb8"
+ }
+ };
+
+ // Get a CMAC-DES instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_DES)) != NULL);
+
+ // Key
+ ByteString k(pk);
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+ key.setBitLen(112);
+
+ for (int i = 0; i < 4; i++)
+ {
+ ByteString b(testData[i][0]);
+ ByteString nistMac(testData[i][1]);
+ ByteString shsmMac;
+ size_t size, part1, part2;
+
+ // Now recreate the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+
+ // Now sign the MAC in a multiple part operation
+ shsmMac.wipe();
+ size = b.size();
+ part1 = size / 2;
+ part2 = size - part1;
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+ }
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testCMACDES3()
+{
+ // Test vectors from NIST SP 800-38B
+ char pk[49] = "8aa83bf8cbda10620bc1bf19fbb6cd58bc313d4a371ca8b5";
+ char testData[4][2][256] = {
+ {
+ "",
+ "b7a688e122ffaf95"
+ },
+ {
+ "6bc1bee22e409f96",
+ "8e8f293136283797"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a57",
+ "743ddbe0ce2dc2ed"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51",
+ "33e6b1092400eae5"
+ }
+ };
+
+ // Get a CMAC-DES instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_DES)) != NULL);
+
+ // Key
+ ByteString k(pk);
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+ key.setBitLen(168);
+
+ for (int i = 0; i < 4; i++)
+ {
+ ByteString b(testData[i][0]);
+ ByteString nistMac(testData[i][1]);
+ ByteString shsmMac;
+ size_t size, part1, part2;
+
+ // Now recreate the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+
+ // Now sign the MAC in a multiple part operation
+ shsmMac.wipe();
+ size = b.size();
+ part1 = size / 2;
+ part2 = size - part1;
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+ }
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testCMACAES128()
+{
+ // Test vectors from NIST SP 800-38B
+ char pk[33] = "2b7e151628aed2a6abf7158809cf4f3c";
+ char testData[4][2][256] = {
+ {
+ "",
+ "bb1d6929e95937287fa37d129b756746"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172a",
+ "070a16b46b4d4144f79bdd9dd04a287c"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411",
+ "dfa66747de9ae63030ca32611497c827"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+ "51f0bebf7e3b9d92fc49741779363cfe"
+ }
+ };
+
+ // Get a CMAC-AES instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL);
+
+ // Key
+ ByteString k(pk);
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+ key.setBitLen(128);
+
+ for (int i = 0; i < 4; i++)
+ {
+ ByteString b(testData[i][0]);
+ ByteString nistMac(testData[i][1]);
+ ByteString shsmMac;
+ size_t size, part1, part2;
+
+ // Now recreate the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+
+ // Now sign the MAC in a multiple part operation
+ shsmMac.wipe();
+ size = b.size();
+ part1 = size / 2;
+ part2 = size - part1;
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+ }
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testCMACAES192()
+{
+ // Test vectors from NIST SP 800-38B
+ char pk[49] = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
+ char testData[4][2][256] = {
+ {
+ "",
+ "d17ddf46adaacde531cac483de7a9367"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172a",
+ "9e99a7bf31e710900662f65e617c5184"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411",
+ "8a1de5be2eb31aad089a82e6ee908b0e"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+ "a1d5df0eed790f794d77589659f39a11"
+ }
+ };
+
+ // Get a CMAC-AES instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL);
+
+ // Key
+ ByteString k(pk);
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+ key.setBitLen(192);
+
+ for (int i = 0; i < 4; i++)
+ {
+ ByteString b(testData[i][0]);
+ ByteString nistMac(testData[i][1]);
+ ByteString shsmMac;
+ size_t size, part1, part2;
+
+ // Now recreate the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+
+ // Now sign the MAC in a multiple part operation
+ shsmMac.wipe();
+ size = b.size();
+ part1 = size / 2;
+ part2 = size - part1;
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+ }
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
+
+void MacTests::testCMACAES256()
+{
+ // Test vectors from NIST SP 800-38B
+ char pk[65] = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
+ char testData[4][2][256] = {
+ {
+ "",
+ "028962f61b7bf89efc6b551f4667d983"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172a",
+ "28a7023f452e8f82bd4bf28d8c37c35c"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411",
+ "aaf3d8f1de5640c232f5b169b9c911e6"
+ },
+ {
+ "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+ "e1992190549f6ed5696a2c056c315410"
+ }
+ };
+
+ // Get a CMAC-AES instance
+ CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL);
+
+ // Key
+ ByteString k(pk);
+ SymmetricKey key;
+ CPPUNIT_ASSERT(key.setKeyBits(k));
+ key.setBitLen(256);
+
+ for (int i = 0; i < 4; i++)
+ {
+ ByteString b(testData[i][0]);
+ ByteString nistMac(testData[i][1]);
+ ByteString shsmMac;
+ size_t size, part1, part2;
+
+ // Now recreate the MAC using our implementation in a single operation
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a single operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+
+ // Now sign the MAC in a multiple part operation
+ shsmMac.wipe();
+ size = b.size();
+ part1 = size / 2;
+ part2 = size - part1;
+ CPPUNIT_ASSERT(mac->signInit(&key));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->signFinal(shsmMac));
+ CPPUNIT_ASSERT(nistMac == shsmMac);
+
+ // Now verify the MAC in a multiple part operation
+ CPPUNIT_ASSERT(mac->verifyInit(&key));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1)));
+ CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2)));
+ CPPUNIT_ASSERT(mac->verifyFinal(nistMac));
+ }
+
+ CryptoFactory::i()->recycleMacAlgorithm(mac);
+
+ mac = NULL;
+ rng = NULL;
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/MacTests.h b/SoftHSMv2/src/lib/crypto/test/MacTests.h
new file mode 100644
index 0000000..9e6fa99
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/MacTests.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ MacTests.h
+
+ Contains test cases to test the MAC implementations
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_MACTESTS_H
+#define _SOFTHSM_V2_MACTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "MacAlgorithm.h"
+#include "RNG.h"
+
+class MacTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(MacTests);
+#ifndef WITH_FIPS
+ CPPUNIT_TEST(testHMACMD5);
+#endif
+ CPPUNIT_TEST(testHMACSHA1);
+ CPPUNIT_TEST(testHMACSHA224);
+ CPPUNIT_TEST(testHMACSHA256);
+ CPPUNIT_TEST(testHMACSHA384);
+ CPPUNIT_TEST(testHMACSHA512);
+ CPPUNIT_TEST(testCMACDES2);
+ CPPUNIT_TEST(testCMACDES3);
+ CPPUNIT_TEST(testCMACAES128);
+ CPPUNIT_TEST(testCMACAES192);
+ CPPUNIT_TEST(testCMACAES256);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+#ifndef WITH_FIPS
+ void testHMACMD5();
+#endif
+ void testHMACSHA1();
+ void testHMACSHA224();
+ void testHMACSHA256();
+ void testHMACSHA384();
+ void testHMACSHA512();
+ void testCMACDES2();
+ void testCMACDES3();
+ void testCMACAES128();
+ void testCMACAES192();
+ void testCMACAES256();
+
+ void setUp();
+ void tearDown();
+
+private:
+ MacAlgorithm* mac;
+
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_MACTESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/Makefile.am b/SoftHSMv2/src/lib/crypto/test/Makefile.am
new file mode 100644
index 0000000..bf63ae6
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/Makefile.am
@@ -0,0 +1,39 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../pkcs11 \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ @CPPUNIT_CFLAGS@ \
+ @CRYPTO_INCLUDES@
+
+check_PROGRAMS = cryptotest
+
+cryptotest_SOURCES = cryptotest.cpp \
+ AESTests.cpp \
+ DESTests.cpp \
+ DHTests.cpp \
+ DSATests.cpp \
+ ECDHTests.cpp \
+ ECDSATests.cpp \
+ GOSTTests.cpp \
+ HashTests.cpp \
+ MacTests.cpp \
+ RNGTests.cpp \
+ RSATests.cpp \
+ chisq.c \
+ ent.c \
+ iso8859.c \
+ randtest.c
+
+cryptotest_LDADD = ../../libsofthsm_convarch.la
+
+cryptotest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install
+
+TESTS = cryptotest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp b/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp
new file mode 100644
index 0000000..da793b5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RNGTests.cpp
+
+ Contains test cases to test the RNG class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNGTests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "ent.h"
+#include <stdio.h>
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RNGTests);
+
+void RNGTests::setUp()
+{
+ rng = NULL;
+
+ rng = CryptoFactory::i()->getRNG();
+
+ // Check the RNG
+ CPPUNIT_ASSERT(rng != NULL);
+}
+
+void RNGTests::tearDown()
+{
+ fflush(stdout);
+}
+
+void RNGTests::testSimpleComparison()
+{
+ ByteString a,b;
+
+ CPPUNIT_ASSERT(rng->generateRandom(a, 256));
+ CPPUNIT_ASSERT(rng->generateRandom(b, 256));
+ CPPUNIT_ASSERT(a.size() == 256);
+ CPPUNIT_ASSERT(b.size() == 256);
+ CPPUNIT_ASSERT(a != b);
+}
+
+void RNGTests::testEnt()
+{
+ ByteString a;
+ double entropy, chiProbability, arithMean, montePi, serialCorrelation;
+
+ // Generate 10MB of random data
+ CPPUNIT_ASSERT(rng->generateRandom(a, 10*1024*1024));
+
+ // Perform entropy tests
+ doEnt(a.byte_str(), a.size(), &entropy, &chiProbability, &arithMean, &montePi, &serialCorrelation);
+
+ // Check entropy
+ CPPUNIT_ASSERT(entropy >= 7.999);
+ CPPUNIT_ASSERT((arithMean >= 127.4) && (arithMean <= 127.6));
+ CPPUNIT_ASSERT(serialCorrelation <= 0.001);
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/test/RNGTests.h b/SoftHSMv2/src/lib/crypto/test/RNGTests.h
new file mode 100644
index 0000000..1391d81
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/RNGTests.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RNGTests.h
+
+ Contains test cases to test the RNG class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RNGTESTS_H
+#define _SOFTHSM_V2_RNGTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+
+class RNGTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RNGTests);
+ CPPUNIT_TEST(testSimpleComparison);
+ CPPUNIT_TEST(testEnt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testSimpleComparison();
+ void testEnt();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // RNG instance
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_RNGTESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/RSATests.cpp b/SoftHSMv2/src/lib/crypto/test/RSATests.cpp
new file mode 100644
index 0000000..6af1e19
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/RSATests.cpp
@@ -0,0 +1,682 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSATests.cpp
+
+ Contains test cases to test the RNG class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <vector>
+#include <cppunit/extensions/HelperMacros.h>
+#include "RSATests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricAlgorithm.h"
+#include "RSAParameters.h"
+#include "RSAPublicKey.h"
+#include "RSAPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RSATests);
+
+void RSATests::setUp()
+{
+ rsa = NULL;
+
+ rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
+
+ // Check the RSA object
+ CPPUNIT_ASSERT(rsa != NULL);
+}
+
+void RSATests::tearDown()
+{
+ if (rsa != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
+ }
+
+ fflush(stdout);
+}
+
+void RSATests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ // Public exponents to test
+ std::vector<ByteString> exponents;
+ exponents.push_back("010001");
+ exponents.push_back("03");
+ exponents.push_back("0B");
+ exponents.push_back("11");
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(1024);
+#ifndef WITH_FIPS
+ keySizes.push_back(1025);
+#endif
+ keySizes.push_back(1280);
+ keySizes.push_back(2048);
+ //keySizes.push_back(4096);
+
+ for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++)
+ {
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ p.setE(*e);
+ p.setBitLength(*k);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+
+ RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
+ RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getBitLength() == *k);
+ CPPUNIT_ASSERT(priv->getBitLength() == *k);
+ CPPUNIT_ASSERT(pub->getE() == *e);
+ CPPUNIT_ASSERT(priv->getE() == *e);
+
+ rsa->recycleKeyPair(kp);
+ }
+ }
+}
+
+void RSATests::testSerialisation()
+{
+ // Generate a 1024-bit key-pair for testing
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ p.setE("010001");
+ p.setBitLength(1024);
+
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+ CPPUNIT_ASSERT(kp != NULL);
+
+ // Serialise the parameters
+ ByteString serialisedParams = p.serialise();
+
+ // Deserialise the parameters
+ AsymmetricParameters* dP;
+
+ CPPUNIT_ASSERT(rsa->reconstructParameters(&dP, serialisedParams));
+ CPPUNIT_ASSERT(dP->areOfType(RSAParameters::type));
+
+ RSAParameters* ddP = (RSAParameters*) dP;
+
+ CPPUNIT_ASSERT(p.getE() == ddP->getE());
+ CPPUNIT_ASSERT(p.getBitLength() == ddP->getBitLength());
+ rsa->recycleParameters(dP);
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ CPPUNIT_ASSERT(serialisedKP.size() != 0);
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(rsa->reconstructKeyPair(&dKP, serialisedKP));
+ CPPUNIT_ASSERT(serialisedKP.size() == 0);
+ CPPUNIT_ASSERT(dKP != NULL);
+
+ RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
+ RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
+
+ RSAPublicKey* dPub = (RSAPublicKey*) dKP->getPublicKey();
+ RSAPrivateKey* dPriv = (RSAPrivateKey*) dKP->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getN() == dPub->getN());
+ CPPUNIT_ASSERT(pub->getE() == dPub->getE());
+
+ CPPUNIT_ASSERT(priv->getP() == dPriv->getP());
+ CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ());
+ CPPUNIT_ASSERT(priv->getPQ() == dPriv->getPQ());
+ CPPUNIT_ASSERT(priv->getDP1() == dPriv->getDP1());
+ CPPUNIT_ASSERT(priv->getDQ1() == dPriv->getDQ1());
+ CPPUNIT_ASSERT(priv->getD() == dPriv->getD());
+ CPPUNIT_ASSERT(priv->getN() == dPriv->getN());
+ CPPUNIT_ASSERT(priv->getE() == dPriv->getE());
+
+ // Serialise and deserialise the public key
+ ByteString serialisedPub = pub->serialise();
+
+ RSAPublicKey* desPub;
+
+ CPPUNIT_ASSERT(rsa->reconstructPublicKey((PublicKey**) &desPub, serialisedPub));
+ CPPUNIT_ASSERT(serialisedPub.size() == 0);
+ CPPUNIT_ASSERT(desPub != NULL);
+
+ CPPUNIT_ASSERT(pub->getN() == desPub->getN());
+ CPPUNIT_ASSERT(pub->getE() == desPub->getE());
+
+ // Serialise and deserialise the private key
+ ByteString serialisedPriv = priv->serialise();
+
+ RSAPrivateKey* desPriv;
+
+ CPPUNIT_ASSERT(rsa->reconstructPrivateKey((PrivateKey**) &desPriv, serialisedPriv));
+ CPPUNIT_ASSERT(serialisedPriv.size() == 0);
+ CPPUNIT_ASSERT(desPriv != NULL);
+
+ CPPUNIT_ASSERT(priv->getP() == desPriv->getP());
+ CPPUNIT_ASSERT(priv->getQ() == desPriv->getQ());
+ CPPUNIT_ASSERT(priv->getPQ() == desPriv->getPQ());
+ CPPUNIT_ASSERT(priv->getDP1() == desPriv->getDP1());
+ CPPUNIT_ASSERT(priv->getDQ1() == desPriv->getDQ1());
+ CPPUNIT_ASSERT(priv->getD() == desPriv->getD());
+ CPPUNIT_ASSERT(priv->getN() == desPriv->getN());
+ CPPUNIT_ASSERT(priv->getE() == desPriv->getE());
+
+ rsa->recycleKeyPair(kp);
+ rsa->recycleKeyPair(dKP);
+ rsa->recyclePublicKey(desPub);
+ rsa->recyclePrivateKey(desPriv);
+}
+
+void RSATests::testPKCS8()
+{
+ // Generate a 1024-bit key-pair for testing
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ p.setE("010001");
+ p.setBitLength(1024);
+
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+ CPPUNIT_ASSERT(kp != NULL);
+
+ RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
+ CPPUNIT_ASSERT(priv != NULL);
+
+ // Encode and decode the private key
+ ByteString pkcs8 = priv->PKCS8Encode();
+ CPPUNIT_ASSERT(pkcs8.size() != 0);
+
+ RSAPrivateKey* dPriv = (RSAPrivateKey*) rsa->newPrivateKey();
+ CPPUNIT_ASSERT(dPriv != NULL);
+
+ CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8));
+
+ CPPUNIT_ASSERT(priv->getP() == dPriv->getP());
+ CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ());
+ CPPUNIT_ASSERT(priv->getPQ() == dPriv->getPQ());
+ CPPUNIT_ASSERT(priv->getDP1() == dPriv->getDP1());
+ CPPUNIT_ASSERT(priv->getDQ1() == dPriv->getDQ1());
+ CPPUNIT_ASSERT(priv->getD() == dPriv->getD());
+ CPPUNIT_ASSERT(priv->getN() == dPriv->getN());
+ CPPUNIT_ASSERT(priv->getE() == dPriv->getE());
+
+ rsa->recycleKeyPair(kp);
+ rsa->recyclePrivateKey(dPriv);
+}
+
+void RSATests::testSigningVerifying()
+{
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ // Public exponents to test
+ std::vector<ByteString> exponents;
+ exponents.push_back("010001");
+ exponents.push_back("03");
+ exponents.push_back("0B");
+ exponents.push_back("11");
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(1024);
+ keySizes.push_back(1280);
+ keySizes.push_back(2048);
+ //keySizes.push_back(4096);
+
+ // Mechanisms to test
+ std::vector<AsymMech::Type> mechanisms;
+#ifndef WITH_FIPS
+ mechanisms.push_back(AsymMech::RSA_MD5_PKCS);
+#endif
+ mechanisms.push_back(AsymMech::RSA_SHA1_PKCS);
+ mechanisms.push_back(AsymMech::RSA_SHA224_PKCS);
+ mechanisms.push_back(AsymMech::RSA_SHA256_PKCS);
+ mechanisms.push_back(AsymMech::RSA_SHA384_PKCS);
+ mechanisms.push_back(AsymMech::RSA_SHA512_PKCS);
+ mechanisms.push_back(AsymMech::RSA_SHA1_PKCS_PSS);
+ mechanisms.push_back(AsymMech::RSA_SHA224_PKCS_PSS);
+ mechanisms.push_back(AsymMech::RSA_SHA256_PKCS_PSS);
+ mechanisms.push_back(AsymMech::RSA_SHA384_PKCS_PSS);
+ mechanisms.push_back(AsymMech::RSA_SHA512_PKCS_PSS);
+#ifndef WITH_FIPS
+ mechanisms.push_back(AsymMech::RSA_SSL);
+#endif
+
+ /* Max salt length for SHA512 and 1024-bit RSA is 62 bytes */
+ RSA_PKCS_PSS_PARAMS pssParams[] = {
+ { HashAlgo::SHA1, AsymRSAMGF::MGF1_SHA1, 20 },
+ { HashAlgo::SHA224, AsymRSAMGF::MGF1_SHA224, 0 },
+ { HashAlgo::SHA256, AsymRSAMGF::MGF1_SHA256, 0 },
+ { HashAlgo::SHA384, AsymRSAMGF::MGF1_SHA384, 48 },
+ { HashAlgo::SHA512, AsymRSAMGF::MGF1_SHA512, 62 }
+ };
+
+ for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++)
+ {
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ p.setE(*e);
+ p.setBitLength(*k);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+
+ // Generate some data to sign
+ ByteString dataToSign;
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));
+
+ // Test mechanisms that perform internal hashing
+ for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++)
+ {
+ ByteString blockSignature, singlePartSignature;
+ void* param = NULL;
+ size_t paramLen = 0;
+ bool isPSS = false;
+
+ switch (*m)
+ {
+ case AsymMech::RSA_SHA1_PKCS_PSS:
+ param = &pssParams[0];
+ paramLen = sizeof(pssParams[0]);
+ isPSS = true;
+ break;
+ case AsymMech::RSA_SHA224_PKCS_PSS:
+ param = &pssParams[1];
+ paramLen = sizeof(pssParams[1]);
+ isPSS = true;
+ break;
+ case AsymMech::RSA_SHA256_PKCS_PSS:
+ param = &pssParams[2];
+ paramLen = sizeof(pssParams[2]);
+ isPSS = true;
+ break;
+ case AsymMech::RSA_SHA384_PKCS_PSS:
+ param = &pssParams[3];
+ paramLen = sizeof(pssParams[3]);
+ isPSS = true;
+ break;
+ case AsymMech::RSA_SHA512_PKCS_PSS:
+ param = &pssParams[4];
+ paramLen = sizeof(pssParams[4]);
+ isPSS = true;
+ break;
+ default:
+ break;
+ }
+
+ // Sign the data in blocks
+ CPPUNIT_ASSERT(rsa->signInit(kp->getPrivateKey(), *m, param, paramLen));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(0, 134)));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134, 289)));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134 + 289)));
+ CPPUNIT_ASSERT(rsa->signFinal(blockSignature));
+
+ // Sign the data in one pass
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m, param, paramLen));
+
+ // If it is not a PSS signature, check if the two signatures match
+ if (!isPSS)
+ {
+ // Check if the two signatures match
+ CPPUNIT_ASSERT(blockSignature == singlePartSignature);
+ }
+
+ // Now perform multi-pass verification
+ CPPUNIT_ASSERT(rsa->verifyInit(kp->getPublicKey(), *m, param, paramLen));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(0, 125)));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125, 247)));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125 + 247)));
+ CPPUNIT_ASSERT(rsa->verifyFinal(blockSignature));
+
+ // And single-pass verification
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m, param, paramLen));
+ }
+
+ // Test mechanisms that do not perform internal hashing
+
+ // Test PKCS #1 signing
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 35));
+
+ // Sign the data
+ ByteString signature;
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS));
+
+ // Verify the signature
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS));
+
+ // Test raw RSA signing
+ size_t byteSize = *k >> 3;
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, byteSize));
+
+ // Strip the topmost bit
+ dataToSign[0] &= 0x7F;
+
+ // Sign the data
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA));
+
+ // Verify the signature
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA));
+
+#ifdef WITH_RAW_PSS
+ // Test raw (SHA1) PKCS PSS signing
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 20));
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[0], sizeof(pssParams[0])));
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[0], sizeof(pssParams[0])));
+
+ // Test raw (SHA224) PKCS PSS signing
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 28));
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[1], sizeof(pssParams[1])));
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[1], sizeof(pssParams[1])));
+
+ // Test raw (SHA256) PKCS PSS signing
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 32));
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[2], sizeof(pssParams[2])));
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[2], sizeof(pssParams[2])));
+
+ // Test raw (SHA384) PKCS PSS signing
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 48));
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[3], sizeof(pssParams[3])));
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[3], sizeof(pssParams[3])));
+
+ // Test raw (SHA512) PKCS PSS signing
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 64));
+ CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[4], sizeof(pssParams[4])));
+ CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[4], sizeof(pssParams[4])));
+#endif
+
+ rsa->recycleKeyPair(kp);
+ }
+ }
+}
+
+void RSATests::testSignVerifyKnownVector()
+{
+ // These test vectors were taken from the Crypto++ set of test vectors
+ // Crypto++ can be downloaded from www.cryptopp.com
+
+#ifndef WITH_FIPS
+ RSAPublicKey* pubKey1 = (RSAPublicKey*) rsa->newPublicKey();
+ RSAPublicKey* pubKey2 = (RSAPublicKey*) rsa->newPublicKey();
+#endif
+ RSAPublicKey* pubKey3 = (RSAPublicKey*) rsa->newPublicKey();
+#ifndef WITH_FIPS
+ RSAPrivateKey* privKey1_1 = (RSAPrivateKey*) rsa->newPrivateKey();
+ RSAPrivateKey* privKey1_2 = (RSAPrivateKey*) rsa->newPrivateKey();
+ RSAPrivateKey* privKey2_1 = (RSAPrivateKey*) rsa->newPrivateKey();
+ RSAPrivateKey* privKey2_2 = (RSAPrivateKey*) rsa->newPrivateKey();
+#endif
+ RSAPrivateKey* privKey3 = (RSAPrivateKey*) rsa->newPrivateKey();
+
+#ifndef WITH_FIPS
+ // Reconstruct public and private key #1
+ ByteString n1 = "0A66791DC6988168DE7AB77419BB7FB0C001C62710270075142942E19A8D8C51D053B3E3782A1DE5DC5AF4EBE99468170114A1DFE67CDC9A9AF55D655620BBAB";
+ ByteString e1 = "010001";
+ ByteString d1 = "0123C5B61BA36EDB1D3679904199A89EA80C09B9122E1400C09ADCF7784676D01D23356A7D44D6BD8BD50E94BFC723FA87D8862B75177691C11D757692DF8881";
+ ByteString p1 = "33D48445C859E52340DE704BCDDA065FBB4058D740BD1D67D29E9C146C11CF61";
+ ByteString q1 = "335E8408866B0FD38DC7002D3F972C67389A65D5D8306566D5C4F2A5AA52628B";
+ ByteString dp11 = "045EC90071525325D3D46DB79695E9AFACC4523964360E02B119BAA366316241";
+ ByteString dq11 = "15EB327360C7B60D12E5E2D16BDCD97981D17FBA6B70DB13B20B436E24EADA59";
+ ByteString pq1 = "2CA6366D72781DFA24D34A9A24CBC2AE927A9958AF426563FF63FB11658A461D";
+
+ pubKey1->setN(n1);
+ pubKey1->setE(e1);
+ privKey1_1->setN(n1);
+ privKey1_1->setE(e1);
+ privKey1_1->setD(d1);
+ privKey1_1->setP(p1);
+ privKey1_1->setQ(q1);
+ privKey1_1->setDP1(dp11);
+ privKey1_1->setDQ1(dq11);
+ privKey1_1->setPQ(pq1);
+
+ // The same key but without CRT factors
+ privKey1_2->setN(n1);
+ privKey1_2->setE(e1);
+ privKey1_2->setD(d1);
+
+ // Reconstruct public and private key #2
+ ByteString n2 = "A885B6F851A8079AB8A281DB0297148511EE0D8C07C0D4AE6D6FED461488E0D41E3FF8F281B06A3240B5007A5C2AB4FB6BE8AF88F119DB998368DDDC9710ABED";
+ ByteString e2 = "010001";
+ ByteString d2 = "2B259D2CA3DF851EE891F6F4678BDDFD9A131C95D3305C63D2723B4A5B9C960F5EC8BB7DCDDBEBD8B6A38767D64AD451E9383E0891E4EE7506100481F2B49323";
+ ByteString p2 = "D7103CD676E39824E2BE50B8E6533FE7CB7484348E283802AD2B8D00C80D19DF";
+ ByteString q2 = "C89996DC169CEB3F227958275968804D4BE9FC4012C3219662F1A438C9950BB3";
+ ByteString dp12 = "5D8EA4C8AF83A70634D5920C3DB66D908AC3AF57A597FD75BC9BBB856181C185";
+ ByteString dq12 = "C598E54DAEC8ABC1E907769A6C2BD01653ED0C9960E1EDB7E186FDA922883A99";
+ ByteString pq2 = "7C6F27B5B51B78AD80FB36E700990CF307866F2943124CBD93D97C137794C104";
+
+ pubKey2->setN(n2);
+ pubKey2->setE(e2);
+ privKey2_1->setN(n2);
+ privKey2_1->setE(e2);
+ privKey2_1->setD(d2);
+ privKey2_1->setP(p2);
+ privKey2_1->setQ(q2);
+ privKey2_1->setDP1(dp12);
+ privKey2_1->setDQ1(dq12);
+ privKey2_1->setPQ(pq2);
+
+ // The same key but without CRT factors
+ privKey2_2->setN(n2);
+ privKey2_2->setE(e2);
+ privKey2_2->setD(d2);
+#endif
+
+ ByteString n3 = "A8D68ACD413C5E195D5EF04E1B4FAAF242365CB450196755E92E1215BA59802AAFBADBF2564DD550956ABB54F8B1C917844E5F36195D1088C600E07CADA5C080EDE679F50B3DE32CF4026E514542495C54B1903768791AAE9E36F082CD38E941ADA89BAECADA61AB0DD37AD536BCB0A0946271594836E92AB5517301D45176B5";
+ ByteString e3 = "03";
+ ByteString d3 = "1C23C1CCE034BA598F8FD2B7AF37F1D30B090F7362AEE68E5187ADAE49B9955C729F24A863B7A38D6E3C748E2972F6D940B7BA89043A2D6C2100256A1CF0F56A8CD35FC6EE205244876642F6F9C3820A3D9D2C8921DF7D82AAADCAF2D7334D398931DDBBA553190B3A416099F3AA07FD5B26214645A828419E122CFB857AD73B";
+ ByteString p3 = "C107a2fe924b76e206cb9bc4af2ab7008547c00846bf6d0680b3eac3ebcbd0c7fd7a54c2b9899b08f80cde1d3691eaaa2816b1eb11822d6be7beaf4e30977c49";
+ ByteString q3 = "DFEA984CE4307EAFC0D140C2BB82861E5DBAC4F8567CBC981D70440DD639492079031486315E305EB83E591C4A2E96064966F7C894C3CA351925B5CE82D8EF0D";
+
+ pubKey3->setN(n3);
+ pubKey3->setE(e3);
+ privKey3->setN(n3);
+ privKey3->setE(e3);
+ privKey3->setD(d3);
+ privKey3->setP(p3);
+ privKey3->setQ(q3);
+
+#ifndef WITH_FIPS
+ // Test with key #1
+ const char* testValue1 = "Everyone gets Friday off.";
+
+ ByteString dataToSign1((const unsigned char*) testValue1, strlen(testValue1));
+
+ ByteString expectedSignature1 = "0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81";
+ ByteString signature1_1;
+ ByteString signature1_2;
+
+ CPPUNIT_ASSERT(rsa->signInit(privKey1_1, AsymMech::RSA_SHA1_PKCS));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign1));
+ CPPUNIT_ASSERT(rsa->signFinal(signature1_1));
+
+#ifndef WITH_BOTAN
+ CPPUNIT_ASSERT(rsa->signInit(privKey1_2, AsymMech::RSA_SHA1_PKCS));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign1));
+ CPPUNIT_ASSERT(rsa->signFinal(signature1_2));
+
+ CPPUNIT_ASSERT(signature1_1 == signature1_2);
+#endif
+ CPPUNIT_ASSERT(signature1_1 == expectedSignature1);
+
+ CPPUNIT_ASSERT(rsa->verifyInit(pubKey1, AsymMech::RSA_SHA1_PKCS));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign1));
+ CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature1));
+
+ // Test with key #2
+ const char* testValue2 = "test";
+
+ ByteString dataToSign2((const unsigned char*) testValue2, strlen(testValue2));
+
+ ByteString expectedSignature2 = "A7E00CE4391F914D82158D9B732759808E25A1C6383FE87A5199157650D4296CF612E9FF809E686A0AF328238306E79965F6D0138138829D9A1A22764306F6CE";
+ ByteString signature2_1;
+ ByteString signature2_2;
+
+ CPPUNIT_ASSERT(rsa->signInit(privKey2_1, AsymMech::RSA_SHA1_PKCS));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign2));
+ CPPUNIT_ASSERT(rsa->signFinal(signature2_1));
+
+#ifndef WITH_BOTAN
+ CPPUNIT_ASSERT(rsa->signInit(privKey2_2, AsymMech::RSA_SHA1_PKCS));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign2));
+ CPPUNIT_ASSERT(rsa->signFinal(signature2_2));
+
+ CPPUNIT_ASSERT(signature2_1 == signature2_2);
+#endif
+ CPPUNIT_ASSERT(signature2_1 == expectedSignature2);
+
+ CPPUNIT_ASSERT(rsa->verifyInit(pubKey2, AsymMech::RSA_SHA1_PKCS));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign2));
+ CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature2));
+#endif
+
+ // Test with key #3
+ ByteString dataToSign3 = "D73829497CDDBE41B705FAAC50E7899FDB5A38BF3A459E536357029E64F8796BA47F4FE96BA5A8B9A4396746E2164F55A25368DDD0B9A5188C7AC3DA2D1F742286C3BDEE697F9D546A25EFCFE53191D743FCC6B47833D993D08804DAECA78FB9076C3C017F53E33A90305AF06220974D46BF19ED3C9B84EDBAE98B45A8771258";
+ ByteString expectedSignature3 = "175015BDA50ABE0FA7D39A8353885CA01BE3A7E7FCC55045744111362EE1914473A48DC537D956294B9E20A1EF661D58537ACDC8DE908FA050630FCC272E6D001045E6FDEED2D10531C8603334C2E8DB39E73E6D9665EE1343F9E4198302D2201B44E8E8D06B3EF49CEE6197582163A8490089CA654C0012FCE1BA6511089750";
+ ByteString signature3;
+
+ CPPUNIT_ASSERT(rsa->signInit(privKey3, AsymMech::RSA_SHA1_PKCS));
+ CPPUNIT_ASSERT(rsa->signUpdate(dataToSign3));
+ CPPUNIT_ASSERT(rsa->signFinal(signature3));
+
+ CPPUNIT_ASSERT(signature3 == expectedSignature3);
+
+ CPPUNIT_ASSERT(rsa->verifyInit(pubKey3, AsymMech::RSA_SHA1_PKCS));
+ CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign3));
+ CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature3));
+
+#ifndef WITH_FIPS
+ rsa->recyclePublicKey(pubKey1);
+ rsa->recyclePublicKey(pubKey2);
+#endif
+ rsa->recyclePublicKey(pubKey3);
+#ifndef WITH_FIPS
+ rsa->recyclePrivateKey(privKey1_1);
+ rsa->recyclePrivateKey(privKey1_2);
+ rsa->recyclePrivateKey(privKey2_1);
+ rsa->recyclePrivateKey(privKey2_2);
+#endif
+ rsa->recyclePrivateKey(privKey3);
+}
+
+void RSATests::testEncryptDecrypt()
+{
+ AsymmetricKeyPair* kp;
+ RSAParameters p;
+
+ // Public exponents to test
+ std::vector<ByteString> exponents;
+ exponents.push_back("010001");
+ exponents.push_back("03");
+ exponents.push_back("0B");
+ exponents.push_back("11");
+
+ // Key sizes to test
+ std::vector<size_t> keySizes;
+ keySizes.push_back(1024);
+ keySizes.push_back(1280);
+ keySizes.push_back(2048);
+ //keySizes.push_back(4096);
+
+ // Paddings to test
+ std::vector<AsymMech::Type> paddings;
+ paddings.push_back(AsymMech::RSA_PKCS);
+ paddings.push_back(AsymMech::RSA_PKCS_OAEP);
+ paddings.push_back(AsymMech::RSA);
+
+ for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++)
+ {
+ for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++)
+ {
+ p.setE(*e);
+ p.setBitLength(*k);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p));
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ for (std::vector<AsymMech::Type>::iterator pad = paddings.begin(); pad != paddings.end(); pad++)
+ {
+ // Generate some test data to encrypt based on the selected padding
+ ByteString testData;
+
+ if (*pad == AsymMech::RSA_PKCS)
+ {
+ CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 12));
+ }
+ else if (*pad == AsymMech::RSA_PKCS_OAEP)
+ {
+ CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 42));
+ }
+ else if (*pad == AsymMech::RSA)
+ {
+ CPPUNIT_ASSERT(rng->generateRandom(testData, *k >> 3));
+ testData[0] &= 0x0F;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(true == false);
+ }
+
+ // Encrypt the data
+ ByteString encryptedData;
+
+ CPPUNIT_ASSERT(rsa->encrypt(kp->getPublicKey(), testData, encryptedData, *pad));
+
+ // The encrypted data length should equal the modulus length
+ CPPUNIT_ASSERT(encryptedData.size() == (*k >> 3));
+ CPPUNIT_ASSERT(encryptedData != testData);
+
+ // Now decrypt the data
+ ByteString decryptedData;
+
+ CPPUNIT_ASSERT(rsa->decrypt(kp->getPrivateKey(), encryptedData, decryptedData, *pad));
+
+ // Check that the data was properly decrypted
+ CPPUNIT_ASSERT(decryptedData == testData);
+ }
+
+ rsa->recycleKeyPair(kp);
+ }
+ }
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/test/RSATests.h b/SoftHSMv2/src/lib/crypto/test/RSATests.h
new file mode 100644
index 0000000..ca5c86d
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/RSATests.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RSATests.h
+
+ Contains test cases to test the RSA class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RSATESTS_H
+#define _SOFTHSM_V2_RSATESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+
+class RSATests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RSATests);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testPKCS8);
+ CPPUNIT_TEST(testSigningVerifying);
+ CPPUNIT_TEST(testSignVerifyKnownVector);
+ CPPUNIT_TEST(testEncryptDecrypt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testKeyGeneration();
+ void testSerialisation();
+ void testPKCS8();
+ void testSigningVerifying();
+ void testSignVerifyKnownVector();
+ void testEncryptDecrypt();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // RSA instance
+ AsymmetricAlgorithm* rsa;
+};
+
+#endif // !_SOFTHSM_V2_RSATESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/chisq.c b/SoftHSMv2/src/lib/crypto/test/chisq.c
new file mode 100644
index 0000000..3fe4f66
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/chisq.c
@@ -0,0 +1,144 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/*
+
+ Compute probability of measured Chi Square value.
+
+ This code was developed by Gary Perlman of the Wang
+ Institute (full citation below) and has been minimally
+ modified for use in this program.
+
+*/
+
+#include <math.h>
+
+/*HEADER
+ Module: z.c
+ Purpose: compute approximations to normal z distribution probabilities
+ Programmer: Gary Perlman
+ Organization: Wang Institute, Tyngsboro, MA 01879
+ Copyright: none
+ Tabstops: 4
+*/
+
+#define Z_MAX 6.0 /* maximum meaningful z value */
+
+/*FUNCTION poz: probability of normal z value */
+/*ALGORITHM
+ Adapted from a polynomial approximation in:
+ Ibbetson D, Algorithm 209
+ Collected Algorithms of the CACM 1963 p. 616
+ Note:
+ This routine has six digit accuracy, so it is only useful for absolute
+ z values < 6. For z values >= to 6.0, poz() returns 0.0.
+*/
+static double /*VAR returns cumulative probability from -oo to z */
+poz(const double z) /*VAR normal z value */
+{
+ double y, x, w;
+
+ if (z == 0.0) {
+ x = 0.0;
+ } else {
+ y = 0.5 * fabs(z);
+ if (y >= (Z_MAX * 0.5)) {
+ x = 1.0;
+ } else if (y < 1.0) {
+ w = y * y;
+ x = ((((((((0.000124818987 * w
+ -0.001075204047) * w +0.005198775019) * w
+ -0.019198292004) * w +0.059054035642) * w
+ -0.151968751364) * w +0.319152932694) * w
+ -0.531923007300) * w +0.797884560593) * y * 2.0;
+ } else {
+ y -= 2.0;
+ x = (((((((((((((-0.000045255659 * y
+ +0.000152529290) * y -0.000019538132) * y
+ -0.000676904986) * y +0.001390604284) * y
+ -0.000794620820) * y -0.002034254874) * y
+ +0.006549791214) * y -0.010557625006) * y
+ +0.011630447319) * y -0.009279453341) * y
+ +0.005353579108) * y -0.002141268741) * y
+ +0.000535310849) * y +0.999936657524;
+ }
+ }
+ return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5));
+}
+
+/*
+ Module: chisq.c
+ Purpose: compute approximations to chisquare distribution probabilities
+ Contents: pochisq()
+ Uses: poz() in z.c (Algorithm 209)
+ Programmer: Gary Perlman
+ Organization: Wang Institute, Tyngsboro, MA 01879
+ Copyright: none
+ Tabstops: 4
+*/
+
+#define LOG_SQRT_PI 0.5723649429247000870717135 /* log (sqrt (pi)) */
+#define I_SQRT_PI 0.5641895835477562869480795 /* 1 / sqrt (pi) */
+#define BIGX 20.0 /* max value to represent exp (x) */
+#define ex(x) (((x) < -BIGX) ? 0.0 : exp(x))
+
+/*FUNCTION pochisq: probability of chi sqaure value */
+/*ALGORITHM Compute probability of chi square value.
+ Adapted from:
+ Hill, I. D. and Pike, M. C. Algorithm 299
+ Collected Algorithms for the CACM 1967 p. 243
+ Updated for rounding errors based on remark in
+ ACM TOMS June 1985, page 185
+*/
+
+double pochisq(
+ const double ax, /* obtained chi-square value */
+ const int df /* degrees of freedom */
+ )
+{
+ double x = ax;
+ double a, y, s;
+ double e, c, z;
+ int even; /* true if df is an even number */
+
+ if (x <= 0.0 || df < 1) {
+ return 1.0;
+ }
+
+ a = 0.5 * x;
+ even = (2 * (df / 2)) == df;
+ y = 0.0;
+ if (df > 1) {
+ y = ex(-a);
+ }
+ s = (even ? y : (2.0 * poz(-sqrt(x))));
+ if (df > 2) {
+ x = 0.5 * (df - 1.0);
+ z = (even ? 1.0 : 0.5);
+ if (a > BIGX) {
+ e = (even ? 0.0 : LOG_SQRT_PI);
+ c = log(a);
+ while (z <= x) {
+ e = log(z) + e;
+ s += ex(c * z - a - e);
+ z += 1.0;
+ }
+ return (s);
+ } else {
+ e = (even ? 1.0 : (I_SQRT_PI / sqrt(a)));
+ c = 0.0;
+ while (z <= x) {
+ e = e * (a / z);
+ c = c + e;
+ z += 1.0;
+ }
+ return (c * y + s);
+ }
+ } else {
+ return s;
+ }
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp b/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp
new file mode 100644
index 0000000..2fc7b8f
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ cryptotest.cpp
+
+ The main test executor for tests on the cryptographic functions in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "SecureMemoryRegistry.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#endif
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ CryptoFactory::reset();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/ent.c b/SoftHSMv2/src/lib/crypto/test/ent.c
new file mode 100644
index 0000000..b255405
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/ent.c
@@ -0,0 +1,110 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/*
+ ENT -- Entropy calculation and analysis of putative
+ random sequences.
+
+ Designed and implemented by John "Random" Walker in May 1985.
+
+ Multiple analyses of random sequences added in December 1985.
+
+ Bit stream analysis added in September 1997.
+
+ Terse mode output, getopt() command line processing,
+ optional stdin input, and HTML documentation added in
+ October 1998.
+
+ Documentation for the -t (terse output) option added
+ in July 2006.
+
+ Replaced table look-up for chi square to probability
+ conversion with algorithmic computation in January 2008.
+
+ For additional information and the latest version,
+ see http://www.fourmilab.ch/random/
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#ifdef _WIN32
+#include <fcntl.h>
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "iso8859.h"
+#include "randtest.h"
+
+#define UPDATE "January 28th, 2008"
+
+#define FALSE 0
+#define TRUE 1
+
+#ifdef M_PI
+#define PI M_PI
+#else
+#define PI 3.14159265358979323846
+#endif
+
+extern double pochisq(const double ax, const int df);
+
+/* Main program */
+
+void doEnt
+(
+ unsigned char* data,
+ size_t len,
+ double* pEntropy,
+ double* pChiProbability,
+ double* pArithMean,
+ double* pMontePi,
+ double* pSerialCorrelation
+)
+{
+ size_t s;
+ long ccount[256]; /* Bins to count occurrences of values */
+ double montepi, chip,
+ scc, ent, mean, chisq;
+
+ /* Initialise for calculations */
+
+ rt_init(FALSE);
+
+ /* Scan input file and count character occurrences */
+
+ for (s = 0; s < len; s++)
+ {
+ unsigned char ocb = data[s];
+
+ ccount[ocb]++; /* Update counter for this bin */
+ rt_add(&ocb, 1);
+ }
+
+ /* Complete calculation and return sequence metrics */
+
+ rt_end(&ent, &chisq, &mean, &montepi, &scc);
+
+ /* Calculate probability of observed distribution occurring from
+ the results of the Chi-Square test */
+
+ chip = pochisq(chisq, 255);
+
+ /* Print bin counts if requested */
+
+ /* Return calculated results */
+
+ *pEntropy = ent;
+ *pChiProbability = chip;
+ *pArithMean = mean;
+ *pMontePi = montepi;
+ *pSerialCorrelation = scc;
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/ent.h b/SoftHSMv2/src/lib/crypto/test/ent.h
new file mode 100644
index 0000000..5958888
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/ent.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ent.h
+
+ Header file to give access to the modified ent.c implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ENT_H
+#define _SOFTHSM_V2_ENT_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void doEnt
+(
+ unsigned char* data,
+ size_t len,
+ double* pEntropy,
+ double* pChiProbability,
+ double* pArithMean,
+ double* pMontePi,
+ double* pSerialCorrelation
+);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // !_SOFTHSM_V2_ENT_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/iso8859.c b/SoftHSMv2/src/lib/crypto/test/iso8859.c
new file mode 100644
index 0000000..bed7244
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/iso8859.c
@@ -0,0 +1,25 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/* ISO 8859/1 Latin-1 alphabetic and upper and lower case bit vector tables. */
+
+/* LINTLIBRARY */
+
+unsigned char isoalpha[32] = {
+ 0,0,0,0,0,0,0,0,127,255,255,224,127,255,255,224,0,0,0,0,0,0,0,0,255,255,
+ 254,255,255,255,254,255
+};
+
+unsigned char isoupper[32] = {
+ 0,0,0,0,0,0,0,0,127,255,255,224,0,0,0,0,0,0,0,0,0,0,0,0,255,255,254,254,
+ 0,0,0,0
+};
+
+unsigned char isolower[32] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,127,255,255,224,0,0,0,0,0,0,0,0,0,0,0,1,255,255,
+ 254,255
+};
diff --git a/SoftHSMv2/src/lib/crypto/test/iso8859.h b/SoftHSMv2/src/lib/crypto/test/iso8859.h
new file mode 100644
index 0000000..7462f15
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/iso8859.h
@@ -0,0 +1,23 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/* ISO 8859/1 Latin-1 "ctype" macro replacements. */
+
+extern unsigned char isoalpha[32], isoupper[32], isolower[32];
+
+#define isISOspace(x) ((isascii(((unsigned char) (x))) && isspace(((unsigned char) (x)))) || ((x) == 0xA0))
+#define isISOalpha(x) ((isoalpha[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0)
+#define isISOupper(x) ((isoupper[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0)
+#define isISOlower(x) ((isolower[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0)
+#define isISOprint(x) ((((x) >= ' ') && ((x) <= '~')) || ((x) >= 0xA0))
+#define toISOupper(x) (isISOlower(x) ? (isascii(((unsigned char) (x))) ? \
+ toupper(x) : (((((unsigned char) (x)) != 0xDF) && \
+ (((unsigned char) (x)) != 0xFF)) ? \
+ (((unsigned char) (x)) - 0x20) : (x))) : (x))
+#define toISOlower(x) (isISOupper(x) ? (isascii(((unsigned char) (x))) ? \
+ tolower(x) : (((unsigned char) (x)) + 0x20)) \
+ : (x))
diff --git a/SoftHSMv2/src/lib/crypto/test/randtest.c b/SoftHSMv2/src/lib/crypto/test/randtest.c
new file mode 100644
index 0000000..5a54737
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/randtest.c
@@ -0,0 +1,190 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/*
+
+ Apply various randomness tests to a stream of bytes
+
+ by John Walker -- September 1996
+ http://www.fourmilab.ch/
+
+*/
+
+#include <math.h>
+
+#define FALSE 0
+#define TRUE 1
+
+#define log2of10 3.32192809488736234787
+
+static int binary = FALSE; /* Treat input as a bitstream */
+
+static long ccount[256], /* Bins to count occurrences of values */
+ totalc = 0; /* Total bytes counted */
+static double prob[256]; /* Probabilities per bin for entropy */
+
+/* RT_LOG2 -- Calculate log to the base 2 */
+
+static double rt_log2(double x)
+{
+ return log2of10 * log10(x);
+}
+
+#define MONTEN 6 /* Bytes used as Monte Carlo
+ co-ordinates. This should be no more
+ bits than the mantissa of your
+ "double" floating point type. */
+
+static int mp, sccfirst;
+static unsigned int monte[MONTEN];
+static long inmont, mcount;
+static double cexp, incirc, montex, montey, montepi,
+ scc, sccun, sccu0, scclast, scct1, scct2, scct3,
+ ent, chisq, datasum;
+
+/* RT_INIT -- Initialise random test counters. */
+
+void rt_init(int binmode)
+{
+ int i;
+
+ binary = binmode; /* Set binary / byte mode */
+
+ /* Initialise for calculations */
+
+ ent = 0.0; /* Clear entropy accumulator */
+ chisq = 0.0; /* Clear Chi-Square */
+ datasum = 0.0; /* Clear sum of bytes for arithmetic mean */
+
+ mp = 0; /* Reset Monte Carlo accumulator pointer */
+ mcount = 0; /* Clear Monte Carlo tries */
+ inmont = 0; /* Clear Monte Carlo inside count */
+ incirc = 65535.0 * 65535.0;/* In-circle distance for Monte Carlo */
+
+ sccfirst = TRUE; /* Mark first time for serial correlation */
+ scct1 = scct2 = scct3 = 0.0; /* Clear serial correlation terms */
+
+ incirc = pow(pow(256.0, (double) (MONTEN / 2)) - 1, 2.0);
+
+ for (i = 0; i < 256; i++) {
+ ccount[i] = 0;
+ }
+ totalc = 0;
+}
+
+/* RT_ADD -- Add one or more bytes to accumulation. */
+
+void rt_add(void *buf, int bufl)
+{
+ unsigned char *bp = (unsigned char *)buf;
+ int oc, c, bean;
+
+ while (bean = 0, (bufl-- > 0)) {
+ oc = *bp++;
+
+ do {
+ if (binary) {
+ c = !!(oc & 0x80);
+ } else {
+ c = oc;
+ }
+ ccount[c]++; /* Update counter for this bin */
+ totalc++;
+
+ /* Update inside / outside circle counts for Monte Carlo
+ computation of PI */
+
+ if (bean == 0) {
+ monte[mp++] = oc; /* Save character for Monte Carlo */
+ if (mp >= MONTEN) { /* Calculate every MONTEN character */
+ int mj;
+
+ mp = 0;
+ mcount++;
+ montex = montey = 0;
+ for (mj = 0; mj < MONTEN / 2; mj++) {
+ montex = (montex * 256.0) + monte[mj];
+ montey = (montey * 256.0) + monte[(MONTEN / 2) + mj];
+ }
+ if ((montex * montex + montey * montey) <= incirc) {
+ inmont++;
+ }
+ }
+ }
+
+ /* Update calculation of serial correlation coefficient */
+
+ sccun = c;
+ if (sccfirst) {
+ sccfirst = FALSE;
+ scclast = 0;
+ sccu0 = sccun;
+ } else {
+ scct1 = scct1 + scclast * sccun;
+ }
+ scct2 = scct2 + sccun;
+ scct3 = scct3 + (sccun * sccun);
+ scclast = sccun;
+ oc <<= 1;
+ } while (binary && (++bean < 8));
+ }
+}
+
+/* RT_END -- Complete calculation and return results. */
+
+void rt_end(double *r_ent, double *r_chisq, double *r_mean,
+ double *r_montepicalc, double *r_scc)
+{
+ int i;
+
+ /* Complete calculation of serial correlation coefficient */
+
+ scct1 = scct1 + scclast * sccu0;
+ scct2 = scct2 * scct2;
+ scc = totalc * scct3 - scct2;
+ if (scc == 0.0) {
+ scc = -100000;
+ } else {
+ scc = (totalc * scct1 - scct2) / scc;
+ }
+
+ /* Scan bins and calculate probability for each bin and
+ Chi-Square distribution. The probability will be reused
+ in the entropy calculation below. While we're at it,
+ we sum of all the data which will be used to compute the
+ mean. */
+
+ cexp = totalc / (binary ? 2.0 : 256.0); /* Expected count per bin */
+ for (i = 0; i < (binary ? 2 : 256); i++) {
+ double a = ccount[i] - cexp;;
+
+ prob[i] = ((double) ccount[i]) / totalc;
+ chisq += (a * a) / cexp;
+ datasum += ((double) i) * ccount[i];
+ }
+
+ /* Calculate entropy */
+
+ for (i = 0; i < (binary ? 2 : 256); i++) {
+ if (prob[i] > 0.0) {
+ ent += prob[i] * rt_log2(1 / prob[i]);
+ }
+ }
+
+ /* Calculate Monte Carlo value for PI from percentage of hits
+ within the circle */
+
+ montepi = 4.0 * (((double) inmont) / mcount);
+
+ /* Return results through arguments */
+
+ *r_ent = ent;
+ *r_chisq = chisq;
+ *r_mean = datasum / totalc;
+ *r_montepicalc = montepi;
+ *r_scc = scc;
+}
diff --git a/SoftHSMv2/src/lib/crypto/test/randtest.h b/SoftHSMv2/src/lib/crypto/test/randtest.h
new file mode 100644
index 0000000..53bef35
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/randtest.h
@@ -0,0 +1,13 @@
+/* This code was taken from http://www.fourmilab.ch/random/ where it states that:
+
+ This software is in the public domain. Permission to use, copy, modify, and distribute
+ this software and its documentation for any purpose and without fee is hereby granted,
+ without any conditions or restrictions. This software is provided “as is” without
+ express or implied warranty. */
+
+/* Random test function prototypes */
+
+extern void rt_init(int binmode);
+extern void rt_add(void *buf, int bufl);
+extern void rt_end(double *r_ent, double *r_chisq, double *r_mean,
+ double *r_montepicalc, double *r_scc);
diff --git a/SoftHSMv2/src/lib/data_mgr/ByteString.cpp b/SoftHSMv2/src/lib/data_mgr/ByteString.cpp
new file mode 100644
index 0000000..e133f71
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/ByteString.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ByteString.cpp
+
+ A string class for byte strings stored in securely allocated memory
+ *****************************************************************************/
+
+#include <algorithm>
+#include <string>
+#include <stdio.h>
+#include "config.h"
+#include "log.h"
+#include "ByteString.h"
+
+// Constructors
+ByteString::ByteString()
+{
+}
+
+ByteString::ByteString(const unsigned char* bytes, const size_t bytesLen)
+{
+ byteString.resize(bytesLen);
+
+ if (bytesLen > 0)
+ memcpy(&byteString[0], bytes, bytesLen);
+}
+
+ByteString::ByteString(const char* hexString)
+{
+ std::string hex = std::string(hexString);
+
+ if (hex.size() % 2 != 0)
+ {
+ hex = "0" + hex;
+ }
+
+ for (size_t i = 0; i < hex.size(); i += 2)
+ {
+ std::string byteStr;
+ byteStr += hex[i];
+ byteStr += hex[i+1];
+
+ unsigned char byteVal = (unsigned char) strtoul(byteStr.c_str(), NULL, 16);
+
+ this->operator+=(byteVal);
+ }
+}
+
+ByteString::ByteString(const unsigned long longValue)
+{
+ unsigned long setValue = longValue;
+
+ // Convert the value to a big-endian byte string; N.B.: this code assumes that unsigned long
+ // values are stored as a 64-bit value, which is a safe assumption on modern systems. It will
+ // also properly handle a 32-bit value and will simply store 4 zeroes at the front of the
+ // string. If at some point in time we get 128-bit architectures, the top 8 bytes of the value
+ // will be discarded... (but hey, 640K is enough for everybody, right?)
+ //
+ // The reason for coding it this way is that implementations of SoftHSM will maintain
+ // binary compatibility between eachothers background storage (i.e. a 32-bit SoftHSM version can
+ // read the storage of a 64-bit version and vice versa under the assumption that the stored
+ // values never exceed 32-bits, which is likely since these values are only used to encode
+ // byte string lengths)
+ unsigned char byteStrIn[8];
+
+ for (size_t i = 0; i < 8; i++)
+ {
+ byteStrIn[7-i] = (unsigned char) (setValue & 0xFF);
+ setValue >>= 8;
+ }
+
+ byteString.resize(8);
+ memcpy(&byteString[0], byteStrIn, 8);
+}
+
+ByteString::ByteString(const ByteString& in)
+{
+ this->byteString = in.byteString;
+}
+
+// Append data
+ByteString& ByteString::operator+=(const ByteString& append)
+{
+ size_t curLen = byteString.size();
+ size_t toAdd = append.byteString.size();
+ size_t newLen = curLen + toAdd;
+
+ byteString.resize(newLen);
+
+ if (toAdd > 0)
+ memcpy(&byteString[curLen], &append.byteString[0], toAdd);
+
+ return *this;
+}
+
+ByteString& ByteString::operator+=(const unsigned char byte)
+{
+ byteString.push_back(byte);
+
+ return *this;
+}
+
+// XORing
+ByteString& ByteString::operator^=(const ByteString& rhs)
+{
+ size_t xorLen = std::min(this->size(), rhs.size());
+
+ for (size_t i = 0; i < xorLen; i++)
+ {
+ byteString[i] ^= rhs.const_byte_str()[i];
+ }
+
+ return *this;
+}
+
+// Return a substring
+ByteString ByteString::substr(const size_t start, const size_t len /* = SIZE_T_MAX */) const
+{
+ size_t retLen = std::min(len, byteString.size() - start);
+
+ if (start >= byteString.size())
+ {
+ return ByteString();
+ }
+ else
+ {
+ return ByteString(&byteString[start], retLen);
+ }
+}
+
+// Add data
+ByteString operator+(const ByteString& lhs, const ByteString& rhs)
+{
+ ByteString rv = lhs;
+ rv += rhs;
+
+ return rv;
+}
+
+ByteString operator+(const unsigned char lhs, const ByteString& rhs)
+{
+ ByteString rv(&lhs, 1);
+ rv += rhs;
+
+ return rv;
+}
+
+ByteString operator+(const ByteString& lhs, const unsigned char rhs)
+{
+ ByteString rv = lhs;
+ rv += rhs;
+
+ return rv;
+}
+
+// Array operator
+unsigned char& ByteString::operator[](size_t pos)
+{
+ return byteString[pos];
+}
+
+// Return the byte string data
+unsigned char* ByteString::byte_str()
+{
+ return &byteString[0];
+}
+
+// Return the const byte string
+const unsigned char* ByteString::const_byte_str() const
+{
+ return (const unsigned char*) &byteString[0];
+}
+
+// Return a hexadecimal character representation of the string
+std::string ByteString::hex_str() const
+{
+ std::string rv;
+ char hex[3];
+
+ for (size_t i = 0; i < byteString.size(); i++)
+ {
+ sprintf(hex, "%02X", byteString[i]);
+
+ rv += hex;
+ }
+
+ return rv;
+}
+
+// Return the long value
+unsigned long ByteString::long_val() const
+{
+ // Convert the first 8 bytes of the string to an unsigned long value
+ unsigned long rv = 0;
+
+ for (size_t i = 0; i < std::min(size_t(8), byteString.size()); i++)
+ {
+ rv <<= 8;
+ rv += byteString[i];
+ }
+
+ return rv;
+}
+
+// Cut of the first part of the string and convert it to a long value
+unsigned long ByteString::firstLong()
+{
+ unsigned long rv = long_val();
+
+ split(8);
+
+ return rv;
+}
+
+// Split of the specified part of the string as a separate byte string
+ByteString ByteString::split(size_t len)
+{
+ ByteString rv = substr(0, len);
+
+ size_t newSize = (byteString.size() > len) ? (byteString.size() - len) : 0;
+
+ if (newSize > 0)
+ {
+ for (size_t i = 0; i < newSize; i++)
+ {
+ byteString[i] = byteString[i + len];
+ }
+ }
+
+ byteString.resize(newSize);
+
+ return rv;
+}
+
+// The size of the byte string in bits
+size_t ByteString::bits() const
+{
+ size_t bits = byteString.size() * 8;
+
+ if (bits == 0) return 0;
+
+ for (size_t i = 0; i < byteString.size(); i++)
+ {
+ unsigned char byte = byteString[i];
+
+ for (unsigned char mask = 0x80; mask > 0; mask >>= 1)
+ {
+ if ((byte & mask) == 0)
+ {
+ bits--;
+ }
+ else
+ {
+ return bits;
+ }
+ }
+ }
+
+ return bits;
+}
+
+// The size of the byte string in bytes
+size_t ByteString::size() const
+{
+ return byteString.size();
+}
+
+void ByteString::resize(const size_t newSize)
+{
+ byteString.resize(newSize);
+}
+
+void ByteString::wipe(const size_t newSize /* = 0 */)
+{
+ this->resize(newSize);
+
+ if (!byteString.empty())
+ memset(&byteString[0], 0x00, byteString.size());
+}
+
+// Comparison
+bool ByteString::operator==(const ByteString& compareTo) const
+{
+ if (compareTo.size() != this->size())
+ {
+ return false;
+ }
+ else if (this->size() == 0)
+ {
+ return true;
+ }
+
+ return (memcmp(&byteString[0], &compareTo.byteString[0], this->size()) == 0);
+}
+
+bool ByteString::operator!=(const ByteString& compareTo) const
+{
+ if (compareTo.size() != this->size())
+ {
+ return true;
+ }
+ else if (this->size() == 0)
+ {
+ return false;
+ }
+
+ return (memcmp(&byteString[0], &compareTo.byteString[0], this->size()) != 0);
+}
+
+// XOR data
+ByteString operator^(const ByteString& lhs, const ByteString& rhs)
+{
+ size_t xorLen = std::min(lhs.size(), rhs.size());
+ ByteString rv;
+
+ for (size_t i = 0; i < xorLen; i++)
+ {
+ rv += lhs.const_byte_str()[i] ^ rhs.const_byte_str()[i];
+ }
+
+ return rv;
+}
+
+// Serialisation/deserialisation
+ByteString ByteString::serialise() const
+{
+ ByteString len((unsigned long) size());
+
+ return len + *this;
+}
+
+/* static */ ByteString ByteString::chainDeserialise(ByteString& serialised)
+{
+ size_t len = (size_t) serialised.firstLong();
+
+ ByteString rv = serialised.split(len);
+
+ return rv;
+}
+
diff --git a/SoftHSMv2/src/lib/data_mgr/ByteString.h b/SoftHSMv2/src/lib/data_mgr/ByteString.h
new file mode 100644
index 0000000..2c2ef33
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/ByteString.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ByteString.h
+
+ A string class for byte strings stored in securely allocated memory
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BYTESTRING_H
+#define _SOFTHSM_V2_BYTESTRING_H
+
+#include <cstddef>
+#include <vector>
+#include <string>
+#include <stdlib.h>
+#include <limits.h>
+#include "config.h"
+#include "SecureAllocator.h"
+#include "Serialisable.h"
+
+#ifndef SIZE_T_MAX
+#define SIZE_T_MAX ((size_t) -1)
+#endif // !SIZE_T_MAX
+
+class ByteString
+{
+public:
+ // Constructors
+ ByteString();
+
+ ByteString(const unsigned char* bytes, const size_t bytesLen);
+
+ ByteString(const char* hexString);
+
+ ByteString(const unsigned long longValue);
+
+ ByteString(const ByteString& in);
+
+ // Destructor
+ virtual ~ByteString() { }
+
+ // Append data
+ ByteString& operator+=(const ByteString& append);
+ ByteString& operator+=(const unsigned char byte);
+
+ // Return a substring
+ ByteString substr(const size_t start, const size_t len = SIZE_T_MAX) const;
+
+ // Array operator
+ unsigned char& operator[](size_t pos);
+
+ // Return the byte string
+ unsigned char* byte_str();
+
+ // Return the const byte string
+ const unsigned char* const_byte_str() const;
+
+ // Return a hexadecimal character representation of the string
+ std::string hex_str() const;
+
+ // Return the long value
+ unsigned long long_val() const;
+
+ // Cut of the first part of the string and convert it to a long value
+ unsigned long firstLong();
+
+ // Split of the specified part of the string as a separate byte string
+ ByteString split(size_t len);
+
+ // Return the size in bits
+ size_t bits() const;
+
+ // Return the size in bytes
+ size_t size() const;
+
+ // Resize
+ void resize(const size_t newSize);
+
+ // Wipe
+ void wipe(const size_t newSize = 0);
+
+ // Comparison
+ bool operator==(const ByteString& compareTo) const;
+ bool operator!=(const ByteString& compareTo) const;
+
+ // XORing
+ ByteString& operator^=(const ByteString& rhs);
+
+ // Serialisation/deserialisation
+ virtual ByteString serialise() const;
+
+ static ByteString chainDeserialise(ByteString& serialised);
+
+private:
+ std::vector<unsigned char, SecureAllocator<unsigned char> > byteString;
+};
+
+// Add data
+ByteString operator+(const ByteString& lhs, const ByteString& rhs);
+ByteString operator+(const unsigned char lhs, const ByteString& rhs);
+ByteString operator+(const ByteString& lhs, const unsigned char rhs);
+
+// XOR data
+ByteString operator^(const ByteString& lhs, const ByteString& rhs);
+
+#endif // !_SOFTHSM_V2_BYTESTRING_H
+
diff --git a/SoftHSMv2/src/lib/data_mgr/Makefile.am b/SoftHSMv2/src/lib/data_mgr/Makefile.am
new file mode 100644
index 0000000..85aa4d7
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/Makefile.am
@@ -0,0 +1,17 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../pkcs11
+
+noinst_LTLIBRARIES = libsofthsm_datamgr.la
+libsofthsm_datamgr_la_SOURCES = ByteString.cpp \
+ RFC4880.cpp \
+ salloc.cpp \
+ SecureDataManager.cpp \
+ SecureMemoryRegistry.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/data_mgr/RFC4880.cpp b/SoftHSMv2/src/lib/data_mgr/RFC4880.cpp
new file mode 100644
index 0000000..9ea23bd
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/RFC4880.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RFC4880.cpp
+
+ Implements a secure password-based key derivation scheme. It is not a generic
+ implementation of the RFC but only generates 256-bit AES keys according to
+ the "iterated and salted" scheme.
+ *****************************************************************************/
+
+#include "config.h"
+#include "RFC4880.h"
+#include "CryptoFactory.h"
+#include "HashAlgorithm.h"
+
+// This function derives a 256-bit AES key from the supplied password data
+bool RFC4880::PBEDeriveKey(const ByteString& password, ByteString& salt, AESKey** ppKey)
+{
+ // Check that a proper salt value was supplied; it should be at least 8 bytes long
+ if (salt.size() < 8)
+ {
+ ERROR_MSG("Insufficient salt data supplied for password-based encryption");
+
+ return false;
+ }
+
+ // Check other parameters
+ if ((password.size() == 0) || (ppKey == NULL))
+ {
+ return false;
+ }
+
+ // Determine the iteration count based on the last byte of the salt
+ unsigned int iter = PBE_ITERATION_BASE_COUNT + salt[salt.size() - 1];
+
+ // Get a hash instance
+ HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA256);
+
+ if (hash == NULL)
+ {
+ ERROR_MSG("Could not get a SHA-256 instance");
+
+ return false;
+ }
+
+ // Perform the first iteration which takes as input the salt value and
+ // the password
+ ByteString intermediate;
+
+ if (!hash->hashInit() ||
+ !hash->hashUpdate(salt) ||
+ !hash->hashUpdate(password) ||
+ !hash->hashFinal(intermediate))
+ {
+ ERROR_MSG("Hashing failed");
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ return false;
+ }
+
+ // Perform the remaining iteration
+ while (--iter > 0)
+ {
+ if (!hash->hashInit() ||
+ !hash->hashUpdate(intermediate) ||
+ !hash->hashFinal(intermediate))
+ {
+ ERROR_MSG("Hashing failed");
+
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ return false;
+ }
+ }
+
+ // Create the AES key instance
+ *ppKey = new AESKey(256);
+ (*ppKey)->setKeyBits(intermediate);
+
+ // Release the hash instance
+ CryptoFactory::i()->recycleHashAlgorithm(hash);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/data_mgr/RFC4880.h b/SoftHSMv2/src/lib/data_mgr/RFC4880.h
new file mode 100644
index 0000000..7967ef6
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/RFC4880.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RFC4880.h
+
+ Implements a secure password-based key derivation scheme. It is not a generic
+ implementation of the RFC but only generates 256-bit AES keys according to
+ the "iterated and salted" scheme.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RFC4880_H
+#define _SOFTHSM_V2_RFC4880_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "log.h"
+#include "AESKey.h"
+
+// This define sets the base PBE iteration count; the lowest byte of the salt is added
+// to this value as a form of jitter
+#define PBE_ITERATION_BASE_COUNT 1500
+
+namespace RFC4880
+{
+ // This function derives a 256-bit AES key from the supplied password data
+ bool PBEDeriveKey(const ByteString& password, ByteString& salt, AESKey** ppKey);
+}
+
+#endif // !_SOFTHSM_V2_RFC4880_H
+
diff --git a/SoftHSMv2/src/lib/data_mgr/SecureAllocator.h b/SoftHSMv2/src/lib/data_mgr/SecureAllocator.h
new file mode 100644
index 0000000..71dc80c
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/SecureAllocator.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureAllocator.h
+
+ Implements a template class for a secure C++ allocator. The allocator will
+ zero all the memory it allocates before releasing it to ensure that the
+ data stored in the memory is destroyed properly to minimise the risk of
+ obtaining sensitive data from memory
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SECUREALLOCATOR_H
+#define _SOFTHSM_V2_SECUREALLOCATOR_H
+
+#include <limits>
+#include <stdlib.h>
+#include <string.h>
+#if defined(SENSITIVE_NON_PAGED) && !defined(_WIN32)
+#include <sys/mman.h>
+#endif // SENSITIVE_NON_PAGED
+#include "config.h"
+#include "log.h"
+#include "SecureMemoryRegistry.h"
+
+template<class T> class SecureAllocator
+{
+public:
+ // Member types
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef const T* const_pointer;
+ typedef const T& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ // Rebind to another type
+ template<class U> struct rebind
+ {
+ typedef SecureAllocator<U> other;
+ };
+
+ // Constructor
+ inline SecureAllocator() { }
+
+ inline SecureAllocator(const SecureAllocator&) { }
+
+ template<class U> SecureAllocator(const SecureAllocator<U>&) { }
+
+ // Destructor
+ inline virtual ~SecureAllocator() { }
+
+ // Return the maximum allocation size
+ size_type max_size() const
+ {
+ return std::numeric_limits<std::size_t>::max() / sizeof(T);
+ }
+
+ // Return the address of values
+ inline pointer address(reference value) const
+ {
+ return &value;
+ }
+
+ inline const_pointer address(const_reference value) const
+ {
+ return &value;
+ }
+
+ // Allocate n elements of type T
+ inline pointer allocate(size_type n, const void* = NULL)
+ {
+#ifdef SENSITIVE_NON_PAGED
+ // Allocate memory on a page boundary
+#ifndef _WIN32
+ pointer r = (pointer) valloc(n * sizeof(T));
+#else
+ pointer r = (pointer) VirtualAlloc(NULL, n * sizeof(T), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#endif
+
+ if (r == NULL)
+ {
+ ERROR_MSG("Out of memory");
+
+ return NULL;
+ }
+
+ // Lock the memory so it doesn't get swapped out
+#ifndef _WIN32
+ if (mlock((const void*) r, n * sizeof(T)) != 0)
+#else
+ if (VirtualLock((const void*) r, n * sizeof(T)) == 0)
+#endif
+ {
+ ERROR_MSG("Could not allocate non-paged memory for secure storage");
+
+ // Hmmm... best to not return any allocated space in this case
+#ifndef _WIN32
+ free(r);
+#else
+ VirtualFree((const void*) r, MEM_RELEASE);
+#endif
+
+ return NULL;
+ }
+
+ // Register the memory in the secure memory registry
+ SecureMemoryRegistry::i()->add(r, n * sizeof(T));
+
+ return r;
+#else
+ pointer r = (pointer)(::operator new(n * sizeof(T)));
+
+ if (r == NULL)
+ {
+ ERROR_MSG("Out of memory");
+
+ return NULL;
+ }
+
+ // Register the memory in the secure memory registry
+ SecureMemoryRegistry::i()->add(r, n * sizeof(T));
+
+ return r;
+#endif // SENSITIVE_NON_PAGED
+ }
+
+ // Deallocate n elements of type T
+ inline void deallocate(pointer p, size_type n)
+ {
+#ifdef PARANOID
+ // First toggle all bits on
+ memset(p, 0xFF, n * sizeof(T));
+#endif // PARANOID
+
+ // Toggle all bits off
+ memset(p, 0x00, n * sizeof(T));
+
+ // Unregister the memory from the secure memory registry
+ SecureMemoryRegistry::i()->remove(p);
+
+#ifdef SENSITIVE_NON_PAGED
+#ifndef _WIN32
+ munlock((const void*) p, n * sizeof(T));
+#else
+ VirtualUnlock((const void*) p, n * sizeof(T));
+#endif
+
+#ifndef _WIN32
+ free(p);
+#else
+ VirtualFree((const void*) r, MEM_RELEASE);
+#endif
+#else
+ // Release the memory
+ ::operator delete((void*) p);
+#endif // SENSITIVE_NON_PAGED
+ }
+
+ // Initialise allocate storage with a value
+ void construct(pointer p, const T& value)
+ {
+ new((void*) p)T(value);
+ }
+
+ // Destroy elements of initialised storage
+ void destroy(pointer p)
+ {
+ // Call destructor
+ p->~T();
+ }
+
+ // Comparison operators
+ inline bool operator==(SecureAllocator const&) const { return true; }
+ inline bool operator!=(SecureAllocator const&) const { return false; }
+};
+
+#endif // !_SOFTHSM_V2_SECUREALLOCATOR_H
+
diff --git a/SoftHSMv2/src/lib/data_mgr/SecureDataManager.cpp b/SoftHSMv2/src/lib/data_mgr/SecureDataManager.cpp
new file mode 100644
index 0000000..987e76b
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/SecureDataManager.cpp
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureDataManager.cpp
+
+ The secure data manager main class. Every token instance has a secure data
+ manager instance member that is used to decrypt and encrypt sensitive object
+ attributes such as key material. The secure data manager maintains a key blob
+ containing a 256-bit AES key that is used in this decryption and encryption
+ process. The key blob itself is encrypted using a PBE derived key that is
+ derived from the user PIN and a PBE key that is derived from the SO PIN. It
+ is up to the token to enforce access control based on which user is logged
+ in; authentication using the SO PIN is required to be able to change the
+ user PIN. The master key that is used to decrypt/encrypt sensitive attributes
+ is stored in memory under a mask that is changed every time the key is used.
+ *****************************************************************************/
+
+#include "config.h"
+#include "SecureDataManager.h"
+#include "CryptoFactory.h"
+#include "AESKey.h"
+#include "SymmetricAlgorithm.h"
+#include "RFC4880.h"
+
+// Constructors
+
+// Initialise the object; called by all constructors
+void SecureDataManager::initObject()
+{
+ // Get an RNG instance
+ rng = CryptoFactory::i()->getRNG();
+
+ // Get an AES implementation
+ aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
+
+ // Initialise masking data
+ mask = new ByteString();
+
+ rng->generateRandom(*mask, 32);
+
+ // Set the initial login state
+ soLoggedIn = userLoggedIn = false;
+
+ // Set the magic
+ magic = ByteString("524A52"); // RJR
+
+ // Get a mutex
+ dataMgrMutex = MutexFactory::i()->getMutex();
+}
+
+// Constructs a new SecureDataManager for a blank token; actual
+// initialisation is done by setting the SO PIN
+SecureDataManager::SecureDataManager()
+{
+ initObject();
+}
+
+// Constructs a SecureDataManager using the specified key blob
+SecureDataManager::SecureDataManager(const ByteString& soPINBlob, const ByteString& userPINBlob)
+{
+ initObject();
+
+ // De-serialise the key blob
+ soEncryptedKey = soPINBlob;
+ userEncryptedKey = userPINBlob;
+}
+
+// Destructor
+SecureDataManager::~SecureDataManager()
+{
+ // Recycle the AES instance
+ CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
+
+ // Clean up the mask
+ delete mask;
+
+ MutexFactory::i()->recycleMutex(dataMgrMutex);
+}
+
+// Generic function for creating an encrypted version of the key from the specified passphrase
+bool SecureDataManager::pbeEncryptKey(const ByteString& passphrase, ByteString& encryptedKey)
+{
+ // Generate salt
+ ByteString salt;
+
+ if (!rng->generateRandom(salt, 8)) return false;
+
+ // Derive the key using RFC4880 PBE
+ AESKey* pbeKey = NULL;
+
+ if (!RFC4880::PBEDeriveKey(passphrase, salt, &pbeKey))
+ {
+ return false;
+ }
+
+ // Add the salt
+ encryptedKey.wipe();
+ encryptedKey += salt;
+
+ // Generate random IV
+ ByteString IV;
+
+ if (!rng->generateRandom(IV, aes->getBlockSize())) return false;
+
+ // Add the IV
+ encryptedKey += IV;
+
+ // Encrypt the data
+ ByteString block;
+
+ if (!aes->encryptInit(pbeKey, SymMode::CBC, IV))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ // First, add the magic
+ if (!aes->encryptUpdate(magic, block))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ encryptedKey += block;
+
+ // Then, add the key itself
+ ByteString key;
+
+ {
+ MutexLocker lock(dataMgrMutex);
+
+ unmask(key);
+
+ bool rv = aes->encryptUpdate(key, block);
+
+ remask(key);
+
+ if (!rv)
+ {
+ delete pbeKey;
+
+ return false;
+ }
+ }
+
+ encryptedKey += block;
+
+ // And finalise encryption
+ if (!aes->encryptFinal(block))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ encryptedKey += block;
+
+ delete pbeKey;
+
+ return true;
+}
+
+// Set the SO PIN (requires either a blank SecureDataManager or the
+// SO to have logged in previously)
+bool SecureDataManager::setSOPIN(const ByteString& soPIN)
+{
+ // Check the new PIN
+ if (soPIN.size() == 0)
+ {
+ DEBUG_MSG("Zero length PIN specified");
+
+ return false;
+ }
+
+ // Check if the SO needs to be logged in
+ if ((soEncryptedKey.size() > 0) && !soLoggedIn)
+ {
+ DEBUG_MSG("SO must be logged in to change the SO PIN");
+
+ return false;
+ }
+
+ // If no SO PIN was set, then this is a SecureDataManager for a blank token. This
+ // means a new key has to be generated
+ if (soEncryptedKey.size() == 0)
+ {
+ ByteString key;
+
+ rng->generateRandom(key, 32);
+
+ remask(key);
+ }
+
+ return pbeEncryptKey(soPIN, soEncryptedKey);
+}
+
+// Set the user PIN (requires either the SO or the user to have logged
+// in previously)
+bool SecureDataManager::setUserPIN(const ByteString& userPIN)
+{
+ // Check if the SO or the user is logged in
+ if (!soLoggedIn && !userLoggedIn)
+ {
+ DEBUG_MSG("Must be logged in to change the user PIN");
+
+ return false;
+ }
+
+ // Check the new PIN
+ if (userPIN.size() == 0)
+ {
+ DEBUG_MSG("Zero length PIN specified");
+
+ return false;
+ }
+
+ return pbeEncryptKey(userPIN, userEncryptedKey);
+}
+
+// Generic login function
+bool SecureDataManager::login(const ByteString& passphrase, const ByteString& encryptedKey)
+{
+ // Log out first
+ this->logout();
+
+ // First, take the salt from the encrypted key
+ ByteString salt = encryptedKey.substr(0,8);
+
+ // Then, take the IV from the encrypted key
+ ByteString IV = encryptedKey.substr(8, aes->getBlockSize());
+
+ // Now, take the encrypted data from the encrypted key
+ ByteString encryptedKeyData = encryptedKey.substr(8 + aes->getBlockSize());
+
+ // Derive the PBE key
+ AESKey* pbeKey = NULL;
+
+ if (!RFC4880::PBEDeriveKey(passphrase, salt, &pbeKey))
+ {
+ return false;
+ }
+
+ // Decrypt the key data
+ ByteString decryptedKeyData;
+ ByteString finalBlock;
+
+ // NOTE: The login will fail here if incorrect passphrase is supplied
+ if (!aes->decryptInit(pbeKey, SymMode::CBC, IV) ||
+ !aes->decryptUpdate(encryptedKeyData, decryptedKeyData) ||
+ !aes->decryptFinal(finalBlock))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ delete pbeKey;
+
+ decryptedKeyData += finalBlock;
+
+ // Check the magic
+ if (decryptedKeyData.substr(0, 3) != magic)
+ {
+ // The passphrase was incorrect
+ DEBUG_MSG("Incorrect passphrase supplied");
+
+ return false;
+ }
+
+ // Strip off the magic
+ ByteString key = decryptedKeyData.substr(3);
+
+ // And mask the key
+ decryptedKeyData.wipe();
+
+ MutexLocker lock(dataMgrMutex);
+ remask(key);
+
+ return true;
+}
+
+// Log in using the SO PIN
+bool SecureDataManager::loginSO(const ByteString& soPIN)
+{
+ return (soLoggedIn = login(soPIN, soEncryptedKey));
+}
+
+// Log in using the user PIN
+bool SecureDataManager::loginUser(const ByteString& userPIN)
+{
+ return (userLoggedIn = login(userPIN, userEncryptedKey));
+}
+
+// Generic re-authentication function
+bool SecureDataManager::reAuthenticate(const ByteString& passphrase, const ByteString& encryptedKey)
+{
+ // First, take the salt from the encrypted key
+ ByteString salt = encryptedKey.substr(0,8);
+
+ // Then, take the IV from the encrypted key
+ ByteString IV = encryptedKey.substr(8, aes->getBlockSize());
+
+ // Now, take the encrypted data from the encrypted key
+ ByteString encryptedKeyData = encryptedKey.substr(8 + aes->getBlockSize());
+
+ // Derive the PBE key
+ AESKey* pbeKey = NULL;
+
+ if (!RFC4880::PBEDeriveKey(passphrase, salt, &pbeKey))
+ {
+ return false;
+ }
+
+ // Decrypt the key data
+ ByteString decryptedKeyData;
+ ByteString finalBlock;
+
+ // NOTE: The login will fail here if incorrect passphrase is supplied
+ if (!aes->decryptInit(pbeKey, SymMode::CBC, IV) ||
+ !aes->decryptUpdate(encryptedKeyData, decryptedKeyData) ||
+ !aes->decryptFinal(finalBlock))
+ {
+ delete pbeKey;
+
+ return false;
+ }
+
+ delete pbeKey;
+
+ decryptedKeyData += finalBlock;
+
+ // Check the magic
+ if (decryptedKeyData.substr(0, 3) != magic)
+ {
+ // The passphrase was incorrect
+ DEBUG_MSG("Incorrect passphrase supplied");
+
+ return false;
+ }
+
+ // And mask the key
+ decryptedKeyData.wipe();
+
+ return true;
+}
+
+// Re-authenticate the SO
+bool SecureDataManager::reAuthenticateSO(const ByteString& soPIN)
+{
+ return reAuthenticate(soPIN, soEncryptedKey);
+}
+
+// Re-authenticate the user
+bool SecureDataManager::reAuthenticateUser(const ByteString& userPIN)
+{
+ return reAuthenticate(userPIN, userEncryptedKey);
+}
+
+// Log out
+void SecureDataManager::logout()
+{
+ MutexLocker lock(dataMgrMutex);
+
+ // Clear the logged in state
+ soLoggedIn = userLoggedIn = false;
+
+ // Clear the masked key
+ maskedKey.wipe();
+}
+
+// Decrypt the supplied data
+bool SecureDataManager::decrypt(const ByteString& encrypted, ByteString& plaintext)
+{
+ // Check the object logged in state
+ if ((!userLoggedIn && !soLoggedIn) || (maskedKey.size() != 32))
+ {
+ return false;
+ }
+
+ // Do not attempt decryption of empty byte strings
+ if (encrypted.size() == 0)
+ {
+ plaintext = ByteString("");
+ return true;
+ }
+
+ AESKey theKey(256);
+ ByteString unmaskedKey;
+
+ {
+ MutexLocker lock(dataMgrMutex);
+
+ unmask(unmaskedKey);
+
+ theKey.setKeyBits(unmaskedKey);
+
+ remask(unmaskedKey);
+ }
+
+ // Take the IV from the input data
+ ByteString IV = encrypted.substr(0, aes->getBlockSize());
+
+ if (IV.size() != aes->getBlockSize())
+ {
+ ERROR_MSG("Invalid IV in encrypted data");
+
+ return false;
+ }
+
+ ByteString finalBlock;
+
+ if (!aes->decryptInit(&theKey, SymMode::CBC, IV) ||
+ !aes->decryptUpdate(encrypted.substr(aes->getBlockSize()), plaintext) ||
+ !aes->decryptFinal(finalBlock))
+ {
+ return false;
+ }
+
+ plaintext += finalBlock;
+
+ return true;
+}
+
+// Encrypt the supplied data
+bool SecureDataManager::encrypt(const ByteString& plaintext, ByteString& encrypted)
+{
+ // Check the object logged in state
+ if ((!userLoggedIn && !soLoggedIn) || (maskedKey.size() != 32))
+ {
+ return false;
+ }
+
+ AESKey theKey(256);
+ ByteString unmaskedKey;
+
+ {
+ MutexLocker lock(dataMgrMutex);
+
+ unmask(unmaskedKey);
+
+ theKey.setKeyBits(unmaskedKey);
+
+ remask(unmaskedKey);
+ }
+
+ // Wipe encrypted data block
+ encrypted.wipe();
+
+ // Generate random IV
+ ByteString IV;
+
+ if (!rng->generateRandom(IV, aes->getBlockSize())) return false;
+
+ ByteString finalBlock;
+
+ if (!aes->encryptInit(&theKey, SymMode::CBC, IV) ||
+ !aes->encryptUpdate(plaintext, encrypted) ||
+ !aes->encryptFinal(finalBlock))
+ {
+ return false;
+ }
+
+ encrypted += finalBlock;
+
+ // Add IV to output data
+ encrypted = IV + encrypted;
+
+ return true;
+}
+
+// Returns the key blob for the SO PIN
+ByteString SecureDataManager::getSOPINBlob()
+{
+ return soEncryptedKey;
+}
+
+// Returns the key blob for the user PIN
+ByteString SecureDataManager::getUserPINBlob()
+{
+ return userEncryptedKey;
+}
+
+// Unmask the key
+void SecureDataManager::unmask(ByteString& key)
+{
+ key = maskedKey;
+ key ^= *mask;
+}
+
+// Remask the key
+void SecureDataManager::remask(ByteString& key)
+{
+ // Generate a new mask
+ rng->generateRandom(*mask, 32);
+
+ key ^= *mask;
+ maskedKey = key;
+}
+
+// Check if the SO is logged in
+bool SecureDataManager::isSOLoggedIn()
+{
+ return soLoggedIn;
+}
+
+// Check if the user is logged in
+bool SecureDataManager::isUserLoggedIn()
+{
+ return userLoggedIn;
+}
+
diff --git a/SoftHSMv2/src/lib/data_mgr/SecureDataManager.h b/SoftHSMv2/src/lib/data_mgr/SecureDataManager.h
new file mode 100644
index 0000000..93d99bc
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/SecureDataManager.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureDataManager.h
+
+ The secure data manager main class. Every token instance has a secure data
+ manager instance member that is used to decrypt and encrypt sensitive object
+ attributes such as key material. The secure data manager maintains a key blob
+ containing a 256-bit AES key that is used in this decryption and encryption
+ process. The key blob itself is encrypted using a PBE derived key that is
+ derived from the user PIN and a PBE key that is derived from the SO PIN. It
+ is up to the token to enforce access control based on which user is logged
+ in; authentication using the SO PIN is required to be able to change the
+ user PIN. The master key that is used to decrypt/encrypt sensitive attributes
+ is stored in memory under a mask that is changed every time the key is used.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SECUREDATAMANAGER_H
+#define _SOFTHSM_V2_SECUREDATAMANAGER_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "log.h"
+#include "AESKey.h"
+#include "RNG.h"
+#include "SymmetricAlgorithm.h"
+#include "MutexFactory.h"
+
+class SecureDataManager
+{
+public:
+ // Constructors
+
+ // Constructs a new SecureDataManager for a blank token; actual
+ // initialisation is done by setting the SO PIN
+ SecureDataManager();
+
+ // Constructs a SecureDataManager using the specified SO PIN and user PIN
+ SecureDataManager(const ByteString& soPINBlob, const ByteString& userPINBlob);
+
+ // Destructor
+ virtual ~SecureDataManager();
+
+ // Set the SO PIN (requires either a blank SecureDataManager or the
+ // SO to have logged in previously)
+ bool setSOPIN(const ByteString& soPIN);
+
+ // Set the user PIN (requires either the SO or the user to have logged
+ // in previously)
+ bool setUserPIN(const ByteString& userPIN);
+
+ // Log in using the SO PIN
+ bool loginSO(const ByteString& soPIN);
+ bool isSOLoggedIn();
+
+ // Log in using the user PIN
+ bool loginUser(const ByteString& userPIN);
+ bool isUserLoggedIn();
+
+ // Re-authentication
+ bool reAuthenticateSO(const ByteString& soPIN);
+ bool reAuthenticateUser(const ByteString& userPIN);
+
+ // Log out
+ void logout();
+
+ // Decrypt the supplied data
+ bool decrypt(const ByteString& encrypted, ByteString& plaintext);
+
+ // Encrypt the supplied data
+ bool encrypt(const ByteString& plaintext, ByteString& encrypted);
+
+ // Returns the key blob for the SO PIN
+ ByteString getSOPINBlob();
+
+ // Returns the key blob for the user PIN
+ ByteString getUserPINBlob();
+
+private:
+ // Initialise the object
+ void initObject();
+
+ // Generic login function
+ bool login(const ByteString& passphrase, const ByteString& encryptedKey);
+
+ // Generic re-authentication function
+ bool reAuthenticate(const ByteString& passphrase, const ByteString& encryptedKey);
+
+ // Generic function for creating an encrypted version of the key from the specified passphrase
+ bool pbeEncryptKey(const ByteString& passphrase, ByteString& encryptedKey);
+
+ // Unmask the key
+ void unmask(ByteString& key);
+
+ // Remask the key
+ void remask(ByteString& key);
+
+ // The user PIN encrypted key
+ ByteString userEncryptedKey;
+
+ // The SO PIN encrypted key
+ ByteString soEncryptedKey;
+
+ // Which users are logged in
+ bool soLoggedIn;
+ bool userLoggedIn;
+
+ // The masked version of the actual key
+ ByteString maskedKey;
+
+ // The "magic" data used to detect if a PIN was likely to be correct
+ ByteString magic;
+
+ // The mask; this is not a stack member but a heap member. This
+ // hopefully ensures that the mask ends up in a memory location
+ // that is not logically linked to the masked key
+ ByteString* mask;
+
+ // Random number generator instance
+ RNG* rng;
+
+ // AES instance
+ SymmetricAlgorithm* aes;
+
+ // Mutex
+ Mutex* dataMgrMutex;
+};
+
+#endif // !_SOFTHSM_V2_SECUREDATAMANAGER_H
+
diff --git a/SoftHSMv2/src/lib/data_mgr/SecureMemoryRegistry.cpp b/SoftHSMv2/src/lib/data_mgr/SecureMemoryRegistry.cpp
new file mode 100644
index 0000000..57de156
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/SecureMemoryRegistry.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureMemoryRegistry.cpp
+
+ Implements a singleton class that keeps track of all securely allocated
+ memory. This registry can be used to wipe securely allocated memory in case
+ of a fatal exception
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "log.h"
+#include "SecureMemoryRegistry.h"
+
+// Constructor
+SecureMemoryRegistry::SecureMemoryRegistry()
+{
+ SecMemRegistryMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+SecureMemoryRegistry::~SecureMemoryRegistry()
+{
+ if (!registry.empty())
+ {
+ ERROR_MSG("SecureMemoryRegistry is not empty: leak!");
+ }
+ MutexFactory::i()->recycleMutex(SecMemRegistryMutex);
+}
+
+// Return the one-and-only instance
+SecureMemoryRegistry* SecureMemoryRegistry::i()
+{
+ if (instance.get() == NULL)
+ {
+ instance.reset(new SecureMemoryRegistry());
+
+ if (instance.get() == NULL)
+ {
+ // This is very bad!
+ ERROR_MSG("failed to instantiate SecureMemoryRegistry");
+
+ }
+ }
+
+ return instance.get();
+}
+
+// This will destroy the one-and-only instance.
+void SecureMemoryRegistry::reset()
+{
+ instance.reset();
+}
+
+// Register a block of memory
+void SecureMemoryRegistry::add(void* pointer, size_t blocksize)
+{
+ MutexLocker lock(SecMemRegistryMutex);
+
+ registry[pointer] = blocksize;
+
+ //DEBUG_MSG("Registered block of %d bytes at 0x%x", blocksize, pointer);
+}
+
+// Unregister a block of memory
+size_t SecureMemoryRegistry::remove(void* pointer)
+{
+ //DEBUG_MSG("Unregistered block of %d bytes at 0x%x", registry[pointer], pointer);
+
+ MutexLocker lock(SecMemRegistryMutex);
+
+ size_t rv = registry[pointer];
+
+ registry.erase(pointer);
+
+ return rv;
+}
+
+// Wipe all registered blocks of memory
+void SecureMemoryRegistry::wipe()
+{
+ MutexLocker lock(SecMemRegistryMutex);
+
+ // Be very careful in this method to catch any weird exceptions that
+ // may occur since if we're in this method it means something has already
+ // gone pear shaped once before and we're exiting on a fatal exception
+ try
+ {
+ for (std::map<void*, size_t>::iterator i = registry.begin(); i != registry.end(); i++)
+ {
+ try
+ {
+ DEBUG_MSG("Wiping block of %d bytes at 0x%x", i->second, i->first);
+ }
+ catch (...)
+ {
+ }
+
+ try
+ {
+ #ifdef PARANOID
+ memset(i->first, 0xFF, i->second);
+ #endif // PARANOID
+ memset(i->first, 0x00, i->second);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to wipe block of %d bytes at 0x%x", i->second, i->first);
+ }
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Failed to enumerate the secure memory registry");
+ }
+}
+
diff --git a/SoftHSMv2/src/lib/data_mgr/SecureMemoryRegistry.h b/SoftHSMv2/src/lib/data_mgr/SecureMemoryRegistry.h
new file mode 100644
index 0000000..6c73369
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/SecureMemoryRegistry.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureMemoryRegistry.h
+
+ Implements a singleton class that keeps track of all securely allocated
+ memory. This registry can be used to wipe securely allocated memory in case
+ of a fatal exception
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SECUREMEMORYREGISTRY_H
+#define _SOFTHSM_V2_SECUREMEMORYREGISTRY_H
+
+#include <stdlib.h>
+#include <map>
+#include <memory>
+#include "MutexFactory.h"
+
+class SecureMemoryRegistry
+{
+public:
+ SecureMemoryRegistry();
+
+ virtual ~SecureMemoryRegistry();
+
+ static SecureMemoryRegistry* i();
+
+ static void reset();
+
+ void add(void* pointer, size_t blocksize);
+
+ size_t remove(void* pointer);
+
+ void wipe();
+
+private:
+#ifdef HAVE_CXX11
+ static std::unique_ptr<SecureMemoryRegistry> instance;
+#else
+ static std::auto_ptr<SecureMemoryRegistry> instance;
+#endif
+
+ std::map<void*, size_t> registry;
+
+ Mutex* SecMemRegistryMutex;
+};
+
+#endif // !_SOFTHSM_V2_SECUREMEMORYREGISTRY_H
+
diff --git a/SoftHSMv2/src/lib/data_mgr/salloc.cpp b/SoftHSMv2/src/lib/data_mgr/salloc.cpp
new file mode 100644
index 0000000..0bd4238
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/salloc.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ salloc.cpp
+
+ Contains an implementation of malloc that allocates memory securely
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "salloc.h"
+#include <limits>
+#if defined(SENSITIVE_NON_PAGED) && !defined(_WIN32)
+#include <sys/mman.h>
+#endif // SENSITIVE_NON_PAGED
+#include <string.h>
+#include "SecureMemoryRegistry.h"
+
+// Allocate memory
+void* salloc(size_t len)
+{
+#ifdef SENSITIVE_NON_PAGED
+ // Allocate memory on a page boundary
+#ifndef _WIN32
+ void* ptr = (void*) valloc(len);
+#else
+ pointer r = (pointer) VirtualAlloc(NULL, n * sizeof(T), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#endif
+
+ if (ptr == NULL)
+ {
+ ERROR_MSG("Out of memory");
+
+ return NULL;
+ }
+
+ // Lock the memory so it doesn't get swapped out
+#ifndef _WIN32
+ if (mlock((const void*) ptr, len) != 0)
+#else
+ if (VirtualLock((const void*) r, n * sizeof(T)) == 0)
+#endif
+ {
+ ERROR_MSG("Could not allocate non-paged memory for secure storage");
+
+ // Hmmm... best to not return any allocated space in this case
+#ifndef _WIN32
+ free(ptr);
+#else
+ VirtualFree((const void*) pre, MEM_RELEASE);
+#endif
+
+ return NULL;
+ }
+
+ // Register the memory in the secure memory registry
+ SecureMemoryRegistry::i()->add(ptr, len);
+
+ return ptr;
+#else
+ void* ptr = (void*) malloc(len);
+
+ if (ptr == NULL)
+ {
+ ERROR_MSG("Out of memory");
+
+ return NULL;
+ }
+
+ // Register the memory in the secure memory registry
+ SecureMemoryRegistry::i()->add(ptr, len);
+
+ return ptr;
+#endif // SENSITIVE_NON_PAGED
+}
+
+// Free memory
+void sfree(void* ptr)
+{
+ // Unregister the memory from the secure memory registry
+ size_t len = SecureMemoryRegistry::i()->remove(ptr);
+
+#ifdef PARANOID
+ // First toggle all bits on
+ memset(ptr, 0xFF, len);
+#endif // PARANOID
+
+ // Toggle all bits off
+ memset(ptr, 0x00, len);
+
+#ifdef SENSITIVE_NON_PAGED
+#ifndef _WIN32
+ munlock((const void*) ptr, len);
+#else
+ VirtualFree((const void*) pre, MEM_RELEASE);
+#endif
+
+#endif // SENSITIVE_NON_PAGED
+
+ free(ptr);
+}
+
diff --git a/SoftHSMv2/src/lib/data_mgr/salloc.h b/SoftHSMv2/src/lib/data_mgr/salloc.h
new file mode 100644
index 0000000..cfd92fe
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/salloc.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ salloc.h
+
+ Contains an implementation of malloc that allocates memory securely
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SALLOC_H
+#define _SOFTHSM_V2_SALLOC_H
+
+#include <stdlib.h>
+#include "config.h"
+#include "log.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/* Allocate memory */
+void* salloc(size_t len);
+
+/* Free memory */
+void sfree(void* ptr);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* !_SOFTHSM_V2_SALLOC_H */
+
diff --git a/SoftHSMv2/src/lib/data_mgr/test/ByteStringTests.cpp b/SoftHSMv2/src/lib/data_mgr/test/ByteStringTests.cpp
new file mode 100644
index 0000000..1c635a4
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/test/ByteStringTests.cpp
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ByteStringTests.cpp
+
+ Contains test cases to test the ByteString class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <string>
+#include "ByteStringTests.h"
+#include "ByteString.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ByteStringTests);
+
+void ByteStringTests::setUp()
+{
+}
+
+void ByteStringTests::tearDown()
+{
+ fflush(stdout);
+}
+
+void ByteStringTests::testIntegrity()
+{
+ unsigned char testData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
+
+ ByteString b(testData, sizeof(testData));
+
+ // Test if the right data is returned
+ CPPUNIT_ASSERT(memcmp(testData, b.byte_str(), sizeof(testData)) == 0);
+
+ // Test size
+ CPPUNIT_ASSERT(b.size() == sizeof(testData));
+
+ // Test the copy constructor
+ ByteString b2(b);
+
+ // Test using comparison operator
+ CPPUNIT_ASSERT(b == b2);
+
+ // Test using memcmp
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), b2.byte_str(), b.size()) == 0);
+
+ // Modify the copied version and test again
+ b2[1] = 0x20;
+
+ // Test using comparison operator
+ CPPUNIT_ASSERT(b != b2);
+
+ // Test using memcmp directly
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), b2.byte_str(), b.size()) != 0);
+
+ // Verify that b was not affected
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), testData, sizeof(testData)) == 0);
+
+ // Modify the source data and check if the array operator has functioned correctly
+ testData[1] = 0x20;
+
+ // Test if the right data is in b2
+ CPPUNIT_ASSERT(memcmp(b2.byte_str(), testData, sizeof(testData)) == 0);
+}
+
+void ByteStringTests::testAppend()
+{
+ unsigned char testData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
+
+ ByteString b;
+ ByteString b1(testData, sizeof(testData));
+
+ // Test that b is empty and b1 is not
+ CPPUNIT_ASSERT((b.size() == 0) && (b1.size() == sizeof(testData)));
+
+ // Append 1 byte to b
+ b += 0x01;
+
+ // Check the contents of b
+ CPPUNIT_ASSERT(b.size() == 1);
+ CPPUNIT_ASSERT(b[0] == 0x01);
+
+ // Append another byte to b
+ b += 0x02;
+
+ // Check the contents of b
+ CPPUNIT_ASSERT(b.size() == 2);
+ CPPUNIT_ASSERT((b[0] == 0x01) && (b[1] == 0x02));
+
+ // Append b1 to b
+ b += b1;
+
+ // Check the contents of b
+ CPPUNIT_ASSERT(b.size() == 2 + sizeof(testData));
+ CPPUNIT_ASSERT((b[0] == 0x01) && (b[1] == 0x02));
+ CPPUNIT_ASSERT(memcmp(&b[2], testData, sizeof(testData)) == 0);
+
+ // Append b to b
+ b += b;
+
+ // Check the contents of b
+ CPPUNIT_ASSERT(b.size() == 2 * (2 + sizeof(testData)));
+ CPPUNIT_ASSERT((b[0] == 0x01) && (b[1] == 0x02) &&
+ (b[(2 + sizeof(testData)) + 0] == 0x01) &&
+ (b[(2 + sizeof(testData)) + 1] == 0x02));
+ CPPUNIT_ASSERT((memcmp(&b[2], testData, sizeof(testData)) == 0) &&
+ (memcmp(&b[2 + 2 + sizeof(testData)], testData, sizeof(testData)) == 0));
+}
+
+void ByteStringTests::testSubstr()
+{
+ unsigned char testData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
+
+ ByteString b;
+ ByteString b1(testData, sizeof(testData));
+
+ // Take a substring
+ b = b1.substr(8, 4);
+
+ // Check b
+ CPPUNIT_ASSERT(b.size() == 4);
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), &testData[8], 4) == 0);
+
+ // Take another substring
+ b = b1.substr(8);
+
+ // Check b
+ CPPUNIT_ASSERT(b.size() == 8);
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), &testData[8], 8) == 0);
+
+ // Two substrings added should yield the original string
+ b = b1.substr(0, 8) + b1.substr(8);
+
+ // Check b
+ CPPUNIT_ASSERT(b.size() == sizeof(testData));
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), testData, sizeof(testData)) == 0);
+}
+
+void ByteStringTests::testFromHexStr()
+{
+ unsigned char testData[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
+
+ ByteString b("0102030405060708090a0b0c0d0e0f10");
+ ByteString b1("0102030405060708090A0B0C0D0E0F10");
+
+ CPPUNIT_ASSERT(memcmp(b.byte_str(), testData, sizeof(testData)) == 0);
+ CPPUNIT_ASSERT(memcmp(b1.byte_str(), testData, sizeof(testData)) == 0);
+}
+
+void ByteStringTests::testXOR()
+{
+ unsigned char left[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
+ unsigned char right[] = { 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10 };
+ unsigned char xorred[] = { 0x81, 0x72, 0x63, 0x54, 0x45, 0x36, 0x27, 0x18 };
+
+ ByteString l(left, 8);
+ ByteString r(right, 8);
+ ByteString x(xorred, 8);
+ ByteString xed;
+
+ xed = l ^ r;
+
+ CPPUNIT_ASSERT(xed == x);
+
+ ByteString l1(left, 8);
+ ByteString r1(right, 8);
+
+ l1 ^= r1;
+
+ CPPUNIT_ASSERT(l1 == x);
+
+ l1 ^= l;
+
+ CPPUNIT_ASSERT(l1 == r);
+
+ ByteString l_(left, 7);
+
+ xed = l_ ^ r;
+
+ CPPUNIT_ASSERT((xed.size() == 7) && (xed == x.substr(0, 7)));
+
+ ByteString r_(right, 7);
+
+ xed = l ^ r_;
+
+ CPPUNIT_ASSERT((xed.size() == 7) && (xed == x.substr(0, 7)));
+
+ ByteString l1_(left, 8);
+
+ l1_ ^= r_;
+
+ CPPUNIT_ASSERT((l1.size() == 8) && (l1_.substr(0, 7) == x.substr(0,7)) && (l1_[7] == l[7]));
+
+ ByteString l1__(left, 7);
+
+ l1__ ^= r;
+
+ CPPUNIT_ASSERT((l1__ == x.substr(0,7)) && (l1__.size() == 7));
+}
+
+void ByteStringTests::testToHexStr()
+{
+ ByteString b("0102030405060708090A0B0C0D0E0F");
+ ByteString b1("DEADBEEF");
+ ByteString b2("deadC0FFEE");
+
+ std::string s = b.hex_str();
+ std::string s1 = b1.hex_str();
+ std::string s2 = b2.hex_str();
+
+ CPPUNIT_ASSERT(s.compare("0102030405060708090A0B0C0D0E0F") == 0);
+ CPPUNIT_ASSERT(s1.compare("DEADBEEF") == 0);
+ CPPUNIT_ASSERT(s2.compare("DEADC0FFEE") == 0);
+}
+
+void ByteStringTests::testLongValues()
+{
+ unsigned long ul1 = 0x00112233;
+ unsigned long ul2 = 0x10203040;
+ unsigned long ul3 = 0xF0E0D0C0;
+
+ ByteString b1(ul1);
+ ByteString b2(ul2);
+ ByteString b3(ul3);
+
+ CPPUNIT_ASSERT(b1 == ByteString("0000000000112233"));
+ CPPUNIT_ASSERT(b2 == ByteString("0000000010203040"));
+ CPPUNIT_ASSERT(b3 == ByteString("00000000F0E0D0C0"));
+
+ CPPUNIT_ASSERT(b1.long_val() == ul1);
+ CPPUNIT_ASSERT(b2.long_val() == ul2);
+ CPPUNIT_ASSERT(b3.long_val() == ul3);
+
+ ByteString concat = b1 + b2 + b3;
+
+ CPPUNIT_ASSERT(concat == ByteString("0000000000112233000000001020304000000000F0E0D0C0"));
+
+ unsigned long ulr1 = concat.firstLong();
+
+ CPPUNIT_ASSERT(ulr1 == ul1);
+ CPPUNIT_ASSERT(concat == ByteString("000000001020304000000000F0E0D0C0"));
+
+ unsigned long ulr2 = concat.firstLong();
+
+ CPPUNIT_ASSERT(ulr2 == ul2);
+ CPPUNIT_ASSERT(concat == ByteString("00000000F0E0D0C0"));
+
+ unsigned long ulr3 = concat.firstLong();
+
+ CPPUNIT_ASSERT(ulr3 == ul3);
+ CPPUNIT_ASSERT(concat.size() == 0);
+
+ ByteString b4("ABCDEF");
+
+ CPPUNIT_ASSERT(b4.long_val() == 0xABCDEF);
+ CPPUNIT_ASSERT(b4.size() == 3);
+ CPPUNIT_ASSERT(b4.firstLong() == 0xABCDEF);
+ CPPUNIT_ASSERT(b4.size() == 0);
+}
+
+void ByteStringTests::testSplitting()
+{
+ ByteString b("AABBCCDDEEFF112233445566");
+
+ ByteString b1 = b.split(6);
+
+ CPPUNIT_ASSERT(b == ByteString("112233445566"));
+ CPPUNIT_ASSERT(b1 == ByteString("AABBCCDDEEFF"));
+
+ ByteString b2 = b1.split(8);
+
+ CPPUNIT_ASSERT(b2 == ByteString("AABBCCDDEEFF"));
+ CPPUNIT_ASSERT(b1.size() == 0);
+}
+
+void ByteStringTests::testBits()
+{
+ ByteString b1("0");
+ ByteString b2("08");
+ ByteString b3("00FFFFF");
+ ByteString b4("123456");
+
+ CPPUNIT_ASSERT(b1.bits() == 0);
+ CPPUNIT_ASSERT(b2.bits() == 4);
+ CPPUNIT_ASSERT(b3.bits() == 20);
+ CPPUNIT_ASSERT(b4.bits() == 21);
+}
+
+void ByteStringTests::testSerialising()
+{
+ ByteString b1("AA11AA11AA11AA11AA11AA11AA11");
+ ByteString b2("BB22BB22BB22BB22BB22BB22");
+ ByteString b3("CC33CC33CC33CC33CC33CC33CC33CC33");
+
+ ByteString s1 = b1.serialise();
+
+ CPPUNIT_ASSERT(s1.size() == b1.size() + 8);
+
+ ByteString d1 = ByteString::chainDeserialise(s1);
+
+ CPPUNIT_ASSERT(s1.size() == 0);
+ CPPUNIT_ASSERT(d1 == b1);
+
+ ByteString s2 = b3.serialise() + b2.serialise() + b1.serialise();
+
+ CPPUNIT_ASSERT(s2.size() == b1.size() + b2.size() + b3.size() + (3*8));
+
+ d1 = ByteString::chainDeserialise(s2);
+
+ CPPUNIT_ASSERT(d1.size() == b3.size());
+ CPPUNIT_ASSERT(s2.size() == b1.size() + b2.size() + (2*8));
+
+ ByteString d2 = ByteString::chainDeserialise(s2);
+
+ CPPUNIT_ASSERT(d2.size() == b2.size());
+ CPPUNIT_ASSERT(s2.size() == b1.size() + 8);
+
+ ByteString d3 = ByteString::chainDeserialise(s2);
+
+ CPPUNIT_ASSERT(d3.size() == b1.size());
+ CPPUNIT_ASSERT(s2.size() == 0);
+
+ CPPUNIT_ASSERT(d1 == b3);
+ CPPUNIT_ASSERT(d2 == b2);
+ CPPUNIT_ASSERT(d3 == b1);
+}
+
diff --git a/SoftHSMv2/src/lib/data_mgr/test/ByteStringTests.h b/SoftHSMv2/src/lib/data_mgr/test/ByteStringTests.h
new file mode 100644
index 0000000..b1dd967
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/test/ByteStringTests.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ByteStringTests.h
+
+ Contains test cases to test the ByteString class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BYTESTRINGTESTS_H
+#define _SOFTHSM_V2_BYTESTRINGTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ByteStringTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ByteStringTests);
+ CPPUNIT_TEST(testIntegrity);
+ CPPUNIT_TEST(testAppend);
+ CPPUNIT_TEST(testSubstr);
+ CPPUNIT_TEST(testFromHexStr);
+ CPPUNIT_TEST(testXOR);
+ CPPUNIT_TEST(testToHexStr);
+ CPPUNIT_TEST(testLongValues);
+ CPPUNIT_TEST(testSplitting);
+ CPPUNIT_TEST(testBits);
+ CPPUNIT_TEST(testSerialising);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testIntegrity();
+ void testAppend();
+ void testSubstr();
+ void testFromHexStr();
+ void testXOR();
+ void testToHexStr();
+ void testLongValues();
+ void testSplitting();
+ void testBits();
+ void testSerialising();
+
+ void setUp();
+ void tearDown();
+
+};
+
+#endif // !_SOFTHSM_V2_BYTESTRINGTESTS_H
+
diff --git a/SoftHSMv2/src/lib/data_mgr/test/Makefile.am b/SoftHSMv2/src/lib/data_mgr/test/Makefile.am
new file mode 100644
index 0000000..e1ebcdd
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/test/Makefile.am
@@ -0,0 +1,27 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../pkcs11 \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ @CPPUNIT_CFLAGS@ \
+ @CRYPTO_INCLUDES@
+
+check_PROGRAMS = datamgrtest
+
+datamgrtest_SOURCES = datamgrtest.cpp \
+ ByteStringTests.cpp \
+ RFC4880Tests.cpp \
+ SecureDataMgrTests.cpp
+
+datamgrtest_LDADD = ../../libsofthsm_convarch.la
+
+datamgrtest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install
+
+TESTS = datamgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/data_mgr/test/RFC4880Tests.cpp b/SoftHSMv2/src/lib/data_mgr/test/RFC4880Tests.cpp
new file mode 100644
index 0000000..6fcfd94
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/test/RFC4880Tests.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RFC4880Tests.cpp
+
+ Contains test cases to test the RFC4880 implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "RFC4880Tests.h"
+#include "RFC4880.h"
+#include "ByteString.h"
+#include "CryptoFactory.h"
+#include "AESKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RFC4880Tests);
+
+void RFC4880Tests::setUp()
+{
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+}
+
+void RFC4880Tests::tearDown()
+{
+}
+
+void RFC4880Tests::testRFC4880()
+{
+ const unsigned char* pwd1String = (const unsigned char*) "monkey";
+ const unsigned char* pwd2String = (const unsigned char*) "bicycle";
+ ByteString pwd1(pwd1String, strlen("monkey"));
+ ByteString pwd2(pwd2String, strlen("bicycle"));
+
+ // Generate salt and make sure that two different salt values are generated and
+ // that the last byte is also different (resulting in a different iteration jitter
+ // when computing a PBE key using both salt values)
+ ByteString salt1, salt2;
+
+ do
+ {
+ CPPUNIT_ASSERT(rng->generateRandom(salt1, 8) && rng->generateRandom(salt2, 8));
+ }
+ while ((salt1 == salt2) || (salt1[salt1.size() - 1] == salt2[salt2.size() - 1]));
+
+ // Create a password-based encryption key from the first and second password
+ AESKey* key1;
+ AESKey* key2;
+
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd1, salt1, &key1));
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd2, salt2, &key2));
+
+ // Check that the output keys differ and have the correct length
+ CPPUNIT_ASSERT(key1->getKeyBits().size() == 32);
+ CPPUNIT_ASSERT(key2->getKeyBits().size() == 32);
+ CPPUNIT_ASSERT(key1->getKeyBits() != key2->getKeyBits());
+
+ // Rederive the keys to check that the same output is generated every time
+ AESKey* key1_;
+ AESKey* key2_;
+
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd1, salt1, &key1_));
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd2, salt2, &key2_));
+
+ CPPUNIT_ASSERT(key1->getKeyBits() == key1_->getKeyBits());
+ CPPUNIT_ASSERT(key2->getKeyBits() == key2_->getKeyBits());
+
+ // Now reverse the salts and derive new keys
+ AESKey* key3;
+ AESKey* key4;
+
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd1, salt2, &key3));
+ CPPUNIT_ASSERT(RFC4880::PBEDeriveKey(pwd2, salt1, &key4));
+
+ // Check that the keys are different and that they differ from the
+ // original keys (because different salts were used)
+ CPPUNIT_ASSERT(key3->getKeyBits() != key4->getKeyBits());
+ CPPUNIT_ASSERT(key1->getKeyBits() != key3->getKeyBits());
+ CPPUNIT_ASSERT(key1->getKeyBits() != key4->getKeyBits());
+ CPPUNIT_ASSERT(key2->getKeyBits() != key3->getKeyBits());
+ CPPUNIT_ASSERT(key2->getKeyBits() != key4->getKeyBits());
+
+ // Clean up
+ delete key1;
+ delete key2;
+ delete key1_;
+ delete key2_;
+ delete key3;
+ delete key4;
+}
+
diff --git a/SoftHSMv2/src/lib/data_mgr/test/RFC4880Tests.h b/SoftHSMv2/src/lib/data_mgr/test/RFC4880Tests.h
new file mode 100644
index 0000000..4663626
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/test/RFC4880Tests.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RFC4880Tests.h
+
+ Contains test cases to test the RFC4880 implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RFC4880TESTS_H
+#define _SOFTHSM_V2_RFC4880TESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+
+class RFC4880Tests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(RFC4880Tests);
+ CPPUNIT_TEST(testRFC4880);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRFC4880();
+
+ void setUp();
+ void tearDown();
+
+private:
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_RFC4880TESTS_H
+
diff --git a/SoftHSMv2/src/lib/data_mgr/test/SecureDataMgrTests.cpp b/SoftHSMv2/src/lib/data_mgr/test/SecureDataMgrTests.cpp
new file mode 100644
index 0000000..7ef4816
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/test/SecureDataMgrTests.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureDataMgrTests.cpp
+
+ Contains test cases to test the secure data manager
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SecureDataMgrTests.h"
+#include "SecureDataManager.h"
+#include "CryptoFactory.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SecureDataMgrTests);
+
+void SecureDataMgrTests::setUp()
+{
+ CPPUNIT_ASSERT((rng = CryptoFactory::i()->getRNG()) != NULL);
+}
+
+void SecureDataMgrTests::tearDown()
+{
+}
+
+void SecureDataMgrTests::testSecureDataManager()
+{
+ ByteString soPIN = "3132333435363738"; // "12345678"
+ ByteString userPIN = "4041424344454647"; // "ABCDEFGH"
+ ByteString newSOPIN = "3837363534333231"; // "87654321"
+ ByteString newUserPIN = "4746454443424140"; // "HGFEDCBA"
+
+ // Instantiate a blank secure data manager
+ SecureDataManager s1;
+ ByteString plaintext = "010203040506070809";
+ ByteString emptyPlaintext = "";
+ ByteString encrypted;
+
+ // Verify that no function other than setting the SO PIN works
+ CPPUNIT_ASSERT(!s1.setUserPIN(userPIN));
+ CPPUNIT_ASSERT(!s1.loginSO(soPIN));
+ CPPUNIT_ASSERT(!s1.loginUser(userPIN));
+ CPPUNIT_ASSERT(!s1.reAuthenticateSO(soPIN));
+ CPPUNIT_ASSERT(!s1.reAuthenticateUser(userPIN));
+ CPPUNIT_ASSERT(!s1.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(!s1.decrypt(encrypted, plaintext));
+ CPPUNIT_ASSERT(s1.getSOPINBlob().size() == 0);
+ CPPUNIT_ASSERT(s1.getUserPINBlob().size() == 0);
+
+ // Now set the SO PIN
+ CPPUNIT_ASSERT(s1.setSOPIN(soPIN));
+
+ // Check that it is still not possible to set the user PIN
+ CPPUNIT_ASSERT(!s1.setUserPIN(userPIN));
+
+ // Check that it is possible to log in with the SO PIN
+ CPPUNIT_ASSERT(s1.loginSO(soPIN));
+
+ // Check that it is now possible to also set the user PIN
+ CPPUNIT_ASSERT(s1.setUserPIN(userPIN));
+
+ // Check that is is now also possible to log in with the user PIN
+ CPPUNIT_ASSERT(s1.loginUser(userPIN));
+
+ // Check that it is possible to encrypt and decrypt some data
+ ByteString decrypted;
+
+ CPPUNIT_ASSERT(s1.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(encrypted != plaintext);
+
+ CPPUNIT_ASSERT(s1.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == plaintext);
+
+ // Log out
+ s1.logout();
+
+ // Check that it is no longer possible to set the SO PIN
+ CPPUNIT_ASSERT(!s1.setSOPIN(soPIN));
+
+ // Check that it is no longer possible to set the user PIN
+ CPPUNIT_ASSERT(!s1.setUserPIN(userPIN));
+
+ // Check that encrypting/decrypting no longer works
+ CPPUNIT_ASSERT(!s1.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(!s1.decrypt(encrypted, plaintext));
+
+ // Export the key blobs
+ ByteString soPINBlob = s1.getSOPINBlob();
+ ByteString userPINBlob = s1.getUserPINBlob();
+
+ // Create a new instance with the exported key blobs
+ SecureDataManager s2(soPINBlob, userPINBlob);
+
+ // Check that the key blobs match
+ CPPUNIT_ASSERT(s1.getSOPINBlob() == s2.getSOPINBlob());
+ CPPUNIT_ASSERT(s1.getUserPINBlob() == s2.getUserPINBlob());
+
+ // Check that it is not possible to set the SO PIN
+ CPPUNIT_ASSERT(!s2.setSOPIN(soPIN));
+
+ // Check that it is possible to log in with the SO PIN
+ CPPUNIT_ASSERT(s2.loginSO(soPIN));
+
+ // Check that is is now also possible to log in with the user PIN
+ CPPUNIT_ASSERT(s2.loginUser(userPIN));
+
+ // Check that encrypting the data results in different ciphertext because of the random IV
+ ByteString encrypted2;
+
+ CPPUNIT_ASSERT(s2.encrypt(plaintext, encrypted2));
+ CPPUNIT_ASSERT(encrypted != encrypted2);
+
+ // Check that decrypting earlier data can be done with the recreated key
+ CPPUNIT_ASSERT(s2.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == plaintext);
+
+ // Log in with the SO PIN
+ CPPUNIT_ASSERT(s2.loginSO(soPIN));
+
+ // Check that the SO PIN can be changed
+ CPPUNIT_ASSERT(s2.setSOPIN(newSOPIN));
+
+ // Check that it is no longer possible to log in with the old SO PIN
+ CPPUNIT_ASSERT(!s2.loginSO(soPIN));
+
+ // Check that encrypting/decrypting no longer works
+ CPPUNIT_ASSERT(!s2.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(!s2.decrypt(encrypted, plaintext));
+
+ // Check that the key blobs differ
+ CPPUNIT_ASSERT(s1.getSOPINBlob() != s2.getSOPINBlob());
+
+ // Check that it is possible to log in with the new SO PIN
+ CPPUNIT_ASSERT(s2.loginSO(newSOPIN));
+
+ // Log in with the user PIN
+ CPPUNIT_ASSERT(s2.loginUser(userPIN));
+
+ // Check that it is possible to change the user PIN
+ CPPUNIT_ASSERT(s2.setUserPIN(newUserPIN));
+
+ // Check that it is no longer possible to log in with the old user PIN
+ CPPUNIT_ASSERT(!s2.loginUser(userPIN));
+
+ // Check that encrypting/decrypting no longer works
+ CPPUNIT_ASSERT(!s2.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(!s2.decrypt(encrypted, plaintext));
+
+ // Check that it is possible to log in with the new user PIN
+ CPPUNIT_ASSERT(s2.loginUser(newUserPIN));
+
+ // Check that encrypting the data results in the different ciphertext because of the random IV
+ CPPUNIT_ASSERT(s2.encrypt(plaintext, encrypted2));
+ CPPUNIT_ASSERT(encrypted != encrypted2);
+
+ // Check that decrypting earlier data can be done with the recreated key
+ CPPUNIT_ASSERT(s2.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == plaintext);
+
+ // Check that empty plaintext can be handled
+ CPPUNIT_ASSERT(s2.encrypt(emptyPlaintext, encrypted));
+ CPPUNIT_ASSERT(s2.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == emptyPlaintext);
+
+ // Check that is is possible to log in with the SO PIN and re-authenticate
+ CPPUNIT_ASSERT(s1.loginSO(soPIN));
+ CPPUNIT_ASSERT(!s1.reAuthenticateSO(userPIN));
+ CPPUNIT_ASSERT(s1.reAuthenticateSO(soPIN));
+
+ // Check that is is possible to log in with the user PIN and re-authenticate
+ CPPUNIT_ASSERT(s1.loginUser(userPIN));
+ CPPUNIT_ASSERT(!s1.reAuthenticateUser(soPIN));
+ CPPUNIT_ASSERT(s1.reAuthenticateUser(userPIN));
+
+ // Check that it is possible to encrypt and decrypt some data
+ CPPUNIT_ASSERT(s1.encrypt(plaintext, encrypted));
+ CPPUNIT_ASSERT(encrypted != plaintext);
+
+ CPPUNIT_ASSERT(s1.decrypt(encrypted, decrypted));
+ CPPUNIT_ASSERT(decrypted == plaintext);
+}
+
diff --git a/SoftHSMv2/src/lib/data_mgr/test/SecureDataMgrTests.h b/SoftHSMv2/src/lib/data_mgr/test/SecureDataMgrTests.h
new file mode 100644
index 0000000..743a01b
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/test/SecureDataMgrTests.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SecureDataMgrTests.h
+
+ Contains test cases to test the secure data manager
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SECUREDATAMGRTESTS_H
+#define _SOFTHSM_V2_SECUREDATAMGRTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+
+class SecureDataMgrTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SecureDataMgrTests);
+ CPPUNIT_TEST(testSecureDataManager);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testSecureDataManager();
+
+ void setUp();
+ void tearDown();
+
+private:
+ RNG* rng;
+};
+
+#endif // !_SOFTHSM_V2_SECUREDATAMGRTESTS_H
+
diff --git a/SoftHSMv2/src/lib/data_mgr/test/datamgrtest.cpp b/SoftHSMv2/src/lib/data_mgr/test/datamgrtest.cpp
new file mode 100644
index 0000000..49fa535
--- /dev/null
+++ b/SoftHSMv2/src/lib/data_mgr/test/datamgrtest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ datamgrtest.cpp
+
+ The main test executor for tests on the secure data manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "SecureMemoryRegistry.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#endif
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ CryptoFactory::reset();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/SoftHSMv2/src/lib/handle_mgr/Handle.cpp b/SoftHSMv2/src/lib/handle_mgr/Handle.cpp
new file mode 100644
index 0000000..127b4c7
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/Handle.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Handle.h
+
+ This class represents a single handle
+ *****************************************************************************/
+
+#include "Handle.h"
+
+// Constructor
+Handle::Handle(CK_HANDLE_KIND _kind, CK_SLOT_ID _slotID, CK_SESSION_HANDLE _hSession)
+ : kind(_kind), slotID(_slotID), hSession(_hSession), object(NULL_PTR), isPrivate(false)
+{
+}
+
+Handle::Handle(CK_HANDLE_KIND _kind, CK_SLOT_ID _slotID)
+ : kind(_kind), slotID(_slotID), hSession(CK_INVALID_HANDLE), object(NULL_PTR), isPrivate(false)
+{
+}
+
+Handle::Handle()
+ : kind(CKH_INVALID), slotID(0), hSession(CK_INVALID_HANDLE), object(NULL_PTR), isPrivate(false)
+{
+
+}
diff --git a/SoftHSMv2/src/lib/handle_mgr/Handle.h b/SoftHSMv2/src/lib/handle_mgr/Handle.h
new file mode 100644
index 0000000..94b42f9
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/Handle.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Handle.h
+
+ This class represents a single handle
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLE_H
+#define _SOFTHSM_V2_HANDLE_H
+
+#include "cryptoki.h"
+
+enum {
+ CKH_INVALID,
+ CKH_SESSION,
+ CKH_OBJECT
+};
+
+#define CK_HANDLE_KIND CK_ULONG
+
+class Handle
+{
+public:
+ Handle(CK_HANDLE_KIND kind, CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession);
+ Handle(CK_HANDLE_KIND kind, CK_SLOT_ID slotID);
+ Handle();
+
+ CK_HANDLE_KIND kind;
+ CK_SLOT_ID slotID;
+ CK_SESSION_HANDLE hSession;
+
+ CK_VOID_PTR object;
+ bool isPrivate;
+};
+
+#endif // !_SOFTHSM_V2_HANDLE_H
+
diff --git a/SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp b/SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp
new file mode 100644
index 0000000..ccf42d0
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/HandleManager.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*****************************************************************************
+ HandleManager.cpp
+
+ One of the most difficult problems to track down is when stale cryptoki handles
+ for e.g. keys, objects and sessions get reused by a misbehaving application.
+ Especialy when handles that became invalid have since been reused.
+ A simple solution to this is to never reuse a handle once it has been issued
+ and subsequently invalidated.
+
+ The handle manager tracks issued handles along with what kind of object
+ is presented by the handle and an actual pointer to the object in question.
+
+ Issued handles are unique per application run. All session and object handles
+ use the same handle manager and therefore there will never be e.g. a session
+ with the same handle as an object.
+
+ *****************************************************************************/
+
+#include "HandleManager.h"
+#include "log.h"
+
+// Constructor
+HandleManager::HandleManager()
+{
+ handlesMutex = MutexFactory::i()->getMutex();
+ handleCounter = 0;
+}
+
+// Destructor
+HandleManager::~HandleManager()
+{
+
+ MutexFactory::i()->recycleMutex(handlesMutex);
+}
+
+CK_SESSION_HANDLE HandleManager::addSession(CK_SLOT_ID slotID, CK_VOID_PTR session)
+{
+ MutexLocker lock(handlesMutex);
+
+ Handle h( CKH_SESSION, slotID );
+ h.object = session;
+ handles[++handleCounter] = h;
+ return (CK_SESSION_HANDLE)handleCounter;
+}
+
+CK_VOID_PTR HandleManager::getSession(const CK_SESSION_HANDLE hSession)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hSession);
+ if (it == handles.end() || CKH_SESSION != it->second.kind)
+ return NULL_PTR;
+ return it->second.object;
+}
+
+CK_OBJECT_HANDLE HandleManager::addSessionObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate, CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Return existing handle when the object has already been registered.
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator oit = objects.find(object);
+ if (oit != objects.end()) {
+ std::map< CK_ULONG, Handle>::iterator hit = handles.find(oit->second);
+ if (hit == handles.end() || CKH_OBJECT != hit->second.kind || slotID != hit->second.slotID) {
+ objects.erase(oit);
+ return CK_INVALID_HANDLE;
+ } else
+ return oit->second;
+ }
+
+ Handle h( CKH_OBJECT, slotID, hSession );
+ h.isPrivate = isPrivate;
+ h.object = object;
+ handles[++handleCounter] = h;
+ objects[object] = handleCounter;
+ return (CK_OBJECT_HANDLE)handleCounter;
+}
+
+CK_OBJECT_HANDLE HandleManager::addTokenObject(CK_SLOT_ID slotID, bool isPrivate, CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Return existing handle when the object has already been registered.
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator oit = objects.find(object);
+ if (oit != objects.end()) {
+ std::map< CK_ULONG, Handle>::iterator hit = handles.find(oit->second);
+ if (hit == handles.end() || CKH_OBJECT != hit->second.kind || slotID != hit->second.slotID) {
+ objects.erase(oit);
+ return CK_INVALID_HANDLE;
+ } else
+ return oit->second;
+ }
+
+ // Token objects are not associated with a specific session.
+ Handle h( CKH_OBJECT, slotID );
+ h.isPrivate = isPrivate;
+ h.object = object;
+ handles[++handleCounter] = h;
+ objects[object] = handleCounter;
+ return (CK_OBJECT_HANDLE)handleCounter;
+}
+
+CK_VOID_PTR HandleManager::getObject(const CK_OBJECT_HANDLE hObject)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hObject);
+ if (it == handles.end() || CKH_OBJECT != it->second.kind )
+ return NULL_PTR;
+ return it->second.object;
+}
+
+CK_OBJECT_HANDLE HandleManager::getObjectHandle(CK_VOID_PTR object)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_VOID_PTR, CK_ULONG>::iterator it = objects.find(object);
+ if (it == objects.end())
+ return CK_INVALID_HANDLE;
+ return it->second;
+}
+
+void HandleManager::destroyObject(const CK_OBJECT_HANDLE hObject)
+{
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hObject);
+ if (it != handles.end() && CKH_OBJECT == it->second.kind) {
+ objects.erase(it->second.object);
+ handles.erase(it);
+ }
+}
+
+void HandleManager::sessionClosed(const CK_SESSION_HANDLE hSession)
+{
+ CK_SLOT_ID slotID;
+ {
+ MutexLocker lock(handlesMutex);
+
+ std::map< CK_ULONG, Handle>::iterator it = handles.find(hSession);
+ if (it == handles.end() || CKH_SESSION != it->second.kind)
+ return; // Unable to find the specified session.
+
+ slotID = it->second.slotID;
+
+ // session closed, so we can erase information about it.
+ handles.erase(it);
+
+ // Erase all session object handles associated with the given session handle.
+ CK_ULONG openSessionCount = 0;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (CKH_SESSION == h.kind && slotID == h.slotID) {
+ ++openSessionCount; // another session is open for this slotID.
+ } else {
+ if (CKH_OBJECT == h.kind && hSession == h.hSession) {
+ // A session object is present for the given session, so erase it.
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ }
+ ++it;
+ }
+
+ // We are done when there are still sessions open.
+ if (openSessionCount)
+ return;
+ }
+
+ // No more sessions open for this token, so remove all object handles that are still valid for the given slotID.
+ allSessionsClosed(slotID);
+}
+
+void HandleManager::allSessionsClosed(const CK_SLOT_ID slotID)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Erase all "session", "session object" and "token object" handles for a given slot id.
+ std::map< CK_ULONG, Handle>::iterator it;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (slotID == h.slotID) {
+ if (CKH_OBJECT == it->second.kind)
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ ++it;
+ }
+}
+
+void HandleManager::tokenLoggedOut(const CK_SLOT_ID slotID)
+{
+ MutexLocker lock(handlesMutex);
+
+ // Erase all private "token object" or "session object" handles for a given slot id.
+ std::map< CK_ULONG, Handle>::iterator it;
+ for (it = handles.begin(); it != handles.end(); ) {
+ Handle &h = it->second;
+ if (CKH_OBJECT == h.kind && slotID == h.slotID && h.isPrivate) {
+ // A private object is present for the given slotID so we need to remove it.
+ objects.erase(it->second.object);
+ // Iterator post-incrementing (it++) will return a copy of the original it (which points to handle to be deleted).
+ handles.erase(it++);
+ continue;
+ }
+ ++it;
+ }
+}
diff --git a/SoftHSMv2/src/lib/handle_mgr/HandleManager.h b/SoftHSMv2/src/lib/handle_mgr/HandleManager.h
new file mode 100644
index 0000000..e85e628
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/HandleManager.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManager.h
+
+ Keeps track of the issued cryptoki handles within SoftHSM
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLEMANAGER_H
+#define _SOFTHSM_V2_HANDLEMANAGER_H
+
+#include "MutexFactory.h"
+#include "Handle.h"
+#include "cryptoki.h"
+
+#include <map>
+
+#define CK_INTERNAL_SESSION_HANDLE CK_SESSION_HANDLE
+
+class HandleManager
+{
+public:
+ HandleManager();
+
+ virtual ~HandleManager();
+
+ CK_SESSION_HANDLE addSession(CK_SLOT_ID slotID, CK_VOID_PTR session);
+ CK_VOID_PTR getSession(const CK_SESSION_HANDLE hSession);
+
+ // Add the session object and return a handle. For objects that have already been registered, check that the
+ // slotID matches. The hSession may be different as the object may be added as part of a find objects operation.
+ CK_OBJECT_HANDLE addSessionObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate, CK_VOID_PTR object);
+
+ // Add the token object and return a handle. For objects that have already been registered, check that the
+ // slotID mathces.
+ CK_OBJECT_HANDLE addTokenObject(CK_SLOT_ID slotID, bool isPrivate, CK_VOID_PTR object);
+
+ // Get the object pointer associated with the given object handle.
+ CK_VOID_PTR getObject(const CK_OBJECT_HANDLE hObject);
+
+ // Get the object handle for the object pointer that has been previously registered.
+ // When the object is not found CK_INVALID_HANDLE is returned.
+ CK_OBJECT_HANDLE getObjectHandle(CK_VOID_PTR object);
+
+ // Remove the given object handle.
+ void destroyObject(const CK_OBJECT_HANDLE hObject);
+
+ // Remove the given session handle and all session object handles for the session.
+ // The token object handles retrieved using the session will remain valid unless
+ // this is the last session of a token being closed. In that case remove all token
+ // object handles for the slot/token associated with the session.
+ void sessionClosed(const CK_SESSION_HANDLE hSession);
+
+ // Remove all session and object handles for the given slotID.
+ // All handles for the given slotID will become invalid.
+ void allSessionsClosed(const CK_SLOT_ID slotID);
+
+ // Remove all handles to private objects for the given slotID.
+ // All handles to public objects for the given slotID remain valid.
+ void tokenLoggedOut(const CK_SLOT_ID slotID);
+
+private:
+ Mutex* handlesMutex;
+ std::map< CK_ULONG, Handle> handles;
+ std::map< CK_VOID_PTR, CK_ULONG> objects;
+ CK_ULONG handleCounter;
+};
+
+#endif // !_SOFTHSM_V2_HANDLEMANAGER_H
+
diff --git a/SoftHSMv2/src/lib/handle_mgr/Makefile.am b/SoftHSMv2/src/lib/handle_mgr/Makefile.am
new file mode 100644
index 0000000..108f74d
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/Makefile.am
@@ -0,0 +1,17 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../object_store \
+ -I$(srcdir)/../pkcs11 \
+ -I$(srcdir)/../slot_mgr
+
+noinst_LTLIBRARIES = libsofthsm_handlemgr.la
+libsofthsm_handlemgr_la_SOURCES = HandleManager.cpp \
+ Handle.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp b/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp
new file mode 100644
index 0000000..fbf0403
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManagerTests.cpp
+
+ Contains test cases to test the handle manager implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "HandleManagerTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HandleManagerTests);
+
+void HandleManagerTests::setUp()
+{
+ handleManager = new HandleManager();
+}
+
+void HandleManagerTests::tearDown()
+{
+ delete handleManager;
+}
+
+void HandleManagerTests::testHandleManager()
+{
+ CPPUNIT_ASSERT(handleManager != NULL);
+
+ CK_SLOT_ID slotID = 1234; // we need a unique value
+ CK_SESSION_HANDLE hSession;
+ CK_VOID_PTR session = &hSession; // we need a unique value
+ CK_SESSION_HANDLE hSession2;
+ CK_VOID_PTR session2 = &hSession2; // we need a unique value
+ CK_OBJECT_HANDLE hObject;
+ CK_VOID_PTR object = &hObject; // we need a unique value
+ CK_OBJECT_HANDLE hObject2;
+ CK_VOID_PTR object2 = &hObject2; // we need a unique value
+ CK_OBJECT_HANDLE hObject3;
+ CK_VOID_PTR object3 = &hObject3; // we need a unique value
+ CK_OBJECT_HANDLE hObject4;
+ CK_VOID_PTR object4 = &hObject4; // we need a unique value
+ CK_OBJECT_HANDLE hObject5;
+ CK_VOID_PTR object5 = &hObject5; // we need a unique value
+
+ // Check session object management.
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT_NO_THROW(handleManager->sessionClosed(123124));
+ handleManager->sessionClosed(hSession);
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+
+ // Add an object, hSession doesn't have to exists
+ hObject = handleManager->addSessionObject(slotID, 4412412, true, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ handleManager->sessionClosed(4412412);
+ // Object still exists as the hSession was invalid
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ handleManager->allSessionsClosed(slotID);
+ // Object is now gone as all sessions for the given slotID have been removed.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ // Add an object and then destroy it.
+ hObject = handleManager->addSessionObject(slotID, 4412412, true, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ handleManager->destroyObject(hObject);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ hObject = handleManager->addTokenObject(slotID, false, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ handleManager->destroyObject(hObject);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject));
+
+ // Create a valid session again
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+
+ // Now some magic with a couple of objects
+ // First add a public object
+ hObject = handleManager->addTokenObject(slotID, false, object);
+ CPPUNIT_ASSERT(hObject != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+
+ // Now add a private object
+ hObject2 = handleManager->addTokenObject(slotID, true, object2);
+ CPPUNIT_ASSERT(hObject2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object2 == handleManager->getObject(hObject2));
+
+ // Now add another private object
+ hObject3 = handleManager->addTokenObject(slotID, true, object3);
+ CPPUNIT_ASSERT(hObject3 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object3 == handleManager->getObject(hObject3));
+
+ // Adding the same object will return the same handle whether the object is marked private or public.
+ CPPUNIT_ASSERT(hObject2 == handleManager->addTokenObject(slotID, true, object2));
+ // Because the private state of an object cannot be changed it won't be marked as public, it remains private
+ CPPUNIT_ASSERT(hObject2 == handleManager->addTokenObject(slotID, false, object2));
+
+ // It is not allowed to migrate an object from one slot to another, so here we return an invalid handle.
+ CPPUNIT_ASSERT(CK_INVALID_HANDLE == handleManager->addTokenObject(124121, false, object2));
+
+ // Now add another private session object
+ hObject4 = handleManager->addSessionObject(slotID, hSession, true, object4);
+ CPPUNIT_ASSERT(hObject4 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object4 == handleManager->getObject(hObject4));
+
+ // Now add another public session object
+ hObject5 = handleManager->addSessionObject(slotID, hSession, false, object5);
+ CPPUNIT_ASSERT(hObject5 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(object5 == handleManager->getObject(hObject5));
+
+ // Logout, now private objects should be gone.
+ handleManager->tokenLoggedOut(slotID);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject));
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject2)); // should still be private and removed.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject3));
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject4));
+ CPPUNIT_ASSERT(object5 == handleManager->getObject(hObject5));
+
+ // Create another valid session for the slot
+ hSession2 = handleManager->addSession(slotID, session2);
+ CPPUNIT_ASSERT(hSession2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session2 == handleManager->getSession(hSession2));
+
+ handleManager->sessionClosed(hSession);
+ CPPUNIT_ASSERT(object == handleManager->getObject(hObject)); // token object should still be there.
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject5)); // session object should be gone.
+
+ // Removing the last remaining session should kill the remaining handle.
+ handleManager->sessionClosed(hSession2);
+ CPPUNIT_ASSERT(NULL == handleManager->getObject(hObject)); // should be gone now.
+
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession2));
+
+
+ // Create a valid session again
+ hSession = handleManager->addSession(slotID, session);
+ CPPUNIT_ASSERT(hSession != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == handleManager->getSession(hSession));
+
+ // Create another valid session for the slot
+ hSession2 = handleManager->addSession(slotID, session2);
+ CPPUNIT_ASSERT(hSession2 != CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session2 == handleManager->getSession(hSession2));
+
+ handleManager->allSessionsClosed(slotID);
+
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession));
+ CPPUNIT_ASSERT(NULL == handleManager->getSession(hSession2));
+}
diff --git a/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h b/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h
new file mode 100644
index 0000000..02022e4
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/test/HandleManagerTests.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ HandleManagerTests.h
+
+ Contains test cases to test the handle manager implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_HANDLEMANAGERTESTS_H
+#define _SOFTHSM_V2_HANDLEMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "RNG.h"
+#include "HandleManager.h"
+
+class HandleManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(HandleManagerTests);
+ CPPUNIT_TEST(testHandleManager);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testHandleManager();
+
+ void setUp();
+ void tearDown();
+
+private:
+ HandleManager *handleManager;
+
+};
+
+#endif // !_SOFTHSM_V2_HANDLEMANAGERTESTS_H
+
diff --git a/SoftHSMv2/src/lib/handle_mgr/test/Makefile.am b/SoftHSMv2/src/lib/handle_mgr/test/Makefile.am
new file mode 100644
index 0000000..8d110b0
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/test/Makefile.am
@@ -0,0 +1,26 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../pkcs11 \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ @CPPUNIT_CFLAGS@
+
+check_PROGRAMS = handlemgrtest
+
+handlemgrtest_SOURCES = handlemgrtest.cpp \
+ HandleManagerTests.cpp
+
+handlemgrtest_LDADD = ../../libsofthsm_convarch.la
+
+handlemgrtest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install
+
+TESTS = handlemgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
+
diff --git a/SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp b/SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp
new file mode 100644
index 0000000..eedb407
--- /dev/null
+++ b/SoftHSMv2/src/lib/handle_mgr/test/handlemgrtest.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ handlemgrtest.cpp
+
+ The main test executor for tests on the handle manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+
+#include "config.h"
+#include "MutexFactory.h"
+
+#ifdef HAVE_CXX11
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+#else
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+#endif
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/SoftHSMv2/src/lib/main.cpp b/SoftHSMv2/src/lib/main.cpp
new file mode 100644
index 0000000..2dfd0eb
--- /dev/null
+++ b/SoftHSMv2/src/lib/main.cpp
@@ -0,0 +1,1187 @@
+/*
+ * Copyright (c)2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ main.cpp
+
+ This file contains the main entry point to the PKCS #11 library. All it does
+ is dispatch calls to the actual implementation and check for fatal exceptions
+ on the boundary of the library.
+ *****************************************************************************/
+
+// The functions are exported library/DLL entry points
+#define CRYPTOKI_EXPORTS
+
+#include "config.h"
+#include "log.h"
+#include "fatal.h"
+#include "cryptoki.h"
+#include "SoftHSM.h"
+
+#if defined(__GNUC__) && \
+ (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) || \
+ defined(__SUNPRO_C) && __SUNPRO_C >= 0x590
+#define PKCS_API __attribute__ ((visibility("default")))
+#else
+#define PKCS_API
+#endif
+
+// PKCS #11 function list
+static CK_FUNCTION_LIST functionList =
+{
+ // Version information
+ { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
+ // Function pointers
+ C_Initialize,
+ C_Finalize,
+ C_GetInfo,
+ C_GetFunctionList,
+ C_GetSlotList,
+ C_GetSlotInfo,
+ C_GetTokenInfo,
+ C_GetMechanismList,
+ C_GetMechanismInfo,
+ C_InitToken,
+ C_InitPIN,
+ C_SetPIN,
+ C_OpenSession,
+ C_CloseSession,
+ C_CloseAllSessions,
+ C_GetSessionInfo,
+ C_GetOperationState,
+ C_SetOperationState,
+ C_Login,
+ C_Logout,
+ C_CreateObject,
+ C_CopyObject,
+ C_DestroyObject,
+ C_GetObjectSize,
+ C_GetAttributeValue,
+ C_SetAttributeValue,
+ C_FindObjectsInit,
+ C_FindObjects,
+ C_FindObjectsFinal,
+ C_EncryptInit,
+ C_Encrypt,
+ C_EncryptUpdate,
+ C_EncryptFinal,
+ C_DecryptInit,
+ C_Decrypt,
+ C_DecryptUpdate,
+ C_DecryptFinal,
+ C_DigestInit,
+ C_Digest,
+ C_DigestUpdate,
+ C_DigestKey,
+ C_DigestFinal,
+ C_SignInit,
+ C_Sign,
+ C_SignUpdate,
+ C_SignFinal,
+ C_SignRecoverInit,
+ C_SignRecover,
+ C_VerifyInit,
+ C_Verify,
+ C_VerifyUpdate,
+ C_VerifyFinal,
+ C_VerifyRecoverInit,
+ C_VerifyRecover,
+ C_DigestEncryptUpdate,
+ C_DecryptDigestUpdate,
+ C_SignEncryptUpdate,
+ C_DecryptVerifyUpdate,
+ C_GenerateKey,
+ C_GenerateKeyPair,
+ C_WrapKey,
+ C_UnwrapKey,
+ C_DeriveKey,
+ C_SeedRandom,
+ C_GenerateRandom,
+ C_GetFunctionStatus,
+ C_CancelFunction,
+ C_WaitForSlotEvent
+};
+
+// PKCS #11 initialisation function
+PKCS_API CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
+{
+ try
+ {
+ return SoftHSM::i()->C_Initialize(pInitArgs);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// PKCS #11 finalisation function
+PKCS_API CK_RV C_Finalize(CK_VOID_PTR pReserved)
+{
+ try
+ {
+ return SoftHSM::i()->C_Finalize(pReserved);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return information about the PKCS #11 module
+PKCS_API CK_RV C_GetInfo(CK_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetInfo(pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return the list of PKCS #11 functions
+PKCS_API CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
+{
+ try
+ {
+ if (ppFunctionList == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ *ppFunctionList = &functionList;
+
+ return CKR_OK;
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return a list of available slots
+PKCS_API CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetSlotList(tokenPresent, pSlotList, pulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return information about a slot
+PKCS_API CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetSlotInfo(slotID, pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return information about a token in a slot
+PKCS_API CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetTokenInfo(slotID, pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return the list of supported mechanisms for a given slot
+PKCS_API CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetMechanismList(slotID, pMechanismList, pulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Return more information about a mechanism for a given slot
+PKCS_API CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetMechanismInfo(slotID, type, pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise the token in the specified slot
+PKCS_API CK_RV C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
+{
+ try
+ {
+ return SoftHSM::i()->C_InitToken(slotID, pPin, ulPinLen, pLabel);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise the user PIN
+PKCS_API CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_InitPIN(hSession, pPin, ulPinLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Change the PIN
+PKCS_API CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SetPIN(hSession, pOldPin, ulOldLen, pNewPin, ulNewLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Open a new session to the specified slot
+PKCS_API CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_OpenSession(slotID, flags, pApplication, notify, phSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Close the given session
+PKCS_API CK_RV C_CloseSession(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_CloseSession(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Close all open sessions
+PKCS_API CK_RV C_CloseAllSessions(CK_SLOT_ID slotID)
+{
+ try
+ {
+ return SoftHSM::i()->C_CloseAllSessions(slotID);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Retrieve information about the specified session
+PKCS_API CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetSessionInfo(hSession, pInfo);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Determine the state of a running operation in a session
+PKCS_API CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetOperationState(hSession, pOperationState, pulOperationStateLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Set the operation sate in a session
+PKCS_API CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_SetOperationState(hSession, pOperationState, ulOperationStateLen, hEncryptionKey, hAuthenticationKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Login on the token in the specified session
+PKCS_API CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Login(hSession, userType, pPin, ulPinLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Log out of the token in the specified session
+PKCS_API CK_RV C_Logout(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_Logout(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Create a new object on the token in the specified session using the given attribute template
+PKCS_API CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_CreateObject(hSession, pTemplate, ulCount, phObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Create a copy of the object with the specified handle
+PKCS_API CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_CopyObject(hSession, hObject, pTemplate, ulCount, phNewObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Destroy the specified object
+PKCS_API CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_DestroyObject(hSession, hObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Determine the size of the specified object
+PKCS_API CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetObjectSize(hSession, hObject, pulSize);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Retrieve the specified attributes for the given object
+PKCS_API CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetAttributeValue(hSession, hObject, pTemplate, ulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Change or set the value of the specified attributes on the specified object
+PKCS_API CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_SetAttributeValue(hSession, hObject, pTemplate, ulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise object search in the specified session using the specified attribute template as search parameters
+PKCS_API CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_FindObjectsInit(hSession, pTemplate, ulCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Continue the search for objects in the specified session
+PKCS_API CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
+{
+ try
+ {
+ return SoftHSM::i()->C_FindObjects(hSession, phObject, ulMaxObjectCount, pulObjectCount);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finish searching for objects
+PKCS_API CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_FindObjectsFinal(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise encryption using the specified object and mechanism
+PKCS_API CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_EncryptInit(hSession, pMechanism, hObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single operation encryption operation in the specified session
+PKCS_API CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Encrypt(hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Feed data to the running encryption operation in a session
+PKCS_API CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise the encryption operation
+PKCS_API CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_EncryptFinal(hSession, pEncryptedData, pulEncryptedDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise decryption using the specified object
+PKCS_API CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptInit(hSession, pMechanism, hObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single operation decryption in the given session
+PKCS_API CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Decrypt(hSession, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Feed data to the running decryption operation in a session
+PKCS_API CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, pData, pDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise the decryption operation
+PKCS_API CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptFinal(hSession, pData, pDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise digesting using the specified mechanism in the specified session
+PKCS_API CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestInit(hSession, pMechanism);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Digest the specified data in a one-pass operation and return the resulting digest
+PKCS_API CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Digest(hSession, pData, ulDataLen, pDigest, pulDigestLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running digest operation
+PKCS_API CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestUpdate(hSession, pPart, ulPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running digest operation by digesting a secret key with the specified handle
+PKCS_API CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestKey(hSession, hObject);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise the digest operation in the specified session and return the digest
+PKCS_API CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestFinal(hSession, pDigest, pulDigestLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise a signing operation using the specified key and mechanism
+PKCS_API CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignInit(hSession, pMechanism, hKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Sign the data in a single pass operation
+PKCS_API CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running signing operation with additional data
+PKCS_API CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignUpdate(hSession, pPart, ulPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise a running signing operation and return the signature
+PKCS_API CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignFinal(hSession, pSignature, pulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise a signing operation that allows recovery of the signed data
+PKCS_API CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignRecoverInit(hSession, pMechanism, hKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single part signing operation that allows recovery of the signed data
+PKCS_API CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignRecover(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise a verification operation using the specified key and mechanism
+PKCS_API CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyInit(hSession, pMechanism, hKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single pass verification operation
+PKCS_API CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_Verify(hSession, pData, ulDataLen, pSignature, ulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running verification operation with additional data
+PKCS_API CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyUpdate(hSession, pPart, ulPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Finalise the verification operation and check the signature
+PKCS_API CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyFinal(hSession, pSignature, ulSignatureLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Initialise a verification operation the allows recovery of the signed data from the signature
+PKCS_API CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyRecoverInit(hSession, pMechanism, hKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Perform a single part verification operation and recover the signed data
+PKCS_API CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_VerifyRecover(hSession, pSignature, ulSignatureLen, pData, pulDataLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running multi-part encryption and digesting operation
+PKCS_API CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DigestEncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running multi-part decryption and digesting operation
+PKCS_API CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pDecryptedPart, CK_ULONG_PTR pulDecryptedPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptDigestUpdate(hSession, pPart, ulPartLen, pDecryptedPart, pulDecryptedPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running multi-part signing and encryption operation
+PKCS_API CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SignEncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Update a running multi-part decryption and verification operation
+PKCS_API CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_DecryptVerifyUpdate(hSession, pEncryptedPart, ulEncryptedPartLen, pPart, pulPartLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Generate a secret key using the specified mechanism
+PKCS_API CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
+{
+ try
+ {
+ return SoftHSM::i()->C_GenerateKey(hSession, pMechanism, pTemplate, ulCount, phKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Generate a key-pair using the specified mechanism
+PKCS_API CK_RV C_GenerateKeyPair
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
+ CK_OBJECT_HANDLE_PTR phPrivateKey
+)
+{
+ try
+ {
+ return SoftHSM::i()->C_GenerateKeyPair(hSession, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Wrap the specified key using the specified wrapping key and mechanism
+PKCS_API CK_RV C_WrapKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hWrappingKey,
+ CK_OBJECT_HANDLE hKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG_PTR pulWrappedKeyLen
+)
+{
+ try
+ {
+ return SoftHSM::i()->C_WrapKey(hSession, pMechanism, hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Unwrap the specified key using the specified unwrapping key
+PKCS_API CK_RV C_UnwrapKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hUnwrappingKey,
+ CK_BYTE_PTR pWrappedKey,
+ CK_ULONG ulWrappedKeyLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey
+)
+{
+ try
+ {
+ return SoftHSM::i()->C_UnwrapKey(hSession, pMechanism, hUnwrappingKey, pWrappedKey, ulWrappedKeyLen, pTemplate, ulCount, phKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Derive a key from the specified base key
+PKCS_API CK_RV C_DeriveKey
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey
+)
+{
+ try
+ {
+ return SoftHSM::i()->C_DeriveKey(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Seed the random number generator with new data
+PKCS_API CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_SeedRandom(hSession, pSeed, ulSeedLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Generate the specified amount of random data
+PKCS_API CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
+{
+ try
+ {
+ return SoftHSM::i()->C_GenerateRandom(hSession, pRandomData, ulRandomLen);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Legacy function
+PKCS_API CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_GetFunctionStatus(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Legacy function
+PKCS_API CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession)
+{
+ try
+ {
+ return SoftHSM::i()->C_CancelFunction(hSession);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
+// Wait or poll for a slot even on the specified slot
+PKCS_API CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
+{
+ try
+ {
+ return SoftHSM::i()->C_WaitForSlotEvent(flags, pSlot, pReserved);
+ }
+ catch (...)
+ {
+ FatalException();
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/DB.cpp b/SoftHSMv2/src/lib/object_store/DB.cpp
new file mode 100644
index 0000000..d82d7cb
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/DB.cpp
@@ -0,0 +1,926 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DB.cpp
+
+ Specifies classes to access the Token Database
+ *****************************************************************************/
+#define HAVE_SQL_TRACE 0
+
+#include "config.h"
+#include "OSPathSep.h"
+#include "log.h"
+#include <cstdlib>
+#include <cstdio>
+#include <iostream>
+#include <vector>
+#include <sqlite3.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "DB.h"
+
+#if HAVE_SQL_TRACE
+static void xTrace(void*connectionLabel,const char*zSql)
+{
+ const char *label = static_cast<const char *>(connectionLabel);
+ if (label)
+ std::cout << std::endl << label << ": " << zSql ;
+ else
+ std::cout << std::endl << zSql ;
+}
+#endif
+
+static int static_log_err(const char *format, va_list ap)
+{
+ std::vector<char> logMessage;
+ logMessage.resize(4096);
+ vsnprintf(&logMessage[0], 4096, format, ap);
+ ERROR_MSG(&logMessage[0]);
+ return 0;
+}
+
+static DB::LogErrorHandler static_LogErrorhandler = static_log_err;
+
+void DB::logError(const std::string &format, ...)
+{
+ if (!static_LogErrorhandler)
+ return;
+ va_list args;
+ va_start(args, format);
+ static_LogErrorhandler(format.c_str(),args);
+ va_end(args);
+}
+
+DB::LogErrorHandler DB::setLogErrorHandler(DB::LogErrorHandler handler)
+{
+ LogErrorHandler temp = static_LogErrorhandler;
+ static_LogErrorhandler = handler;
+ return temp;
+}
+
+void DB::resetLogErrorHandler()
+{
+ static_LogErrorhandler = static_log_err;
+}
+
+static void reportErrorDB(sqlite3 *db)
+{
+ if (!db) {
+ DB::logError("sqlite3 pointer is NULL");
+ return;
+ }
+
+ int rv = sqlite3_errcode(db);
+ if (rv == SQLITE_OK || rv == SQLITE_ROW || rv == SQLITE_DONE)
+ return;
+
+#ifdef HAVE_SILENT_BUSY_AND_LOCKED_ERRORS
+ // Either the database file is locked (SQLITE_BUSY)
+ // or a table in the database is locked (SQLITE_LOCKED)
+ if (rv == SQLITE_BUSY || rv == SQLITE_LOCKED)
+ return;
+#endif
+
+ DB::logError("SQLITE3: %s (%d)", sqlite3_errmsg(db), rv);
+}
+
+static void reportError(sqlite3_stmt *stmt)
+{
+ if (!stmt) {
+ DB::logError("sqlite3_stmt pointer is NULL");
+ return;
+ }
+ reportErrorDB(sqlite3_db_handle(stmt));
+}
+
+static time_t sqlite3_gmtime(struct tm *tm)
+{
+ // We don't want to depend on timegm() so we use a workaround via the
+ // gmtime_r() function to determine this.
+ // As input we use a moment in time just 10 days after the POSIX epoch.
+ // The POSIX epoch is defined as the moment in time at midnight Coordinated
+ // Universal Time (UTC) of Thursday, January 1, 1970. A time_t value is
+ // the number of seconds elapsed since epoch.
+ struct tm ref_tm = {0,0,0,0,0,0,0,0,0,0,0};
+ ref_tm.tm_year = 70; // Years since 1900;
+ ref_tm.tm_mday = 10; // 10th
+
+ // We need the time difference between local time and UTC time.
+ // mktime will interpret the UTC time stored in tm as local time
+ // so let's assume we are in a time zone 1 hour ahead of UTC (UTC+1)
+ // then a time of 13:00 interpreted as local time needs 1 hour subtracted
+ // to arrive at UTC time. This UTC time is then converted to a POSIX
+ // time_t value.
+ time_t posix_time = mktime(&ref_tm);
+
+ // Use gmtime_r to convert the POSIX time back to a tm struct.
+ // No time adjustment is done this time because POSIX time is
+ // defined in terms of UTC.
+ gmtime_r(&posix_time, &ref_tm);
+ if (ref_tm.tm_isdst != 0) {
+ DB::logError("expected gmtime_r to return zero in tm_isdst member of tm struct");
+ return ((time_t)-1);
+ }
+
+ // Using mktime again to convert tm. This will again subtract 1 hour from
+ // the time (under the assumption that we are 1 hour ahead of UTC).
+ // We can now use this to determine how much local time differred
+ // from UTC time on january the 10th 1970
+ long diff_time = posix_time - mktime(&ref_tm);
+
+ // We explicitly set tm_isdst to zero to prevent errors
+ // when the time we are trying to convert is occuring at
+ // the moment when a dst change is in progress.
+ // We require mktime to respect our setting of tm_isdst
+ // indicating that no dst is in effect.
+ tm->tm_isdst = 0; // Tell (and force) mktime not to take dst into account.
+
+ // We now can calculate and return a correct POSIX time.
+ // So, although mktime() interprets gm_tm as local time adjusts for
+ // the time difference between local time and UTC time. We then undo
+ // that adjustment by adding diff_time.
+ return mktime(tm) + diff_time;
+}
+
+/**************************
+ * Handle
+ **************************/
+
+class DB::Handle {
+public:
+ int _refcount;
+ sqlite3_stmt *_stmt;
+ Handle(sqlite3_stmt *stmt)
+ : _refcount(1), _stmt(stmt)
+ {
+ }
+ ~Handle()
+ {
+ if (_stmt)
+ {
+ sqlite3_finalize(_stmt);
+ _stmt = NULL;
+ }
+ }
+
+ Handle *retain()
+ {
+ if (_refcount)
+ {
+ _refcount++;
+ return this;
+ }
+ return NULL;
+ }
+ void release()
+ {
+ if (_refcount)
+ {
+ _refcount--;
+ if (_refcount)
+ return;
+ delete this;
+ }
+ }
+ bool reset()
+ {
+ if (sqlite3_reset(_stmt) != SQLITE_OK)
+ {
+ reportError(_stmt);
+ return false;
+ }
+ return true;
+ }
+ Statement::ReturnCode step()
+ {
+ int rv = sqlite3_step(_stmt);
+ if (rv != SQLITE_ROW && rv != SQLITE_DONE)
+ {
+ reportError(_stmt);
+ return Statement::ReturnCodeError;
+ }
+
+ if (rv==SQLITE_ROW)
+ {
+ return Statement::ReturnCodeRow;
+ }
+
+ return Statement::ReturnCodeDone;
+ }
+private:
+ // disable evil constructors
+ Handle(const Handle &);
+ Handle & operator=(const Handle &);
+};
+
+DB::Statement::Statement()
+ : _handle(NULL)
+{
+}
+
+DB::Statement::Statement(sqlite3_stmt *statement)
+ : _handle(new Handle(statement))
+{
+}
+
+DB::Statement::Statement(const DB::Statement &statement)
+ : _handle(statement._handle)
+{
+ if (_handle)
+ _handle = _handle->retain();
+}
+
+DB::Statement &DB::Statement::operator=(const DB::Statement &statement)
+{
+ if (this != &statement)
+ {
+ Handle *tmp = NULL;
+ if (statement._handle) {
+ tmp = statement._handle->retain();
+ }
+ if (_handle) {
+ _handle->release();
+ }
+ _handle = tmp;
+ }
+ return *this;
+}
+
+DB::Statement::~Statement()
+{
+ if (_handle) {
+ _handle->release();
+ _handle = NULL;
+ }
+}
+
+bool DB::Statement::isValid()
+{
+ return _handle != NULL && _handle->_stmt != NULL;
+}
+
+int DB::Statement::refcount()
+{
+ return _handle ? _handle->_refcount : 0;
+}
+
+
+bool DB::Statement::reset()
+{
+ if (!isValid()) {
+ DB::logError("Statement::reset: statement is not valid");
+ return false;
+ }
+ return _handle->reset();
+}
+
+DB::Statement::ReturnCode DB::Statement::step()
+{
+ if (!isValid()) {
+ DB::logError("Statement::step: statement is not valid");
+ return ReturnCodeError;
+ }
+ return _handle->step();
+}
+
+DB::Handle *DB::Statement::handle() const
+{
+ return _handle;
+}
+
+/**************************
+ * Bindings
+ **************************/
+
+DB::Bindings::Bindings()
+ : Statement()
+{
+}
+
+DB::Bindings::Bindings(const Statement &statement)
+ : Statement(statement)
+{
+}
+
+bool DB::Bindings::clear()
+{
+ if (!isValid()) {
+ DB::logError("Bindings::clear: statement is not valid");
+ return false;
+ }
+ if (sqlite3_clear_bindings(_handle->_stmt) != SQLITE_OK) {
+ reportError(_handle->_stmt);
+ return false;
+ }
+ return true;
+}
+
+bool DB::Bindings::bindBlob(int index, const void *value, int n, void(*destruct)(void*))
+{
+ if (!isValid()) {
+ DB::logError("Bindings::bindBlob: statement is not valid");
+ return false;
+ }
+ if (sqlite3_bind_blob(_handle->_stmt, index, value, n, destruct) != SQLITE_OK) {
+ reportError(_handle->_stmt);
+ return false;
+ }
+ return true;
+}
+
+bool DB::Bindings::bindDouble(int index, double value)
+{
+ if (!isValid()) {
+ DB::logError("Bindings::bindDouble: statement is not valid");
+ return false;
+ }
+ if (sqlite3_bind_double(_handle->_stmt, index, value) != SQLITE_OK) {
+ reportError(_handle->_stmt);
+ return false;
+ }
+ return true;
+}
+
+bool DB::Bindings::bindInt(int index, int value)
+{
+ if (!isValid()) {
+ DB::logError("Bindings::bindInt: statement is not valid");
+ return false;
+ }
+ if (sqlite3_bind_int(_handle->_stmt, index, value) != SQLITE_OK) {
+ reportError(_handle->_stmt);
+ return false;
+ }
+ return true;
+}
+
+bool DB::Bindings::bindInt64(int index, long long value)
+{
+ if (!isValid()) {
+ DB::logError("Bindings::bindInt64: statement is not valid");
+ return false;
+ }
+ if (sqlite3_bind_int64(_handle->_stmt, index, value) != SQLITE_OK) {
+ reportError(_handle->_stmt);
+ return false;
+ }
+ return true;
+}
+
+//bool DB::Bindings::bindNull(int index)
+//{
+//#if 0
+// int sqlite3_bind_null(sqlite3_stmt*, int);
+//#endif
+// return false;
+//}
+
+bool DB::Bindings::bindText(int index, const char *value, int n, void (*destruct)(void *))
+{
+ if (!isValid()) {
+ DB::logError("Bindings::bindText: statement is not valid");
+ return false;
+ }
+ if (sqlite3_bind_text(_handle->_stmt, index, value, n, destruct) != SQLITE_OK) {
+ reportError(_handle->_stmt);
+ return false;
+ }
+ return true;
+}
+
+//bool DB::Bindings::bindZeroBlob(int index, int n)
+//{
+//#if 0
+// int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+//#endif
+// return false;
+//}
+
+/**************************
+ * Result
+ **************************/
+
+DB::Result::Result()
+ : Statement()
+{
+}
+
+DB::Result::Result(const Statement &statement)
+ : Statement(statement)
+{
+}
+
+#if 0
+unsigned int DB::Result::getField(const std::string &fieldname)
+{
+ unsigned int fieldidx = fields[fieldname];
+ if (fieldidx == 0)
+ DB::logError("Result: invalid field name \"%s\"",fieldname.c_str());
+ return fieldidx;
+}
+#endif
+
+bool DB::Result::fieldIsNull(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::fieldIsNull: statement is not valid");
+ return true;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return true;
+ }
+ int column_type = sqlite3_column_type(_handle->_stmt, fieldidx-1);
+ return column_type == SQLITE_NULL;
+}
+
+time_t DB::Result::getDatetime(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getDatetime: statement is not valid");
+ return ((time_t)-1);
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return ((time_t)-1);
+ }
+
+ const unsigned char *value = sqlite3_column_text(_handle->_stmt, fieldidx-1);
+ int valuelen = sqlite3_column_bytes(_handle->_stmt, fieldidx-1);
+
+ unsigned long years,mons,days,hours,mins,secs;
+ struct tm gm_tm = {0,0,0,0,0,0,0,0,0,0,0};
+ gm_tm.tm_isdst = 0; // Tell mktime not to take dst into account.
+ gm_tm.tm_year = 70; // 1970
+ gm_tm.tm_mday = 1; // 1th day of the month
+ const char *p = (const char *)value;
+ char *pnext;
+ bool bdateonly = true;
+ switch (valuelen) {
+ case 19: // 2011-12-31 23:59:59
+ bdateonly = false;
+ // falls through to next case
+ case 10: // 2011-12-31
+ years = strtoul(p,&pnext,10);
+ gm_tm.tm_year = ((int)years)-1900; /* years since 1900 */
+ p = pnext+1;
+ mons = strtoul(p,&pnext,10);
+ gm_tm.tm_mon = ((int)mons)-1; /* months since January [0-11] */
+ p = pnext+1;
+ days = strtoul(p,&pnext,10);
+ gm_tm.tm_mday = ((int)days); /* day of the month [1-31] */
+ p = pnext+1;
+ if (bdateonly)
+ break;
+ // falls through to next case
+ case 8: // 23:59:59
+ hours = strtoul(p,&pnext,10);
+ gm_tm.tm_hour = (int)hours; /* hours since midnight [0-23] */
+ if ((pnext-p) != 2) {
+ DB::logError("Result: invalid hours in time: '%s'",value);
+ return 0;
+ }
+ p = pnext+1;
+ mins = strtoul(p,&pnext,10);
+ gm_tm.tm_min = (int)mins; /* minutes after the hour [0-59] */
+ if ((pnext-p) != 2) {
+ DB::logError("Result: invalid minutes in time: '%s'",value);
+ return 0;
+ }
+ p = pnext+1;
+ secs = strtoul(p,&pnext,10);
+ gm_tm.tm_sec = (int)secs; /* seconds after the minute [0-60] */
+ if ((pnext-p) != 2) {
+ DB::logError("Result: invalid seconds in time: '%s'",value);
+ return 0;
+ }
+ break;
+ default:
+ DB::logError("Result: invalid date/time value: '%s'",value);
+ return 0;
+ }
+
+ return sqlite3_gmtime(&gm_tm);
+}
+
+unsigned char DB::Result::getUChar(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getUChar: statement is not valid");
+ return 0;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return 0;
+ }
+ int value = sqlite3_column_int(_handle->_stmt, fieldidx-1);
+ reportError(_handle->_stmt);
+ return (unsigned char)value;
+}
+
+float DB::Result::getFloat(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getFloat: statement is not valid");
+ return 0.0f;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return 0.0f;
+ }
+ double value = sqlite3_column_double(_handle->_stmt, fieldidx-1);
+ reportError(_handle->_stmt);
+ return (float)value;
+}
+
+double DB::Result::getDouble(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getDouble: statement is not valid");
+ return 0.0;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return 0.0;
+ }
+ double value = sqlite3_column_double(_handle->_stmt, fieldidx-1);
+ reportError(_handle->_stmt);
+ return value;
+}
+
+int DB::Result::getInt(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getInt: statement is not valid");
+ return 0;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return 0;
+ }
+ int value = sqlite3_column_int(_handle->_stmt, fieldidx-1);
+ reportError(_handle->_stmt);
+ return value;
+}
+
+unsigned int DB::Result::getUInt(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getUInt: statement is not valid");
+ return 0;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return 0;
+ }
+ int value = sqlite3_column_int(_handle->_stmt, fieldidx-1);
+ reportError(_handle->_stmt);
+ return (unsigned int)value;
+}
+
+long long DB::Result::getLongLong(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getLongLong: statement is not valid");
+ return 0;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return 0;
+ }
+ sqlite3_int64 value = sqlite3_column_int64(_handle->_stmt, fieldidx-1);
+ reportError(_handle->_stmt);
+ return value;
+}
+
+unsigned long long DB::Result::getULongLong(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getULongLong: statement is not valid");
+ return 0;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return 0;
+ }
+ sqlite3_int64 value = sqlite3_column_int64(_handle->_stmt, fieldidx-1);
+ reportError(_handle->_stmt);
+ return (unsigned long long)value;
+}
+
+const char *DB::Result::getString(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getString: statement is not valid");
+ return NULL;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return NULL;
+ }
+ const unsigned char *value = sqlite3_column_text(_handle->_stmt,fieldidx-1);
+ reportError(_handle->_stmt);
+ return (const char *)value;
+}
+
+const unsigned char *DB::Result::getBinary(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getBinary: statement is not valid");
+ return NULL;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return NULL;
+ }
+ const unsigned char *value =
+ (const unsigned char *)sqlite3_column_blob(_handle->_stmt,fieldidx-1);
+ reportError(_handle->_stmt);
+ return value;
+}
+
+size_t DB::Result::getFieldLength(unsigned int fieldidx)
+{
+ if (!isValid()) {
+ DB::logError("Result::getFieldLength: statement is not valid");
+ return 0;
+ }
+ if (fieldidx == 0) {
+ DB::logError("Result: zero is an invalid field index");
+ return 0;
+ }
+ int value = sqlite3_column_bytes(_handle->_stmt,fieldidx-1);
+ reportError(_handle->_stmt);
+ return (size_t)value;
+}
+
+bool DB::Result::firstRow()
+{
+ if (!isValid()) {
+ DB::logError("Result::firstRow: statement is not valid");
+ return false;
+ }
+ return _handle->reset() && _handle->step()==Statement::ReturnCodeRow;
+}
+
+bool DB::Result::nextRow()
+{
+ if (!isValid()) {
+ DB::logError("Result::nextRow: statement is not valid");
+ return false;
+ }
+ return _handle->step()==Statement::ReturnCodeRow;
+}
+
+/**************************
+ * Connection
+ **************************/
+
+DB::Connection *DB::Connection::Create(const std::string &dbdir, const std::string &dbname)
+{
+ if (dbdir.length() == 0) {
+ DB::logError("Connection::Create: database directory parameter dbdir is empty");
+ return NULL;
+ }
+
+ if (dbname.length() == 0) {
+ DB::logError("Connection::Create: database name parameter dbname is empty");
+ return NULL;
+ }
+
+ return new Connection(dbdir,dbname);
+}
+
+DB::Connection::Connection(const std::string &dbdir, const std::string &dbname)
+ : _dbdir(dbdir)
+ , _dbpath(dbdir + OS_PATHSEP + dbname)
+ , _db(NULL)
+{
+}
+
+DB::Connection::~Connection()
+{
+ close();
+}
+
+const std::string &DB::Connection::dbdir()
+{
+ return _dbdir;
+}
+
+const std::string &DB::Connection::dbpath()
+{
+ return _dbpath;
+}
+
+DB::Statement DB::Connection::prepare(const std::string &format, ...){
+ // pstatement will hold a dynamically allocated string that needs to be deleted.
+ char *pstatement = NULL;
+
+ // short form
+ char statement[128];
+ va_list args;
+ va_start(args, format);
+ int cneeded = vsnprintf(statement,sizeof(statement),format.c_str(),args);
+ va_end(args);
+ if (cneeded<0) {
+ DB::logError("Connection::prepare: vsnprintf encoding error");
+ return Statement();
+ }
+ if (((size_t)cneeded)>=sizeof(statement)) {
+ // long form
+ pstatement = new char[cneeded+1];
+ if (!pstatement) {
+ DB::logError("Connection::prepare: out of memory");
+ return Statement();
+ }
+ va_start(args, format);
+ bool ok = vsnprintf(pstatement,cneeded+1,format.c_str(),args)==cneeded;
+ va_end(args);
+ if (!ok) {
+ DB::logError("Connection::prepare: vsnprintf error");
+ delete[] pstatement;
+ return Statement();
+ }
+ }
+
+ sqlite3_stmt *stmt = NULL;
+ int rv = sqlite3_prepare_v2(_db,
+ pstatement ? pstatement : statement,
+ cneeded+1,
+ &stmt,
+ NULL);
+
+ if (pstatement)
+ delete[] pstatement;
+
+ if (rv != SQLITE_OK) {
+ reportErrorDB(_db);
+ if (stmt)
+ sqlite3_finalize(stmt);
+ return Statement();
+ }
+
+ if (!stmt) {
+ DB::logError("Connection::prepare: expected sqlite3_prepare_v2 to return a compiled "
+ "statement, got NULL, out of memory ?");
+ return Statement();
+ }
+
+ return Statement(stmt);
+}
+
+DB::Result DB::Connection::perform(DB::Statement &statement)
+{
+ return (statement.step()==Statement::ReturnCodeRow) ? Result(statement) : Result();
+}
+
+bool DB::Connection::execute(DB::Statement &statement)
+{
+ return statement.step()==Statement::ReturnCodeDone;
+}
+
+bool DB::Connection::connect(const char *
+#if HAVE_SQL_TRACE
+ connectionLabel
+#endif
+ )
+{
+ // Create and set file permissions if the DB does not exist.
+ int fd = open(_dbpath.c_str(), O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1)
+ {
+ DB::logError("Could not open database: %s (errno %i)",
+ _dbpath.c_str(), errno);
+ return false;
+ }
+ ::close(fd);
+
+ int rv = sqlite3_open_v2(_dbpath.c_str(),
+ &_db,
+ SQLITE_OPEN_READWRITE
+ | SQLITE_OPEN_CREATE
+ | SQLITE_OPEN_FULLMUTEX,
+ NULL);
+
+ if (rv != SQLITE_OK) {
+ reportErrorDB(_db);
+ return false;
+ }
+
+ int foreignKeyEnabled = 0;
+ rv = sqlite3_db_config(_db,SQLITE_DBCONFIG_ENABLE_FKEY,1,&foreignKeyEnabled);
+ if (rv != SQLITE_OK) {
+ reportErrorDB(_db);
+ return false;
+ }
+
+ if (foreignKeyEnabled != 1) {
+ DB::logError("Connection::connect: foreign key support not enabled");
+ return false;
+ }
+
+ rv = sqlite3_busy_timeout(_db, 15000); // 15 seconds
+ if (rv != SQLITE_OK) {
+ reportErrorDB(_db);
+ return false;
+ }
+#if HAVE_SQL_TRACE
+ sqlite3_trace(_db, xTrace, const_cast<char *>(connectionLabel));
+#endif
+ return true;
+}
+
+void DB::Connection::close()
+{
+ if (_db) {
+ sqlite3_close(_db);
+ _db = NULL;
+ }
+}
+
+bool DB::Connection::setBusyTimeout(int ms)
+{
+ int rv = sqlite3_busy_timeout(_db, ms);
+ if (rv != SQLITE_OK) {
+ reportErrorDB(_db);
+ return false;
+ }
+
+ return true;
+}
+
+bool DB::Connection::tableExists(const std::string &tablename)
+{
+ Statement statement = prepare("select name from sqlite_master where type='table' and name='%s';",tablename.c_str());
+ return statement.step()==Statement::ReturnCodeRow && statement.step()==Statement::ReturnCodeDone;
+}
+
+long long DB::Connection::lastInsertRowId()
+{
+ return sqlite3_last_insert_rowid(_db);
+}
+
+bool DB::Connection::inTransaction()
+{
+ return sqlite3_get_autocommit(_db)==0;
+}
+
+bool DB::Connection::beginTransactionRO()
+{
+ Statement statement = prepare("begin");
+ return statement.step()==Statement::ReturnCodeDone;
+}
+
+bool DB::Connection::endTransactionRO()
+{
+ Statement statement = prepare("end");
+ return statement.step()==Statement::ReturnCodeDone;
+}
+
+bool DB::Connection::beginTransactionRW()
+{
+ Statement statement = prepare("begin immediate");
+ return statement.step()==Statement::ReturnCodeDone;
+}
+
+bool DB::Connection::commitTransaction()
+{
+ Statement statement = prepare("commit");
+ return statement.step()==Statement::ReturnCodeDone;
+}
+
+bool DB::Connection::rollbackTransaction()
+{
+ Statement statement = prepare("rollback");
+ return statement.step()==Statement::ReturnCodeDone;
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/DB.h b/SoftHSMv2/src/lib/object_store/DB.h
new file mode 100644
index 0000000..e4e1a11
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/DB.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DB.h
+
+ Specifies classes to access the Token Database
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DB_H
+#define _SOFTHSM_V2_DB_H
+
+#include "config.h"
+
+#include <string>
+#include <sqlite3.h>
+
+namespace DB {
+
+// Log an error to the error handler that has been setup using a call to setLogErrorHandler declared below.
+void logError(const std::string &format, ...);
+
+// The ap parameter has already been started with va_start.
+// So the handler only has to pass this on to a vprintf function
+// to actually print it.
+typedef int (*LogErrorHandler)(const char *format, va_list ap);
+
+// Set an alternative for vprintf to log the actual errors.
+// Set to NULL to disable logging al together.
+LogErrorHandler setLogErrorHandler(LogErrorHandler handler);
+
+// Set the log error handler back to the default value that logs to stdout.
+void resetLogErrorHandler();
+
+// Forward declaration of the handle class used by Statement, Binding and Result.
+class Handle;
+
+// Responsible for holding on to a prepared statement.
+// After a prepared statement has been used it can be reused when the same query is performed again.
+class Statement {
+public:
+ Statement();
+ Statement(sqlite3_stmt *statement);
+ Statement(const Statement &statement);
+ Statement &operator=(const Statement &statement);
+
+ virtual ~Statement();
+ bool isValid();
+
+ // Something we'd like to check during testing.
+ int refcount();
+
+ // Reset a prepared statement
+ bool reset();
+
+ // Perform a single step of the prepared statement.
+ enum ReturnCode {
+ ReturnCodeRow,
+ ReturnCodeDone,
+ ReturnCodeError
+ };
+
+ ReturnCode step();
+
+ Handle *handle() const;
+protected:
+ Handle *_handle;
+};
+
+// Responsible for allowing parameters to be bound to statements.
+// On a statement that has been performed or executed you first
+// need to call reset() before new parameters can be bound.
+class Bindings : public Statement {
+public:
+ Bindings();
+ Bindings(const Statement &statement);
+
+ // To clear all existing bindings call this method.
+ bool clear();
+
+ // Bind a value to a parameter in a prepared statement
+ bool bindBlob(int index, const void *value, int n, void(*destruct)(void*));
+ bool bindDouble(int index, double value);
+ bool bindInt(int index, int value);
+ bool bindInt64(int index, long long value );
+ //bool bindNull(int index);
+ bool bindText(int index, const char *value, int n, void(*destruct)(void*));
+ //bool bindZeroBlob(int index, int n);
+};
+
+// Responsible for providing access to the result set of a query.
+// Used for queries that actually provide a result set.
+// A result that is returned will be positioned at the first row.
+class Result : public Statement {
+public:
+ Result();
+ Result(const Statement &statement);
+
+ bool fieldIsNull(unsigned int fieldidx);
+ time_t getDatetime(unsigned int fieldidx);
+ unsigned char getUChar(unsigned int fieldidx);
+ float getFloat(unsigned int fieldidx);
+ double getDouble(unsigned int fieldidx);
+ int getInt(unsigned int fieldidx);
+ unsigned int getUInt(unsigned int fieldidx);
+ long long getLongLong(unsigned int fieldidx);
+ unsigned long long getULongLong(unsigned int fieldidx);
+
+ const char *getString(unsigned int fieldidx);
+ const unsigned char *getBinary(unsigned int fieldidx);
+ size_t getFieldLength(unsigned int fieldidx);
+
+ // Position the result on the first row again.
+ bool firstRow();
+
+ // Position the result on the next row.
+ bool nextRow();
+};
+
+// Responsible for connection to the database and for managing prepared statements.
+class Connection {
+public:
+ static Connection *Create(const std::string &dbdir, const std::string &dbname);
+ virtual ~Connection();
+
+ // value that was passed into dbdir when this connection was created.
+ const std::string &dbdir();
+
+ // concatenation of dbdir and dbname
+ const std::string &dbpath();
+
+ Statement prepare(const std::string &format, ...);
+ Result perform(Statement &statement);
+ bool execute(Statement &statement);
+
+ bool connect(const char *connectionLabel = NULL);
+ void close();
+
+ bool tableExists(const std::string &tablename);
+ long long lastInsertRowId();
+
+ bool inTransaction();
+ bool beginTransactionRO();
+ bool endTransactionRO();
+ bool beginTransactionRW();
+ bool commitTransaction();
+ bool rollbackTransaction();
+
+ // Set the busy timeout that the database layer will wait for a database lock to become available.
+ bool setBusyTimeout(int ms);
+private:
+ std::string _dbdir;
+ std::string _dbpath;
+ sqlite3 *_db;
+
+ Connection(const std::string &dbdir, const std::string &dbname);
+
+ // disable evil constructors
+ Connection(const Connection &);
+ void operator=(const Connection&);
+};
+
+}
+
+#endif // !_SOFTHSM_V2_DB_H
diff --git a/SoftHSMv2/src/lib/object_store/DBObject.cpp b/SoftHSMv2/src/lib/object_store/DBObject.cpp
new file mode 100644
index 0000000..d2515bd
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/DBObject.cpp
@@ -0,0 +1,1493 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObject.h
+
+ This class represents object records in a database
+ *****************************************************************************/
+
+#include "config.h"
+#include "DBObject.h"
+#include "OSPathSep.h"
+#include "DB.h"
+#include "OSAttributes.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <cstdio>
+#include <map>
+
+// Create an object that can access a record, but don't do anything yet.
+DBObject::DBObject(DB::Connection *connection, ObjectStoreToken *token)
+ : _mutex(MutexFactory::i()->getMutex()), _connection(connection), _token(token), _objectId(0), _transaction(NULL)
+{
+
+}
+
+DBObject::DBObject(DB::Connection *connection, ObjectStoreToken *token, long long objectId)
+ : _mutex(MutexFactory::i()->getMutex()), _connection(connection), _token(token), _objectId(objectId), _transaction(NULL)
+{
+}
+
+// Destructor
+DBObject::~DBObject()
+{
+ for (std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _attributes.begin(); it!=_attributes.end(); ++it) {
+ delete it->second;
+ it->second = NULL;
+ }
+ if (_transaction)
+ {
+ for (std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _transaction->begin(); it!=_transaction->end(); ++it) {
+ delete it->second;
+ it->second = NULL;
+ }
+ delete _transaction;
+ }
+ MutexFactory::i()->recycleMutex(_mutex);
+}
+
+void DBObject::dropConnection()
+{
+ MutexLocker lock(_mutex);
+
+ _connection = NULL;
+}
+
+// create tables to support storage of attributes for the DBObject
+bool DBObject::createTables()
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+
+ // Create the tables inside the database
+ DB::Statement cr_object = _connection->prepare("create table object (id integer primary key autoincrement);");
+ if (!_connection->execute(cr_object))
+ {
+ ERROR_MSG("Failed to create \"object\" table");
+ return false;
+ }
+
+ // attribute_text
+ DB::Statement cr_attr_text = _connection->prepare(
+ "create table attribute_text ("
+ "value text,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ if (!_connection->execute(cr_attr_text))
+ {
+ ERROR_MSG("Failed to create \"attribute_text\" table");
+ return false;
+ }
+
+ // attribute_integer
+ DB::Statement cr_attr_integer = _connection->prepare(
+ "create table attribute_integer ("
+ "value integer,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ if (!_connection->execute(cr_attr_integer))
+ {
+ ERROR_MSG("Failed to create \"attribute_integer\" table");
+ return false;
+ }
+
+ // attribute_binary
+ DB::Statement cr_attr_binary = _connection->prepare(
+ "create table attribute_binary ("
+ "value blob,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ if (!_connection->execute(cr_attr_binary))
+ {
+ ERROR_MSG("Failed to create \"attribute_binary\" table");
+ return false;
+ }
+
+ // attribute_array
+ DB::Statement cr_attr_array = _connection->prepare(
+ "create table attribute_array ("
+ "value blob,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ if (!_connection->execute(cr_attr_array))
+ {
+ ERROR_MSG("Failed to create \"attribute_array\" table");
+ return false;
+ }
+
+ // attribute_boolean
+ DB::Statement cr_attr_boolean = _connection->prepare(
+ "create table attribute_boolean ("
+ "value boolean,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ if (!_connection->execute(cr_attr_boolean))
+ {
+ ERROR_MSG("Failed to create \"attribute_boolean\" table");
+ return false;
+ }
+
+ // attribute_datetime
+ DB::Statement cr_attr_datetime = _connection->prepare(
+ "create table attribute_datetime ("
+ "value datetime,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ if (!_connection->execute(cr_attr_datetime))
+ {
+ ERROR_MSG("Failed to create \"attribute_datetime\" table");
+ return false;
+ }
+
+ // attribute_real
+ DB::Statement cr_attr_real = _connection->prepare(
+ "create table attribute_real ("
+ "value real,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ if (!_connection->execute(cr_attr_real))
+ {
+ ERROR_MSG("Failed to create \"attribute_real\" table");
+ return false;
+ }
+
+ return true;
+}
+
+bool DBObject::dropTables()
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+
+ // Create the tables inside the database
+ DB::Statement dr_object = _connection->prepare("drop table object");
+ if (!_connection->execute(dr_object))
+ {
+ ERROR_MSG("Failed to drop \"object\" table");
+ return false;
+ }
+
+ // attribute_text
+ DB::Statement dr_attr_text = _connection->prepare("drop table attribute_text");
+ if (!_connection->execute(dr_attr_text))
+ {
+ ERROR_MSG("Failed to drop \"attribute_text\" table");
+ return false;
+ }
+
+ // attribute_integer
+ DB::Statement dr_attr_integer = _connection->prepare("drop table attribute_integer");
+ if (!_connection->execute(dr_attr_integer))
+ {
+ ERROR_MSG("Failed to drop \"attribute_integer\" table");
+ return false;
+ }
+
+ // attribute_binary
+ DB::Statement dr_attr_binary = _connection->prepare("drop table attribute_binary");
+ if (!_connection->execute(dr_attr_binary))
+ {
+ ERROR_MSG("Failed to drop \"attribute_binary\" table");
+ return false;
+ }
+
+ // attribute_array
+ DB::Statement dr_attr_array = _connection->prepare("drop table attribute_array");
+ if (!_connection->execute(dr_attr_array))
+ {
+ ERROR_MSG("Failed to drop \"attribute_array\" table");
+ return false;
+ }
+
+ // attribute_boolean
+ DB::Statement dr_attr_boolean = _connection->prepare("drop table attribute_boolean");
+ if (!_connection->execute(dr_attr_boolean))
+ {
+ ERROR_MSG("Failed to drop \"attribute_boolean\" table");
+ return false;
+ }
+
+ // attribute_datetime
+ DB::Statement dr_attr_datetime = _connection->prepare("drop table attribute_datetime");
+ if (!_connection->execute(dr_attr_datetime))
+ {
+ ERROR_MSG("Failed to drop \"attribute_datetime\" table");
+ return false;
+ }
+
+ // attribute_real
+ DB::Statement dr_attr_real = _connection->prepare("drop table attribute_real");
+ if (!_connection->execute(dr_attr_real))
+ {
+ ERROR_MSG("Failed to drop \"attribute_real\" table");
+ return false;
+ }
+
+ return true;
+}
+
+bool DBObject::find(long long objectId)
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+
+ if (objectId == 0) {
+ ERROR_MSG("Invalid object_id 0 passed to find");
+ return false;
+ }
+
+ // find the object in the database for the given object_id
+ DB::Statement statement = _connection->prepare(
+ "select id from object where id=%lld",
+ objectId);
+ if (!statement.isValid()) {
+ ERROR_MSG("Preparing object selection statement failed");
+ return false;
+ }
+
+ DB::Result result = _connection->perform(statement);
+ if (result.getLongLong(1) != objectId) {
+ ERROR_MSG("Failed to find object with id %lld",objectId);
+ return false;
+ }
+
+ _objectId = objectId;
+ return true;
+}
+
+bool DBObject::insert()
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+
+ DB::Statement statement = _connection->prepare("insert into object default values");
+
+ if (!_connection->execute(statement)) {
+ ERROR_MSG("Failed to insert a new object");
+ return false;
+ }
+
+ _objectId = _connection->lastInsertRowId();
+ return _objectId != 0;
+}
+
+bool DBObject::remove()
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+
+ DB::Statement statement = _connection->prepare("delete from object where id=%lld",_objectId);
+
+ if (!_connection->execute(statement)) {
+ ERROR_MSG("Failed to remove an existing object");
+ return false;
+ }
+
+ _objectId = 0;
+ return true;
+}
+
+long long DBObject::objectId()
+{
+ MutexLocker lock(_mutex);
+
+ return _objectId;
+}
+
+static bool isModifiable(CK_ATTRIBUTE_TYPE type)
+{
+ switch (type) {
+ case CKA_LABEL:
+ case CKA_TRUSTED:
+ case CKA_ID:
+ case CKA_ISSUER:
+ case CKA_SERIAL_NUMBER:
+ case CKA_START_DATE:
+ case CKA_END_DATE:
+ case CKA_DERIVE:
+ case CKA_SUBJECT:
+ case CKA_ENCRYPT:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ case CKA_SENSITIVE:
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ case CKA_EXTRACTABLE:
+ case CKA_OS_TOKENFLAGS:
+ case CKA_OS_SOPIN:
+ case CKA_OS_USERPIN:
+ return true;
+ default:
+ return false;
+ }
+}
+
+enum AttributeKind {
+ akUnknown,
+ akBoolean,
+ akInteger,
+ akBinary,
+ akAttrMap,
+ akMechSet
+};
+
+static AttributeKind attributeKind(CK_ATTRIBUTE_TYPE type)
+{
+ switch (type) {
+ case CKA_CLASS: return akInteger;
+ case CKA_TOKEN: return akBoolean;
+ case CKA_PRIVATE: return akBoolean;
+ case CKA_LABEL: return akBinary;
+ case CKA_APPLICATION: return akBinary;
+ case CKA_VALUE: return akBinary;
+ case CKA_OBJECT_ID: return akBinary;
+ case CKA_CERTIFICATE_TYPE: return akInteger;
+ case CKA_ISSUER: return akBinary;
+ case CKA_SERIAL_NUMBER: return akBinary;
+ case CKA_AC_ISSUER: return akBinary;
+ case CKA_OWNER: return akBinary;
+ case CKA_ATTR_TYPES: return akBinary;
+ case CKA_TRUSTED: return akBoolean;
+ case CKA_CERTIFICATE_CATEGORY: return akInteger;
+ case CKA_JAVA_MIDP_SECURITY_DOMAIN: return akInteger;
+ case CKA_URL: return akBinary;
+ case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: return akBinary;
+ case CKA_HASH_OF_ISSUER_PUBLIC_KEY: return akBinary;
+ case CKA_NAME_HASH_ALGORITHM: return akInteger;
+ case CKA_CHECK_VALUE: return akBinary;
+ case CKA_KEY_TYPE: return akInteger;
+ case CKA_SUBJECT: return akBinary;
+ case CKA_ID: return akBinary;
+ case CKA_SENSITIVE: return akBoolean;
+ case CKA_ENCRYPT: return akBoolean;
+ case CKA_DECRYPT: return akBoolean;
+ case CKA_WRAP: return akBoolean;
+ case CKA_UNWRAP: return akBoolean;
+ case CKA_SIGN: return akBoolean;
+ case CKA_SIGN_RECOVER: return akBoolean;
+ case CKA_VERIFY: return akBoolean;
+ case CKA_VERIFY_RECOVER: return akBoolean;
+ case CKA_DERIVE: return akBoolean;
+ case CKA_START_DATE: return akBinary;
+ case CKA_END_DATE: return akBinary;
+ case CKA_MODULUS: return akBinary;
+ case CKA_MODULUS_BITS: return akInteger;
+ case CKA_PUBLIC_EXPONENT: return akBinary;
+ case CKA_PRIVATE_EXPONENT: return akBinary;
+ case CKA_PRIME_1: return akBinary;
+ case CKA_PRIME_2: return akBinary;
+ case CKA_EXPONENT_1: return akBinary;
+ case CKA_EXPONENT_2: return akBinary;
+ case CKA_COEFFICIENT: return akBinary;
+ case CKA_PRIME: return akBinary;
+ case CKA_SUBPRIME: return akBinary;
+ case CKA_BASE: return akBinary;
+ case CKA_PRIME_BITS: return akInteger;
+ case CKA_SUBPRIME_BITS: return akInteger;
+ case CKA_VALUE_BITS: return akInteger;
+ case CKA_VALUE_LEN: return akInteger;
+ case CKA_EXTRACTABLE: return akBoolean;
+ case CKA_LOCAL: return akBoolean;
+ case CKA_NEVER_EXTRACTABLE: return akBoolean;
+ case CKA_ALWAYS_SENSITIVE: return akBoolean;
+ case CKA_KEY_GEN_MECHANISM: return akInteger;
+ case CKA_MODIFIABLE: return akBoolean;
+ case CKA_COPYABLE: return akBoolean;
+ case CKA_ECDSA_PARAMS: return akBinary;
+ case CKA_EC_POINT: return akBinary;
+ case CKA_SECONDARY_AUTH: return akBoolean;
+ case CKA_AUTH_PIN_FLAGS: return akInteger;
+ case CKA_ALWAYS_AUTHENTICATE: return akBoolean;
+ case CKA_WRAP_WITH_TRUSTED: return akBoolean;
+/*
+ case CKA_OTP_FORMAT:
+ case CKA_OTP_LENGTH:
+ case CKA_OTP_TIME_INTERVAL:
+ case CKA_OTP_USER_FRIENDLY_MODE:
+ case CKA_OTP_CHALLENGE_REQUIREMENT:
+ case CKA_OTP_TIME_REQUIREMENT:
+ case CKA_OTP_COUNTER_REQUIREMENT:
+ case CKA_OTP_PIN_REQUIREMENT:
+ case CKA_OTP_COUNTER:
+ case CKA_OTP_TIME:
+ case CKA_OTP_USER_IDENTIFIER:
+ case CKA_OTP_SERVICE_IDENTIFIER:
+ case CKA_OTP_SERVICE_LOGO:
+ case CKA_OTP_SERVICE_LOGO_TYPE:
+*/
+ case CKA_GOSTR3410_PARAMS: return akBinary;
+ case CKA_GOSTR3411_PARAMS: return akBinary;
+ case CKA_GOST28147_PARAMS: return akBinary;
+/*
+ case CKA_HW_FEATURE_TYPE:
+ case CKA_RESET_ON_INIT:
+ case CKA_HAS_RESET:
+ case CKA_PIXEL_X:
+ case CKA_PIXEL_Y:
+ case CKA_RESOLUTION:
+ case CKA_CHAR_ROWS:
+ case CKA_CHAR_COLUMNS:
+ case CKA_COLOR:
+ case CKA_BITS_PER_PIXEL:
+ case CKA_CHAR_SETS:
+ case CKA_ENCODING_METHODS:
+ case CKA_MIME_TYPES:
+ case CKA_MECHANISM_TYPE:
+ case CKA_REQUIRED_CMS_ATTRIBUTES:
+ case CKA_DEFAULT_CMS_ATTRIBUTES:
+ case CKA_SUPPORTED_CMS_ATTRIBUTES:
+*/
+ case CKA_WRAP_TEMPLATE: return akAttrMap;
+ case CKA_UNWRAP_TEMPLATE: return akAttrMap;
+ case CKA_DERIVE_TEMPLATE: return akAttrMap;
+ case CKA_ALLOWED_MECHANISMS: return akMechSet;
+
+ case CKA_OS_TOKENLABEL: return akBinary;
+ case CKA_OS_TOKENSERIAL: return akBinary;
+ case CKA_OS_TOKENFLAGS: return akInteger;
+ case CKA_OS_SOPIN: return akBinary;
+ case CKA_OS_USERPIN: return akBinary;
+
+ default: return akUnknown;
+ }
+}
+
+static bool decodeMechanismTypeSet(std::set<CK_MECHANISM_TYPE>& set, const unsigned char *binary, size_t size)
+{
+ for (size_t pos = 0; pos < size; )
+ {
+ // finished?
+ if (pos == size) break;
+
+ CK_MECHANISM_TYPE mechType;
+ if (pos + sizeof(mechType) > size)
+ {
+ ERROR_MSG("mechanism type set overrun");
+ return false;
+ }
+
+ memcpy(&mechType, binary + pos, sizeof(mechType));
+ pos += sizeof(mechType);
+
+ set.insert(mechType);
+ }
+
+ return true;
+}
+
+static void encodeMechanismTypeSet(ByteString& value, const std::set<CK_MECHANISM_TYPE>& set)
+{
+ for (std::set<CK_MECHANISM_TYPE>::const_iterator i = set.begin(); i != set.end(); ++i)
+ {
+ CK_MECHANISM_TYPE mechType = *i;
+ value += ByteString((unsigned char *) &mechType, sizeof(mechType));
+ }
+}
+
+static bool decodeAttributeMap(std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& map, const unsigned char *binary, size_t size)
+{
+ for (size_t pos = 0; pos < size; )
+ {
+ // finished?
+ if (pos == size) break;
+
+ CK_ATTRIBUTE_TYPE attrType;
+ if (pos + sizeof(attrType) > size)
+ {
+ goto overrun;
+ }
+ memcpy(&attrType, binary + pos, sizeof(attrType));
+ pos += sizeof(attrType);
+
+ AttributeKind attrKind;
+ if (pos + sizeof(AttributeKind) > size)
+ {
+ goto overrun;
+ }
+ memcpy(&attrKind, binary + pos, sizeof(attrKind));
+ pos += sizeof(attrKind);
+
+ // Verify using attributeKind()?
+
+ switch (attrKind)
+ {
+ case akBoolean:
+ {
+ bool value;
+ if (pos + sizeof(value) > size)
+ {
+ goto overrun;
+ }
+ memcpy(&value, binary + pos, sizeof(value));
+ pos += sizeof(value);
+
+ map.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, value));
+ }
+ break;
+
+ case akInteger:
+ {
+ unsigned long value;
+ if (pos + sizeof(value) > size)
+ {
+ goto overrun;
+ }
+ memcpy(&value, binary + pos, sizeof(value));
+ pos += sizeof(value);
+
+ map.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, value));
+ }
+ break;
+
+ case akBinary:
+ {
+ ByteString value;
+ unsigned long len;
+ if (pos + sizeof(len) > size)
+ {
+ goto overrun;
+ }
+ memcpy(&len, binary + pos, sizeof(len));
+ pos += sizeof(len);
+
+ if (pos + len > size)
+ {
+ goto overrun;
+ }
+ value.resize(len);
+ memcpy(&value[0], binary + pos, len);
+ pos += len;
+
+ map.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, value));
+ }
+ break;
+
+ case akMechSet:
+ {
+ unsigned long len;
+ if (pos + sizeof(len) > size)
+ {
+ goto overrun;
+ }
+ memcpy(&len, binary + pos, sizeof(len));
+ pos += sizeof(len);
+
+ if (pos + len > size)
+ {
+ goto overrun;
+ }
+
+ std::set<CK_MECHANISM_TYPE> value;
+ if (!decodeMechanismTypeSet(value, binary + pos, len)) {
+ return false;
+ }
+ pos += len;
+
+ map.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, value));
+ }
+ break;
+
+ default:
+ ERROR_MSG("unsupported attribute kind in attribute map");
+
+ return false;
+ }
+ }
+
+ return true;
+
+overrun:
+ ERROR_MSG("attribute map template overrun");
+
+ return false;
+}
+
+static bool encodeAttributeMap(ByteString& value, const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& attributes)
+{
+ for (std::map<CK_ATTRIBUTE_TYPE,OSAttribute>::const_iterator i = attributes.begin(); i != attributes.end(); ++i)
+ {
+ CK_ATTRIBUTE_TYPE attrType = i->first;
+ value += ByteString((unsigned char*) &attrType, sizeof(attrType));
+
+ OSAttribute attr = i->second;
+ if (attr.isBooleanAttribute())
+ {
+ AttributeKind attrKind = akBoolean;
+ value += ByteString((unsigned char*) &attrKind, sizeof(attrKind));
+
+ bool val = attr.getBooleanValue();
+ value += ByteString((unsigned char*) &val, sizeof(val));
+ }
+ else if (attr.isUnsignedLongAttribute())
+ {
+ AttributeKind attrKind = akInteger;
+ value += ByteString((unsigned char*) &attrKind, sizeof(attrKind));
+
+ unsigned long val = attr.getUnsignedLongValue();
+ value += ByteString((unsigned char*) &val, sizeof(val));
+ }
+ else if (attr.isByteStringAttribute())
+ {
+ AttributeKind attrKind = akBinary;
+ value += ByteString((unsigned char*) &attrKind, sizeof(attrKind));
+
+ ByteString val = attr.getByteStringValue();
+ unsigned long len = val.size();
+ value += ByteString((unsigned char*) &len, sizeof(len));
+ value += val;
+ }
+ else if (attr.isMechanismTypeSetAttribute())
+ {
+ AttributeKind attrKind = akMechSet;
+ value += ByteString((unsigned char*) &attrKind, sizeof(attrKind));
+
+ ByteString val;
+ encodeMechanismTypeSet(val, attr.getMechanismTypeSetValue());
+
+ unsigned long len = val.size();
+ value += ByteString((unsigned char*) &len, sizeof(len));
+ value += val;
+ }
+ else
+ {
+ ERROR_MSG("unsupported attribute kind for attribute map");
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+OSAttribute *DBObject::accessAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ switch (attributeKind(type))
+ {
+ case akUnknown:
+ return NULL;
+ case akBoolean:
+ {
+ // try to find the attribute in the boolean attribute table
+ DB::Statement statement = _connection->prepare(
+ "select value from attribute_boolean where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ if (!statement.isValid())
+ {
+ return NULL;
+ }
+ DB::Result result = _connection->perform(statement);
+ if (!result.isValid())
+ {
+ return NULL;
+ }
+ // Store the attribute in the transaction when it is active.
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*> *attrs = &_attributes;
+ if (_transaction)
+ attrs = _transaction;
+
+ bool value = result.getInt(1) != 0;
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = attrs->find(type);
+ OSAttribute *attr;
+ if (it != attrs->end())
+ {
+ if (it->second != NULL)
+ {
+ delete it->second;
+ }
+
+ it->second = new OSAttribute(value);
+ attr = it->second;
+ }
+ else
+ {
+ attr = new OSAttribute(value);
+ (*attrs)[type] = attr;
+ }
+ return attr;
+ }
+ case akInteger:
+ {
+ // try to find the attribute in the integer attribute table
+ DB::Statement statement = _connection->prepare(
+ "select value from attribute_integer where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ if (!statement.isValid())
+ {
+ return NULL;
+ }
+ DB::Result result = _connection->perform(statement);
+ if (!result.isValid())
+ {
+ return NULL;
+ }
+ // Store the attribute in the transaction when it is active.
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*> *attrs = &_attributes;
+ if (_transaction)
+ attrs = _transaction;
+
+ unsigned long value = result.getULongLong(1);
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = attrs->find(type);
+ OSAttribute *attr;
+ if (it != attrs->end())
+ {
+ if (it->second != NULL)
+ {
+ delete it->second;
+ }
+
+ it->second = new OSAttribute(value);
+ attr = it->second;
+ }
+ else
+ {
+ attr = new OSAttribute(value);
+ (*attrs)[type] = attr;
+ }
+ return attr;
+ }
+ case akBinary:
+ {
+ // try to find the attribute in the binary attribute table
+ DB::Statement statement = _connection->prepare(
+ "select value from attribute_binary where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ if (!statement.isValid())
+ {
+ return NULL;
+ }
+ DB::Result result = _connection->perform(statement);
+ if (!result.isValid())
+ {
+ return NULL;
+ }
+ // Store the attribute in the transaction when it is active.
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*> *attrs = &_attributes;
+ if (_transaction)
+ attrs = _transaction;
+
+ const unsigned char *value = result.getBinary(1);
+ size_t size = result.getFieldLength(1);
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = attrs->find(type);
+ OSAttribute *attr;
+ if (it != attrs->end())
+ {
+ if (it->second != NULL)
+ {
+ delete it->second;
+ }
+
+ it->second = new OSAttribute(ByteString(value,size));
+ attr = it->second;
+ }
+ else
+ {
+ attr = new OSAttribute(ByteString(value,size));
+ (*attrs)[type] = attr;
+ return attr;
+ }
+ return attr;
+ }
+ case akMechSet:
+ {
+ // try to find the attribute in the binary attribute table
+ DB::Statement statement = _connection->prepare(
+ "select value from attribute_binary where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ if (!statement.isValid())
+ {
+ return NULL;
+ }
+ DB::Result result = _connection->perform(statement);
+ if (!result.isValid())
+ {
+ return NULL;
+ }
+ // Store the attribute in the transaction when it is active.
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*> *attrs = &_attributes;
+ if (_transaction)
+ attrs = _transaction;
+
+ const unsigned char *value = result.getBinary(1);
+ size_t size = result.getFieldLength(1);
+
+ std::set<CK_MECHANISM_TYPE> set;
+ if (!decodeMechanismTypeSet(set, value, size))
+ {
+ return NULL;
+ }
+
+ OSAttribute *attr;
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = attrs->find(type);
+ if (it != attrs->end())
+ {
+ if (it->second != NULL)
+ {
+ delete it->second;
+ }
+
+ it->second = new OSAttribute(set);
+ attr = it->second;
+ }
+ else
+ {
+ attr = new OSAttribute(set);
+ (*attrs)[type] = attr;
+ return attr;
+ }
+ return attr;
+ }
+ case akAttrMap:
+ {
+ // try to find the attribute in the array attribute table
+ DB::Statement statement = _connection->prepare(
+ "select value from attribute_array where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ if (!statement.isValid())
+ {
+ return NULL;
+ }
+ DB::Result result = _connection->perform(statement);
+ if (!result.isValid())
+ {
+ return NULL;
+ }
+ // Store the attribute in the transaction when it is active.
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*> *attrs = &_attributes;
+ if (_transaction)
+ attrs = _transaction;
+
+ const unsigned char *binary = result.getBinary(1);
+ size_t size = result.getFieldLength(1);
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = attrs->find(type);
+ OSAttribute *attr;
+ if (it != attrs->end())
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> value;
+ if (!decodeAttributeMap(value,binary,size))
+ {
+ return NULL;
+ }
+
+ if (it->second != NULL)
+ {
+ delete it->second;
+ }
+
+ it->second = new OSAttribute(value);
+ attr = it->second;
+ }
+ else
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> value;
+ if (!decodeAttributeMap(value,binary,size))
+ {
+ return NULL;
+ }
+ attr = new OSAttribute(value);
+ (*attrs)[type] = attr;
+ return attr;
+ }
+ return attr;
+ }
+ }
+
+ return NULL;
+}
+
+// Retrieve the specified attribute for internal use
+// Calling function must lock the mutex
+OSAttribute* DBObject::getAttributeDB(CK_ATTRIBUTE_TYPE type)
+{
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return NULL;
+ }
+
+ if (_objectId == 0)
+ {
+ ERROR_MSG("Cannot read from invalid object.");
+ return NULL;
+ }
+
+ // If a transaction is in progress, we can just return the attribute from the transaction.
+ if (_transaction)
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _transaction->find(type);
+ if (it != _transaction->end())
+ return it->second;
+ }
+
+ // If the attribute exists and is non-modifiable then return a previously retrieved attribute value.
+ if (!isModifiable(type))
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _attributes.find(type);
+ if (it != _attributes.end())
+ {
+ return it->second;
+ }
+ }
+
+ return accessAttribute(type);
+}
+
+// Check if the specified attribute exists
+bool DBObject::attributeExists(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(_mutex);
+
+ return getAttributeDB(type) != NULL;
+}
+
+// Retrieve the specified attribute
+OSAttribute DBObject::getAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(_mutex);
+
+ OSAttribute* attr = getAttributeDB(type);
+ if (attr == NULL) return OSAttribute((unsigned long)0);
+
+ return *attr;
+}
+
+bool DBObject::getBooleanValue(CK_ATTRIBUTE_TYPE type, bool val)
+{
+ MutexLocker lock(_mutex);
+
+ OSAttribute* attr = getAttributeDB(type);
+ if (attr == NULL) return val;
+
+ if (attr->isBooleanAttribute())
+ {
+ return attr->getBooleanValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not a boolean: 0x%08X", type);
+ return val;
+ }
+}
+
+unsigned long DBObject::getUnsignedLongValue(CK_ATTRIBUTE_TYPE type, unsigned long val)
+{
+ MutexLocker lock(_mutex);
+
+ OSAttribute* attr = getAttributeDB(type);
+ if (attr == NULL) return val;
+
+ if (attr->isUnsignedLongAttribute())
+ {
+ return attr->getUnsignedLongValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not an unsigned long: 0x%08X", type);
+ return val;
+ }
+}
+
+ByteString DBObject::getByteStringValue(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(_mutex);
+
+ ByteString val;
+
+ OSAttribute* attr = getAttributeDB(type);
+ if (attr == NULL) return val;
+
+ if (attr->isByteStringAttribute())
+ {
+ return attr->getByteStringValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not a byte string: 0x%08X", type);
+ return val;
+ }
+}
+
+CK_ATTRIBUTE_TYPE DBObject::nextAttributeType(CK_ATTRIBUTE_TYPE)
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+ if (_objectId == 0)
+ {
+ ERROR_MSG("Cannot get next attribute for invalid object.");
+ return false;
+ }
+
+ // FIXME: implement for C_CopyObject
+ return CKA_CLASS;
+}
+
+// Set the specified attribute
+bool DBObject::setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute)
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+ if (_objectId == 0)
+ {
+ ERROR_MSG("Cannot update invalid object.");
+ return false;
+ }
+
+ // Retrieve and existing attribute if it exists or NULL if it doesn't
+ OSAttribute *attr = getAttributeDB(type);
+
+ // Update an existing attribute...
+ if (attr)
+ {
+ DB::Statement statement;
+ if (attr->isBooleanAttribute())
+ {
+ // update boolean attribute
+ statement = _connection->prepare(
+ "update attribute_boolean set value=%d where type=%lu and object_id=%lld",
+ attribute.getBooleanValue() ? 1 : 0,
+ type,
+ _objectId);
+ }
+ else if (attr->isUnsignedLongAttribute())
+ {
+ // update integer attribute
+ statement = _connection->prepare(
+ "update attribute_integer set value=%lld where type=%lu and object_id=%lld",
+ static_cast<long long>(attribute.getUnsignedLongValue()),
+ type,
+ _objectId);
+ }
+ else if (attr->isByteStringAttribute())
+ {
+ // update binary attribute
+ statement = _connection->prepare(
+ "update attribute_binary set value=? where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ DB::Bindings(statement).bindBlob(1, attribute.getByteStringValue().const_byte_str(), attribute.getByteStringValue().size(), SQLITE_STATIC);
+ }
+ else if (attr->isMechanismTypeSetAttribute())
+ {
+ // update binary attribute
+ ByteString value;
+ encodeMechanismTypeSet(value, attribute.getMechanismTypeSetValue());
+
+ statement = _connection->prepare(
+ "update attribute_binary set value=? where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ DB::Bindings(statement).bindBlob(1, value.const_byte_str(), value.size(), SQLITE_TRANSIENT);
+ }
+ else if (attr->isAttributeMapAttribute())
+ {
+ // update attribute map attribute
+ ByteString value;
+ if (!encodeAttributeMap(value, attribute.getAttributeMapValue()))
+ {
+ return false;
+ }
+
+ statement = _connection->prepare(
+ "update attribute_array set value=? where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ DB::Bindings(statement).bindBlob(1, value.const_byte_str(), value.size(), SQLITE_TRANSIENT);
+ }
+
+ // Statement is valid when a prepared statement has been attached to it.
+ if (statement.isValid())
+ {
+ if (!_connection->execute(statement))
+ {
+ ERROR_MSG("Failed to update attribute %lu for object %lld",type,_objectId);
+ return false;
+ }
+
+ if (_transaction)
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _transaction->find(type);
+ if (it != _transaction->end())
+ *it->second = attribute;
+ else
+ (*_transaction)[type] = new OSAttribute(attribute);
+ } else
+ *attr = attribute;
+ return true;
+ }
+ }
+
+ DB::Statement statement;
+
+ // Insert the attribute, because it is currently unknown
+ if (attribute.isBooleanAttribute())
+ {
+ // Could not update it, so we need to insert it.
+ statement = _connection->prepare(
+ "insert into attribute_boolean (value,type,object_id) values (%d,%lu,%lld)",
+ attribute.getBooleanValue() ? 1 : 0,
+ type,
+ _objectId);
+
+ }
+ else if (attribute.isUnsignedLongAttribute())
+ {
+ // Could not update it, so we need to insert it.
+ statement = _connection->prepare(
+ "insert into attribute_integer (value,type,object_id) values (%lld,%lu,%lld)",
+ static_cast<long long>(attribute.getUnsignedLongValue()),
+ type,
+ _objectId);
+ }
+ else if (attribute.isByteStringAttribute())
+ {
+ // Could not update it, so we need to insert it.
+ statement = _connection->prepare(
+ "insert into attribute_binary (value,type,object_id) values (?,%lu,%lld)",
+ type,
+ _objectId);
+
+ DB::Bindings(statement).bindBlob(1, attribute.getByteStringValue().const_byte_str(), attribute.getByteStringValue().size(), SQLITE_STATIC);
+ }
+ else if (attribute.isMechanismTypeSetAttribute())
+ {
+ // Could not update it, so we need to insert it.
+ ByteString value;
+ encodeMechanismTypeSet(value, attribute.getMechanismTypeSetValue());
+
+ statement = _connection->prepare(
+ "insert into attribute_binary (value,type,object_id) values (?,%lu,%lld)",
+ type,
+ _objectId);
+ DB::Bindings(statement).bindBlob(1, value.const_byte_str(), value.size(), SQLITE_TRANSIENT);
+ }
+ else if (attribute.isAttributeMapAttribute())
+ {
+ // Could not update it, so we need to insert it.
+ ByteString value;
+ if (!encodeAttributeMap(value, attribute.getAttributeMapValue()))
+ {
+ return false;
+ }
+
+ statement = _connection->prepare(
+ "insert into attribute_array (value,type,object_id) values (?,%lu,%lld)",
+ type,
+ _objectId);
+ DB::Bindings(statement).bindBlob(1, value.const_byte_str(), value.size(), SQLITE_TRANSIENT);
+ }
+
+ // Statement is valid when a prepared statement has been attached to it.
+ if (statement.isValid())
+ {
+ if (!_connection->execute(statement))
+ {
+ ERROR_MSG("Failed to insert attribute %lu for object %lld",type,_objectId);
+ return false;
+ }
+
+ if (_transaction)
+ (*_transaction)[type] = new OSAttribute(attribute);
+ else
+ _attributes[type] = new OSAttribute(attribute);
+ return true;
+ }
+
+ return false;
+}
+
+// Set the specified attribute
+bool DBObject::deleteAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+ if (_objectId == 0)
+ {
+ ERROR_MSG("Cannot update invalid object.");
+ return false;
+ }
+
+ // Retrieve and existing attribute if it exists or NULL if it doesn't
+ OSAttribute *attr = getAttributeDB(type);
+ if (attr == NULL)
+ {
+ ERROR_MSG("Cannot delete an attribute that doesn't exist.");
+ return false;
+ }
+
+ DB::Statement statement;
+ if (attr->isBooleanAttribute())
+ {
+ // delete boolean attribute
+ statement = _connection->prepare(
+ "delete from attribute_boolean where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ }
+ else if (attr->isUnsignedLongAttribute())
+ {
+ // delete integer attribute
+ statement = _connection->prepare(
+ "delete from attribute_integer where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ }
+ else if (attr->isByteStringAttribute() || attr -> isMechanismTypeSetAttribute())
+ {
+ // delete binary attribute
+ statement = _connection->prepare(
+ "delete from attribute_binary where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ }
+ else if (attr->isAttributeMapAttribute())
+ {
+ // delete attribute map attribute
+ statement = _connection->prepare(
+ "delete from attribute_array where type=%lu and object_id=%lld",
+ type,
+ _objectId);
+ }
+
+ // Statement is valid when a prepared statement has been attached to it.
+ if (statement.isValid())
+ {
+ if (!_connection->execute(statement))
+ {
+ ERROR_MSG("Failed to delete attribute %lu for object %lld",type,_objectId);
+ return false;
+ }
+
+ if (_transaction)
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _transaction->find(type);
+ if (it != _transaction->end())
+ {
+ delete it->second;
+ it->second = NULL;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+// The validity state of the object
+bool DBObject::isValid()
+{
+ MutexLocker lock(_mutex);
+
+ return _objectId != 0 && _connection != NULL;
+}
+
+// Start an attribute set transaction; this method is used when - for
+// example - a key is generated and all its attributes need to be
+// persisted in one go.
+//
+// N.B.: Starting a transaction locks the object!
+bool DBObject::startTransaction(Access access)
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+
+ if (_transaction)
+ {
+ ERROR_MSG("Transaction is already active.");
+ return false;
+ }
+
+ _transaction = new std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>;
+ if (_transaction == NULL)
+ {
+ ERROR_MSG("Not enough memory to start transaction.");
+ return false;
+ }
+
+ if (_connection->inTransaction())
+ {
+ ERROR_MSG("Transaction in database is already active.");
+ return false;
+ }
+
+ // Ask the connection to start the transaction.
+ if (access == ReadWrite)
+ return _connection->beginTransactionRW();
+ else
+ return _connection->beginTransactionRO();
+}
+
+// Commit an attribute transaction
+bool DBObject::commitTransaction()
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+
+ if (_transaction == NULL)
+ {
+ ERROR_MSG("No transaction active.");
+ return false;
+ }
+
+ if (!_connection->commitTransaction())
+ {
+ return false;
+ }
+
+ // Copy the values from the internally stored transaction to the _attributes field.
+ for (std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _transaction->begin(); it!=_transaction->end(); ++it) {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator attr_it = _attributes.find(it->first);
+ if (attr_it == _attributes.end())
+ {
+ _attributes[it->first] = it->second;
+ }
+ else
+ {
+ *attr_it->second = *it->second;
+ delete it->second;
+ }
+ it->second = NULL;
+ }
+ delete _transaction;
+ _transaction = NULL;
+ return true;
+}
+
+// Abort an attribute transaction; loads back the previous version of the object from disk
+bool DBObject::abortTransaction()
+{
+ MutexLocker lock(_mutex);
+
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Object is not connected to the database.");
+ return false;
+ }
+
+ // Forget the atributes that were set during the transaction.
+ if (_transaction)
+ {
+ for (std::map<CK_ATTRIBUTE_TYPE,OSAttribute*>::iterator it = _transaction->begin(); it!=_transaction->end(); ++it) {
+ delete it->second;
+ it->second = NULL;
+ }
+ delete _transaction;
+ _transaction = NULL;
+ }
+
+ return _connection->rollbackTransaction();
+}
+
+// Destroy the object; WARNING: pointers to the object become invalid after this call
+bool DBObject::destroyObject()
+{
+ // NOTE: Do not lock _mutex, because _token will call us back and cause a deadlock.
+ // There is no need to lock anyway as _token is a non-mutable pointer, so no race
+ // conditions possible.
+
+ if (_token == NULL)
+ {
+ ERROR_MSG("Cannot destroy an object that is not associated with a token");
+ return false;
+ }
+
+ return _token->deleteObject(this);
+}
diff --git a/SoftHSMv2/src/lib/object_store/DBObject.h b/SoftHSMv2/src/lib/object_store/DBObject.h
new file mode 100644
index 0000000..4dc1249
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/DBObject.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObject.h
+
+ This class represents object records in a database
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBOBJECT_H
+#define _SOFTHSM_V2_DBOBJECT_H
+
+#include "config.h"
+#include "OSAttribute.h"
+#include "cryptoki.h"
+#include "OSObject.h"
+#include "ObjectStoreToken.h"
+
+#include "MutexFactory.h"
+#include <string>
+
+namespace DB { class Connection; }
+
+class DBObject : public OSObject
+{
+public:
+ // Constructor for creating or accessing an object, don't do anything yet.
+ DBObject(DB::Connection *connection, ObjectStoreToken *token = NULL);
+
+ // Constructor for accessing an object with an objectId known to exists
+ DBObject(DB::Connection *connection, ObjectStoreToken *token, long long objectId);
+
+ // Destructor
+ virtual ~DBObject();
+
+ // Will drop any internal references to the connection
+ void dropConnection();
+
+ // create tables to support storage of attributes for the object.
+ bool createTables();
+
+ // drop tables that support storage of attributes for the object.
+ bool dropTables();
+
+ // Find an existing object.
+ bool find(long long objectId);
+
+ // Insert a new object into the database and retrieve the object id associated with it.
+ bool insert();
+
+ // Remove an existing object from the database and reset the object id to zero.
+ bool remove();
+
+ // Object id associated with this object.
+ long long objectId();
+
+ // Check if the specified attribute exists
+ virtual bool attributeExists(CK_ATTRIBUTE_TYPE type);
+
+ // Retrieve the specified attribute
+ virtual OSAttribute getAttribute(CK_ATTRIBUTE_TYPE type);
+ virtual bool getBooleanValue(CK_ATTRIBUTE_TYPE type, bool val);
+ virtual unsigned long getUnsignedLongValue(CK_ATTRIBUTE_TYPE type, unsigned long val);
+ virtual ByteString getByteStringValue(CK_ATTRIBUTE_TYPE type);
+
+ // Retrieve the next attribute type
+ virtual CK_ATTRIBUTE_TYPE nextAttributeType(CK_ATTRIBUTE_TYPE type);
+
+ // Set the specified attribute
+ virtual bool setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute);
+
+ // Delete the specified attribute
+ virtual bool deleteAttribute(CK_ATTRIBUTE_TYPE type);
+
+ // The validity state of the object
+ virtual bool isValid();
+
+ // Start an attribute set transaction; this method is used when - for
+ // example - a key is generated and all its attributes need to be
+ // persisted in one go.
+ //
+ // N.B.: Starting a transaction locks the object!
+ //
+ // Function returns false in case a transaction is already in progress
+ virtual bool startTransaction(Access access);
+
+ // Commit an attribute transaction; returns false if no transaction is in progress
+ virtual bool commitTransaction();
+
+ // Abort an attribute transaction; loads back the previous version of the object from disk;
+ // returns false if no transaction was in progress
+ virtual bool abortTransaction();
+
+ // Destroys the object (warning, any pointers to the object are no longer
+ // valid after this call because delete is called!)
+ virtual bool destroyObject();
+
+private:
+ // Disable copy constructor and assignment
+ DBObject();
+ DBObject(const DBObject&);
+ DBObject & operator= (const DBObject &);
+
+ // Mutex object for thread-safeness
+ Mutex* _mutex;
+
+ DB::Connection *_connection;
+ ObjectStoreToken *_token;
+ long long _objectId;
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*> _attributes;
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute*> *_transaction;
+
+ OSAttribute* getAttributeDB(CK_ATTRIBUTE_TYPE type);
+ OSAttribute* accessAttribute(CK_ATTRIBUTE_TYPE type);
+};
+
+#endif // !_SOFTHSM_V2_DBOBJECT_H
+
diff --git a/SoftHSMv2/src/lib/object_store/DBToken.cpp b/SoftHSMv2/src/lib/object_store/DBToken.cpp
new file mode 100644
index 0000000..e734372
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/DBToken.cpp
@@ -0,0 +1,874 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBToken.cpp
+
+ The token class; a token is stored in a directory containing a single
+ database file.
+ Each object is stored in multiple tables with every attribute base type
+ stored in a different table.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSAttributes.h"
+#include "OSAttribute.h"
+#include "OSPathSep.h"
+
+#include "cryptoki.h"
+#include "DBToken.h"
+#include "DBObject.h"
+#include "DB.h"
+
+#include "Directory.h"
+
+#include <vector>
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+#include <cstdio>
+#include <sys/stat.h>
+#include <errno.h>
+
+const char * const DBTOKEN_FILE = "sqlite3.db";
+const long long DBTOKEN_OBJECT_TOKENINFO = 1;
+
+// Constructor for creating a new token.
+DBToken::DBToken(const std::string &baseDir, const std::string &tokenName, const ByteString &label, const ByteString &serial)
+ : _connection(NULL), _tokenMutex(NULL)
+{
+ std::string tokenDir = baseDir + OS_PATHSEP + tokenName;
+ std::string tokenPath = tokenDir + OS_PATHSEP + DBTOKEN_FILE;
+
+ // Refuse to open an already existing database.
+ FILE *f = fopen(tokenPath.c_str(),"r");
+ if (f)
+ {
+ fclose(f);
+ ERROR_MSG("Refusing to overwrite and existing database at \"%s\"", tokenPath.c_str());
+ return;
+ }
+
+ // First create the directory for the token, we expect basePath to already exist
+ if (mkdir(tokenDir.c_str(), S_IFDIR | S_IRWXU))
+ {
+ // Allow the directory to exists already.
+ if (errno != EEXIST)
+ {
+ ERROR_MSG("Unable to create directory \"%s\"", tokenDir.c_str());
+ return;
+ }
+ }
+
+ // Create
+ _connection = DB::Connection::Create(tokenDir, DBTOKEN_FILE);
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Failed to create a database connection for \"%s\"", tokenPath.c_str());
+ return;
+ }
+
+ if (!_connection->connect())
+ {
+ delete _connection;
+ _connection = NULL;
+
+ ERROR_MSG("Failed to connect to the database at \"%s\"", tokenPath.c_str());
+
+ // Now remove the token directory
+ if (remove(tokenDir.c_str()))
+ {
+ ERROR_MSG("Failed to remove the token directory \"%s\"", tokenDir.c_str());
+ }
+
+ return;
+ }
+
+ // Create a DBObject for the established connection to the database.
+ DBObject tokenObject(_connection);
+
+ // First create the tables that support storage of object attributes and then insert the object containing
+ // the token info into the database.
+ if (!tokenObject.createTables() || !tokenObject.insert() || tokenObject.objectId()!=DBTOKEN_OBJECT_TOKENINFO)
+ {
+ tokenObject.dropConnection();
+
+ _connection->close();
+ delete _connection;
+ _connection = NULL;
+
+ ERROR_MSG("Failed to create tables for storing objects in database at \"%s\"", tokenPath.c_str());
+ return;
+ }
+
+ // Set the initial attributes
+ CK_ULONG flags =
+ CKF_RNG |
+ CKF_LOGIN_REQUIRED | // FIXME: check
+ CKF_RESTORE_KEY_NOT_NEEDED |
+ CKF_TOKEN_INITIALIZED |
+ CKF_SO_PIN_LOCKED |
+ CKF_SO_PIN_TO_BE_CHANGED;
+
+ OSAttribute tokenLabel(label);
+ OSAttribute tokenSerial(serial);
+ OSAttribute tokenFlags(flags);
+
+ if (!tokenObject.setAttribute(CKA_OS_TOKENLABEL, tokenLabel) ||
+ !tokenObject.setAttribute(CKA_OS_TOKENSERIAL, tokenSerial) ||
+ !tokenObject.setAttribute(CKA_OS_TOKENFLAGS, tokenFlags))
+ {
+ _connection->close();
+ delete _connection;
+ _connection = NULL;
+
+ // Now remove the token file
+ if (remove(tokenPath.c_str()))
+ {
+ ERROR_MSG("Failed to remove the token file at \"%s\"", tokenPath.c_str());
+ }
+
+ // Now remove the token directory
+ if (remove(tokenDir.c_str()))
+ {
+ ERROR_MSG("Failed to remove the token directory at \"%s\"", tokenDir.c_str());
+ }
+ return;
+ }
+
+ _tokenMutex = MutexFactory::i()->getMutex();
+ // Success!
+}
+
+// Constructor for accessing an existing token.
+DBToken::DBToken(const std::string &baseDir, const std::string &tokenName)
+ : _connection(NULL), _tokenMutex(NULL)
+{
+ std::string tokenDir = baseDir + OS_PATHSEP + tokenName;
+ std::string tokenPath = tokenDir + OS_PATHSEP + DBTOKEN_FILE;
+
+ // Refuse to open an already existing database.
+ FILE *f = fopen(tokenPath.c_str(),"r");
+ if (f == NULL)
+ {
+ ERROR_MSG("Refusing to open a non-existant database at \"%s\"", tokenPath.c_str());
+ return;
+ }
+ fclose(f);
+
+ // Create a database connection.
+ _connection = DB::Connection::Create(tokenDir, DBTOKEN_FILE);
+ if (_connection == NULL)
+ {
+ ERROR_MSG("Failed to create a database connection for \"%s\"", tokenPath.c_str());
+ return;
+ }
+
+ if (!_connection->connect())
+ {
+ delete _connection;
+ _connection = NULL;
+
+ ERROR_MSG("Failed to connect to the database at \"%s\"", tokenPath.c_str());
+
+ return;
+ }
+
+ // Find the DBObject for the established connection to the database.
+ DBObject tokenObject(_connection);
+
+ // First find the token obect that indicates the token is properly initialized.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ tokenObject.dropConnection();
+
+ _connection->close();
+ delete _connection;
+ _connection = NULL;
+
+ ERROR_MSG("Failed to open token object in the token database at \"%s\"", tokenPath.c_str());
+ return;
+ }
+
+ _tokenMutex = MutexFactory::i()->getMutex();
+
+ // Success!
+}
+
+DBToken *DBToken::createToken(const std::string basePath, const std::string tokenDir, const ByteString &label, const ByteString &serial)
+{
+ Directory baseDir(basePath);
+
+ if (!baseDir.isValid())
+ {
+ return NULL;
+ }
+
+ // Create the token directory
+ if (!baseDir.mkdir(tokenDir))
+ {
+ return NULL;
+ }
+
+ DBToken *token = new DBToken(basePath, tokenDir, label, serial);
+ if (!token->isValid())
+ {
+ baseDir.rmdir(tokenDir);
+
+ delete token;
+ return NULL;
+ }
+
+ DEBUG_MSG("Created new token %s", tokenDir.c_str());
+
+ return token;
+}
+
+DBToken *DBToken::accessToken(const std::string &basePath, const std::string &tokenDir)
+{
+ return new DBToken(basePath, tokenDir);
+}
+
+// Destructor
+DBToken::~DBToken()
+{
+ if (_tokenMutex)
+ {
+ MutexFactory::i()->recycleMutex(_tokenMutex);
+ _tokenMutex = NULL;
+ }
+
+ std::map<long long, OSObject*> cleanUp = _allObjects;
+ _allObjects.clear();
+ for (std::map<long long, OSObject*>::iterator i = cleanUp.begin(); i != cleanUp.end(); ++i)
+ {
+ delete i->second;
+ }
+
+ if (_connection)
+ {
+ delete _connection;
+ _connection = NULL;
+ }
+}
+
+// Set the SO PIN
+bool DBToken::setSOPIN(const ByteString& soPINBlob)
+{
+ if (_connection == NULL) return false;
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadWrite))
+ {
+ ERROR_MSG("Unable to start a transaction for updating the SOPIN and TOKENFLAGS in token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ OSAttribute soPIN(soPINBlob);
+ if (!tokenObject.setAttribute(CKA_OS_SOPIN, soPIN))
+ {
+ ERROR_MSG("Error while setting SOPIN in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.attributeExists(CKA_OS_TOKENFLAGS))
+ {
+ ERROR_MSG("Error while getting TOKENFLAGS from token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ // Retrieve flags from the database and reset flags related to tries and expiration of the SOPIN.
+ CK_ULONG flags = tokenObject.getAttribute(CKA_OS_TOKENFLAGS).getUnsignedLongValue()
+ & ~(CKF_SO_PIN_COUNT_LOW | CKF_SO_PIN_FINAL_TRY | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED);
+
+ OSAttribute changedTokenFlags(flags);
+ if (!tokenObject.setAttribute(CKA_OS_TOKENFLAGS, changedTokenFlags))
+ {
+ ERROR_MSG("Error while setting TOKENFLAGS in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.commitTransaction())
+ {
+ ERROR_MSG("Error while committing SOPIN and TOKENFLAGS changes to token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ return true;
+}
+
+// Get the SO PIN
+bool DBToken::getSOPIN(ByteString& soPINBlob)
+{
+ if (_connection == NULL) return false;
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadOnly))
+ {
+ ERROR_MSG("Unable to start a transaction for getting the SOPIN from token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.attributeExists(CKA_OS_SOPIN))
+ {
+ ERROR_MSG("Error while getting SOPIN from token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ tokenObject.commitTransaction();
+ soPINBlob = tokenObject.getAttribute(CKA_OS_SOPIN).getByteStringValue();
+ return true;
+}
+
+// Set the user PIN
+bool DBToken::setUserPIN(ByteString userPINBlob)
+{
+ if (_connection == NULL) return false;
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadWrite))
+ {
+ ERROR_MSG("Unable to start a transaction for updating the USERPIN and TOKENFLAGS in token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ OSAttribute userPIN(userPINBlob);
+ if (!tokenObject.setAttribute(CKA_OS_USERPIN, userPIN))
+ {
+ ERROR_MSG("Error while setting USERPIN in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.attributeExists(CKA_OS_TOKENFLAGS))
+ {
+ ERROR_MSG("Error while getting TOKENFLAGS from token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ // Retrieve flags from the database and reset flags related to tries and expiration of the SOPIN.
+ CK_ULONG flags = tokenObject.getAttribute(CKA_OS_TOKENFLAGS).getUnsignedLongValue()
+ | (CKF_USER_PIN_INITIALIZED & ~(CKF_USER_PIN_COUNT_LOW | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_LOCKED | CKF_USER_PIN_TO_BE_CHANGED));
+
+ OSAttribute changedTokenFlags(flags);
+ if (!tokenObject.setAttribute(CKA_OS_TOKENFLAGS, changedTokenFlags))
+ {
+ ERROR_MSG("Error while setting TOKENFLAGS in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.commitTransaction())
+ {
+ ERROR_MSG("Error while committing USERPIN and TOKENFLAGS changes to token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ return true;
+}
+
+// Get the user PIN
+bool DBToken::getUserPIN(ByteString& userPINBlob)
+{
+ if (_connection == NULL) return false;
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadOnly))
+ {
+ ERROR_MSG("Unable to start a transaction for getting the USERPIN from token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.attributeExists(CKA_OS_USERPIN))
+ {
+ ERROR_MSG("Error while getting USERPIN from token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ tokenObject.commitTransaction();
+ userPINBlob = tokenObject.getAttribute(CKA_OS_USERPIN).getByteStringValue();
+ return true;
+}
+
+// Retrieve the token label
+bool DBToken::getTokenLabel(ByteString& label)
+{
+ if (_connection == NULL) return false;
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadOnly))
+ {
+ ERROR_MSG("Unable to start a transaction for getting the TOKENLABEL from token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.attributeExists(CKA_OS_TOKENLABEL))
+ {
+ ERROR_MSG("Error while getting TOKENLABEL from token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ tokenObject.commitTransaction();
+ label = tokenObject.getAttribute(CKA_OS_TOKENLABEL).getByteStringValue();
+ return true;
+}
+
+// Retrieve the token serial
+bool DBToken::getTokenSerial(ByteString& serial)
+{
+ if (_connection == NULL) return false;
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadOnly))
+ {
+ ERROR_MSG("Unable to start a transaction for getting the TOKENSERIAL from token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.attributeExists(CKA_OS_TOKENSERIAL))
+ {
+ ERROR_MSG("Error while getting TOKENSERIAL from token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ tokenObject.commitTransaction();
+ serial = tokenObject.getAttribute(CKA_OS_TOKENSERIAL).getByteStringValue();
+ return true;
+}
+
+// Get the token flags
+bool DBToken::getTokenFlags(CK_ULONG& flags)
+{
+ if (_connection == NULL) return false;
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadOnly))
+ {
+ ERROR_MSG("Unable to start a transaction for updating the SOPIN and TOKENFLAGS in token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.attributeExists(CKA_OS_TOKENFLAGS))
+ {
+ ERROR_MSG("Error while getting TOKENFLAGS from token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ tokenObject.commitTransaction();
+ flags = tokenObject.getAttribute(CKA_OS_TOKENFLAGS).getUnsignedLongValue();
+ return true;
+}
+
+// Set the token flags
+bool DBToken::setTokenFlags(const CK_ULONG flags)
+{
+ if (_connection == NULL) return false;
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadWrite))
+ {
+ ERROR_MSG("Unable to start a transaction for setting the TOKENFLAGS in token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ OSAttribute tokenFlags(flags);
+ if (!tokenObject.setAttribute(CKA_OS_TOKENFLAGS, tokenFlags))
+ {
+ ERROR_MSG("Error while setting TOKENFLAGS in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.commitTransaction())
+ {
+ ERROR_MSG("Error while committing TOKENFLAGS changes to token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ return true;
+}
+
+// Retrieve objects
+std::set<OSObject *> DBToken::getObjects()
+{
+ std::set<OSObject*> objects;
+ getObjects(objects);
+ return objects;
+}
+
+void DBToken::getObjects(std::set<OSObject*> &objects)
+{
+ if (_connection == NULL) return;
+
+ if (!_connection->beginTransactionRO()) return;
+
+ DB::Statement statement = _connection->prepare("select id from object limit -1 offset 1");
+
+ DB::Result result = _connection->perform(statement);
+
+ if (result.isValid())
+ {
+ do {
+ long long objectId = result.getLongLong(1);
+ {
+ MutexLocker lock(_tokenMutex);
+ std::map<long long, OSObject*>::iterator it = _allObjects.find(objectId);
+ if (it == _allObjects.end())
+ {
+ DBObject *object = new DBObject(_connection, this, objectId);
+ _allObjects[objectId] = object;
+ objects.insert(object);
+ }
+ else
+ {
+ objects.insert(it->second);
+ }
+ }
+ } while (result.nextRow());
+ }
+
+ _connection->endTransactionRO();
+}
+
+// Create a new object
+OSObject *DBToken::createObject()
+{
+ if (_connection == NULL) return NULL;
+
+ DBObject *newObject = new DBObject(_connection, this);
+ if (newObject == NULL)
+ {
+ ERROR_MSG("Failed to create an object: out of memory");
+ return NULL;
+ }
+
+ if (!newObject->startTransaction(DBObject::ReadWrite))
+ {
+ delete newObject;
+ ERROR_MSG("Unable to start a transaction in token database at \"%s\"", _connection->dbpath().c_str());
+ return NULL;
+ }
+
+ if (!newObject->insert())
+ {
+ newObject->abortTransaction();
+ delete newObject;
+ ERROR_MSG("Unable to insert an object into token database at \"%s\"", _connection->dbpath().c_str());
+ return NULL;
+ }
+
+ if (!newObject->isValid())
+ {
+ newObject->abortTransaction();
+ delete newObject;
+ ERROR_MSG("Object that was inserted in not valid");
+ return NULL;
+ }
+
+ if (!newObject->commitTransaction())
+ {
+ newObject->abortTransaction();
+ delete newObject;
+ ERROR_MSG("Unable to commit a created object to token database at \"%s\"", _connection->dbpath().c_str());
+ return NULL;
+ }
+
+ // Now add the new object to the list of existing objects.
+ {
+ MutexLocker lock(_tokenMutex);
+ _allObjects[newObject->objectId()] = newObject;
+ }
+
+ return newObject;
+}
+
+bool DBToken::deleteObject(OSObject *object)
+{
+ if (_connection == NULL) return false;
+
+ if (object == NULL)
+ {
+ ERROR_MSG("Object passed in as a parameter is NULL");
+ return false;
+ }
+
+ if (!object->startTransaction(DBObject::ReadWrite))
+ {
+ ERROR_MSG("Unable to start a transaction for deleting an object in token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ if (!static_cast<DBObject *>(object)->remove())
+ {
+ ERROR_MSG("Error while deleting an existing object from the token database at \"%s\"", _connection->dbpath().c_str());
+ object->abortTransaction();
+ return false;
+ }
+
+ if (!object->commitTransaction())
+ {
+ ERROR_MSG("Error while committing the deletion of an existing object in token database at \"%s\"", _connection->dbpath().c_str());
+ object->abortTransaction();
+ return false;
+ }
+
+ return true;
+}
+
+// Checks if the token is consistent
+bool DBToken::isValid()
+{
+ return _connection != NULL && _connection->tableExists("object");
+}
+
+// Invalidate the token (for instance if it is deleted)
+void DBToken::invalidate()
+{
+}
+
+// Delete the token.
+bool DBToken::clearToken()
+{
+ if (_connection == NULL) return false;
+
+ std::string tokenDir = _connection->dbdir();
+ std::string tokenPath = _connection->dbpath();
+
+ if (!DBObject(_connection).dropTables())
+ {
+ ERROR_MSG("Failed to drop all tables in the token database at \"%s\"", tokenPath.c_str());
+ return false;
+ }
+
+ _connection->close();
+ delete _connection;
+ _connection = NULL;
+
+ // Remove all files from the token directory, even ones not placed there by us.
+ Directory dir(tokenDir);
+ std::vector<std::string> tokenFiles = dir.getFiles();
+
+ for (std::vector<std::string>::iterator i = tokenFiles.begin(); i != tokenFiles.end(); i++)
+ {
+ if (!dir.remove(*i))
+ {
+ ERROR_MSG("Failed to remove \"%s\" from token directory \"%s\"", i->c_str(), tokenDir.c_str());
+
+ return false;
+ }
+ }
+
+ // Now remove the token directory
+ if (!dir.rmdir(""))
+ {
+ ERROR_MSG("Failed to remove the token directory \"%s\"", tokenDir.c_str());
+
+ return false;
+ }
+
+ DEBUG_MSG("Token instance %s was succesfully cleared", tokenDir.c_str());
+
+ return true;
+}
+
+// Reset the token
+bool DBToken::resetToken(const ByteString& label)
+{
+ if (_connection == NULL) return false;
+
+ std::string tokenDir = _connection->dbdir();
+
+ // Clean up
+ std::set<OSObject*> cleanUp = getObjects();
+
+ for (std::set<OSObject*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if (!deleteObject(*i))
+ {
+ ERROR_MSG("Unable to delete all objects in token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+ }
+
+ // Create a DBObject for the established connection to the token object in the database
+ DBObject tokenObject(_connection);
+
+ if (!tokenObject.startTransaction(DBObject::ReadWrite))
+ {
+ ERROR_MSG("Unable to start a transaction for setting the TOKENLABEL in token database at \"%s\"", _connection->dbpath().c_str());
+ return false;
+ }
+
+ // First find the token object in the database.
+ if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO))
+ {
+ ERROR_MSG("Token object not found in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (tokenObject.attributeExists(CKA_OS_USERPIN))
+ {
+ if (!tokenObject.deleteAttribute(CKA_OS_USERPIN))
+ {
+ ERROR_MSG("Error while deleting USERPIN in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+ }
+
+ if (!tokenObject.attributeExists(CKA_OS_TOKENFLAGS))
+ {
+ ERROR_MSG("Error while getting TOKENFLAGS from token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ // Retrieve flags from the database and reset flags related to tries and expiration of the SOPIN.
+ CK_ULONG flags = tokenObject.getAttribute(CKA_OS_TOKENFLAGS).getUnsignedLongValue()
+ & ~(CKF_USER_PIN_INITIALIZED | CKF_USER_PIN_COUNT_LOW | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_LOCKED | CKF_USER_PIN_TO_BE_CHANGED);
+
+ OSAttribute changedTokenFlags(flags);
+ if (!tokenObject.setAttribute(CKA_OS_TOKENFLAGS, changedTokenFlags))
+ {
+ ERROR_MSG("Error while setting TOKENFLAGS in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ OSAttribute tokenLabel(label);
+ if (!tokenObject.setAttribute(CKA_OS_TOKENLABEL, tokenLabel))
+ {
+ ERROR_MSG("Error while setting TOKENLABEL in token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ if (!tokenObject.commitTransaction())
+ {
+ ERROR_MSG("Error while committing TOKENLABEL changes to token database at \"%s\"", _connection->dbpath().c_str());
+ tokenObject.abortTransaction();
+ return false;
+ }
+
+ DEBUG_MSG("Token instance %s was succesfully reset", tokenDir.c_str());
+
+ return true;
+}
diff --git a/SoftHSMv2/src/lib/object_store/DBToken.h b/SoftHSMv2/src/lib/object_store/DBToken.h
new file mode 100644
index 0000000..ef4c28e
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/DBToken.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBToken.h
+
+ The token class; a token is stored in a directory containing a single
+ database file.
+ Each object is stored in multiple tables with every attribute base type
+ stored in a different table.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBTOKEN_H
+#define _SOFTHSM_V2_DBTOKEN_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "MutexFactory.h"
+#include "OSAttribute.h"
+#include "cryptoki.h"
+#include "OSObject.h"
+#include "ObjectStoreToken.h"
+
+#include <string>
+#include <set>
+
+namespace DB { class Connection; }
+
+class DBToken : public ObjectStoreToken
+{
+public:
+ // Constructor to create a new token
+ DBToken(const std::string &baseDir, const std::string &tokenName, const ByteString& label, const ByteString& serial);
+
+ // Constructor to access an existing token
+ DBToken(const std::string &baseDir, const std::string &tokenName);
+
+ // Create a new token
+ static DBToken* createToken(const std::string basePath, const std::string tokenDir, const ByteString& label, const ByteString& serial);
+
+ // Access an existing token
+ static DBToken* accessToken(const std::string &basePath, const std::string &tokenDir);
+
+ // Destructor
+ virtual ~DBToken();
+
+ // Set the SO PIN
+ virtual bool setSOPIN(const ByteString& soPINBlob);
+
+ // Get the SO PIN
+ virtual bool getSOPIN(ByteString& soPINBlob);
+
+ // Set the user PIN
+ virtual bool setUserPIN(ByteString userPINBlob);
+
+ // Get the user PIN
+ virtual bool getUserPIN(ByteString& userPINBlob);
+
+ // Get the token flags
+ virtual bool getTokenFlags(CK_ULONG& flags);
+
+ // Set the token flags
+ virtual bool setTokenFlags(const CK_ULONG flags);
+
+ // Retrieve the token label
+ virtual bool getTokenLabel(ByteString& label);
+
+ // Retrieve the token serial
+ virtual bool getTokenSerial(ByteString& serial);
+
+ // Retrieve objects
+ virtual std::set<OSObject*> getObjects();
+
+ // Insert objects into the given set
+ virtual void getObjects(std::set<OSObject*> &objects);
+
+ // Create a new object
+ virtual OSObject* createObject();
+
+ // Delete an object
+ virtual bool deleteObject(OSObject* object);
+
+ // Checks if the token is consistent
+ virtual bool isValid();
+
+ // Invalidate the token (for instance if it is deleted)
+ virtual void invalidate();
+
+ // Delete the token
+ virtual bool clearToken();
+
+ // Reset the token
+ virtual bool resetToken(const ByteString& label);
+
+private:
+ DB::Connection *_connection;
+
+ // All the objects ever associated with this token
+ //
+ // This map is kept to be able to clean up when the token
+ // instance is discarded; in case the contents of a token
+ // change, some objects may disappear but we cannot simply
+ // delete them since they may still be referenced from an
+ // object outside of this class.
+ std::map<long long, OSObject*> _allObjects;
+
+ // For thread safeness
+ Mutex* _tokenMutex;
+};
+
+#endif // !_SOFTHSM_V2_DBTOKEN_H
+
diff --git a/SoftHSMv2/src/lib/object_store/Directory.cpp b/SoftHSMv2/src/lib/object_store/Directory.cpp
new file mode 100644
index 0000000..e964d32
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/Directory.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Directory.cpp
+
+ Helper functions for accessing directories.
+ *****************************************************************************/
+
+#include "config.h"
+#include "Directory.h"
+#include "OSPathSep.h"
+#include "log.h"
+#include <string>
+#include <vector>
+#ifndef _WIN32
+#include <dirent.h>
+#include <unistd.h>
+#else
+#include <direct.h>
+#include <io.h>
+#endif
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// Constructor
+Directory::Directory(std::string inPath)
+{
+ path = inPath;
+ dirMutex = MutexFactory::i()->getMutex();
+
+ valid = (dirMutex != NULL) && refresh();
+}
+
+// Destructor
+Directory::~Directory()
+{
+ MutexFactory::i()->recycleMutex(dirMutex);
+}
+
+// Check if the directory is valid
+bool Directory::isValid()
+{
+ return valid;
+}
+
+// Return a list of all files in a directory
+std::vector<std::string> Directory::getFiles()
+{
+ // Make sure that no other thread is in the process of changing
+ // the file list when we return it
+ MutexLocker lock(dirMutex);
+
+ return files;
+}
+
+// Return a list of all subdirectories in a directory
+std::vector<std::string> Directory::getSubDirs()
+{
+ // Make sure that no other thread is in the process of changing
+ // the subdirectory list when we return it
+ MutexLocker lock(dirMutex);
+
+ return subDirs;
+}
+
+// Refresh the directory listing
+bool Directory::refresh()
+{
+ // Prevent concurrent call until valid is reset
+ MutexLocker lock(dirMutex);
+
+ // Reset the state
+ valid = false;
+
+ subDirs.clear();
+ files.clear();
+
+#ifndef _WIN32
+ // Enumerate the directory
+ DIR* dir = opendir(path.c_str());
+
+ if (dir == NULL)
+ {
+ DEBUG_MSG("Failed to open directory %s", path.c_str());
+
+ return false;
+ }
+
+ // Enumerate the directory
+ struct dirent* entry = NULL;
+
+ while ((entry = readdir(dir)) != NULL)
+ {
+ bool pushed = false;
+
+ // Check if this is the . or .. entry
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
+ {
+ continue;
+ }
+
+ // Convert the name of the entry to a C++ string
+ std::string name(entry->d_name);
+
+#if defined(_DIRENT_HAVE_D_TYPE) && defined(_BSD_SOURCE)
+ // Determine the type of the entry
+ switch(entry->d_type)
+ {
+ case DT_DIR:
+ // This is a directory
+ subDirs.push_back(name);
+ pushed = true;
+ break;
+ case DT_REG:
+ // This is a regular file
+ files.push_back(name);
+ pushed = true;
+ break;
+ default:
+ break;
+ }
+#endif
+ if (!pushed) {
+ // The entry type has to be determined using lstat
+ struct stat entryStatus;
+
+ std::string fullPath = path + OS_PATHSEP + name;
+
+ if (!lstat(fullPath.c_str(), &entryStatus))
+ {
+ if (S_ISDIR(entryStatus.st_mode))
+ {
+ subDirs.push_back(name);
+ }
+ else if (S_ISREG(entryStatus.st_mode))
+ {
+ files.push_back(name);
+ }
+ else
+ {
+ DEBUG_MSG("File not used %s", name.c_str());
+ }
+ }
+ }
+ }
+
+ // Close the directory
+ closedir(dir);
+
+#else
+ // Enumerate the directory
+ std::string pattern;
+ intptr_t h;
+ struct _finddata_t fi;
+
+ if ((path.back() == '/') || (path.back() == '\\'))
+ pattern = path + "*";
+ else
+ pattern = path + "/*";
+ memset(&fi, 0, sizeof(fi));
+ h = _findfirst(pattern.c_str(), &fi);
+ if (h == -1)
+ {
+ // empty directory
+ if (errno == ENOENT)
+ goto finished;
+
+ DEBUG_MSG("Failed to open directory %s", path.c_str());
+
+ return false;
+ }
+
+ // scan files & subdirs
+ do {
+ // Check if this is the . or .. entry
+ if (!strcmp(fi.name, ".") || !strcmp(fi.name, ".."))
+ continue;
+
+ if ((fi.attrib & _A_SUBDIR) == 0)
+ files.push_back(fi.name);
+ else
+ subDirs.push_back(fi.name);
+
+ memset(&fi, 0, sizeof(fi));
+ } while (_findnext(h, &fi) == 0);
+
+ (void) _findclose(h);
+
+ finished:
+#endif
+
+ valid = true;
+
+ return true;
+}
+
+// Create a new subdirectory
+bool Directory::mkdir(std::string name)
+{
+ std::string fullPath = path + OS_PATHSEP + name;
+
+#ifndef _WIN32
+ int rv = ::mkdir(fullPath.c_str(), S_IFDIR | S_IRWXU);
+#else
+ int rv = _mkdir(fullPath.c_str());
+#endif
+
+ if (rv != 0)
+ {
+ ERROR_MSG("Failed to create the directory (%s): %s", strerror(errno), fullPath.c_str());
+
+ return false;
+ }
+
+ return refresh();
+}
+
+// Delete a subdirectory in the directory
+bool Directory::rmdir(std::string name, bool doRefresh /* = false */)
+{
+ std::string fullPath;
+
+ if (name.empty())
+ fullPath = path;
+ else
+ fullPath = path + OS_PATHSEP + name;
+
+#ifndef _WIN32
+ if (::rmdir(fullPath.c_str()) != 0)
+ return false;
+#else
+ if (_rmdir(fullPath.c_str()) != 0)
+ return false;
+#endif
+ if (doRefresh)
+ return refresh();
+ return true;
+}
+
+// Delete a file in the directory
+bool Directory::remove(std::string name)
+{
+ std::string fullPath = path + OS_PATHSEP + name;
+
+#ifndef _WIN32
+ return (!::remove(fullPath.c_str()) && refresh());
+#else
+ return (!_unlink(fullPath.c_str()) && refresh());
+#endif
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/Directory.h b/SoftHSMv2/src/lib/object_store/Directory.h
new file mode 100644
index 0000000..d7681a1
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/Directory.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Directory.h
+
+ Helper functions for accessing directories.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DIRECTORY_H
+#define _SOFTHSM_V2_DIRECTORY_H
+
+#include "config.h"
+#include "MutexFactory.h"
+#include <string>
+#include <vector>
+
+class Directory
+{
+public:
+ // Constructor
+ Directory(std::string inPath);
+
+ // Destructor
+ virtual ~Directory();
+
+ // Check if the directory is valid
+ bool isValid();
+
+ // Return a list of all files in a directory
+ std::vector<std::string> getFiles();
+
+ // Return a list of all subdirectories in a directory
+ std::vector<std::string> getSubDirs();
+
+ // Refresh the directory listing
+ bool refresh();
+
+ // Create a new subdirectory
+ bool mkdir(std::string name);
+
+ // Delete a subdirectory in the directory
+ bool rmdir(std::string name, bool doRefresh = false);
+
+ // Delete a file in the directory
+ bool remove(std::string name);
+
+private:
+ // The directory path
+ std::string path;
+
+ // The status
+ bool valid;
+
+ // All files in the directory
+ std::vector<std::string> files;
+
+ // All subdirectories in the directory
+ std::vector<std::string> subDirs;
+
+ // For thread safeness
+ Mutex* dirMutex;
+};
+
+#endif // !_SOFTHSM_V2_DIRECTORY_H
+
diff --git a/SoftHSMv2/src/lib/object_store/File.cpp b/SoftHSMv2/src/lib/object_store/File.cpp
new file mode 100644
index 0000000..2af8ea9
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/File.cpp
@@ -0,0 +1,765 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this vector of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this vector of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ File.h
+
+ This class wraps standard C file I/O in a convenient way for the object store
+ *****************************************************************************/
+
+#include "config.h"
+#include "File.h"
+#include "log.h"
+#include <string>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32
+#include <sys/file.h>
+#include <unistd.h>
+#else
+#include <io.h>
+#define F_SETLK 12
+#define F_SETLKW 13
+#define F_RDLCK 1
+#define F_UNLCK 2
+#define F_WRLCK 3
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+enum AttributeKind {
+ akUnknown,
+ akBoolean,
+ akInteger,
+ akBinary,
+ akAttrMap,
+ akMechSet
+};
+
+// Constructor
+//
+// N.B.: the create flag only has a function when a file is opened read/write
+// N.B.: the truncate flag only has a function when the create one is true
+File::File(std::string inPath, bool forRead /* = true */, bool forWrite /* = false */, bool create /* = false */, bool truncate /* = true */)
+{
+ stream = NULL;
+
+ isReadable = forRead;
+ isWritable = forWrite;
+ locked = false;
+
+ path = inPath;
+ valid = false;
+
+ if (forRead || forWrite)
+ {
+ std::string fileMode = "";
+ int flags, fd;
+
+#ifndef _WIN32
+ flags = 0;
+ if (forRead && !forWrite) flags |= O_RDONLY;
+ if (!forRead && forWrite) flags |= O_WRONLY | O_CREAT | O_TRUNC;
+ if (forRead && forWrite) flags |= O_RDWR;
+ if (forRead && forWrite && create) flags |= O_CREAT;
+ if (forRead && forWrite && create && truncate) flags |= O_TRUNC;
+ // Open the file
+ fd = open(path.c_str(), flags, 0600);
+ if (fd == -1)
+ {
+ ERROR_MSG("Could not open the file (%s): %s", strerror(errno), path.c_str());
+ valid = false;
+ return;
+ }
+
+ if (forRead && !forWrite) fileMode = "r";
+ if (!forRead && forWrite) fileMode = "w";
+ if (forRead && forWrite && !create) fileMode = "r+";
+ if (forRead && forWrite && create) fileMode = "w+";
+ // Open the stream
+ valid = ((stream = fdopen(fd, fileMode.c_str())) != NULL);
+#else
+ flags = _O_BINARY;
+ if (forRead && !forWrite) flags |= _O_RDONLY;
+ if (!forRead && forWrite) flags |= _O_WRONLY | _O_CREAT | _O_TRUNC;
+ if (forRead && forWrite) flags |= _O_RDWR;
+ if (forRead && forWrite && create) flags |= _O_CREAT;
+ if (forRead && forWrite && create && truncate) flags |= _O_TRUNC;
+ // Open the file
+ fd = _open(path.c_str(), flags, _S_IREAD | _S_IWRITE);
+ if (fd == -1)
+ {
+ ERROR_MSG("Could not open the file (%s): %s", strerror(errno), path.c_str());
+ valid = false;
+ return;
+ }
+
+ if (forRead && !forWrite) fileMode = "rb";
+ if (!forRead && forWrite) fileMode = "wb";
+ if (forRead && forWrite && !create) fileMode = "rb+";
+ if (forRead && forWrite && create) fileMode = "wb+";
+ // Open the stream
+ valid = ((stream = _fdopen(fd, fileMode.c_str())) != NULL);
+#endif
+ }
+}
+
+// Destructor
+File::~File()
+{
+ if (locked)
+ {
+ unlock();
+ }
+
+ if (stream != NULL)
+ {
+ fclose(stream);
+ }
+}
+
+// Check if the file is valid
+bool File::isValid()
+{
+ return valid;
+}
+
+// Check if the file is readable
+bool File::isRead()
+{
+ return isReadable;
+}
+
+// Check if the file is writable
+bool File::isWrite()
+{
+ return isWritable;
+}
+
+// Check if the file is empty
+bool File::isEmpty()
+{
+#ifndef _WIN32
+ struct stat s;
+
+ if (fstat(fileno(stream), &s) != 0)
+ {
+ valid = false;
+
+ return false;
+ }
+
+ return (s.st_size == 0);
+#else
+ struct _stat s;
+
+ if (_fstat(_fileno(stream), &s) != 0)
+ {
+ valid = false;
+
+ return false;
+ }
+
+ return (s.st_size == 0);
+#endif
+}
+
+// Check if the end-of-file was reached
+bool File::isEOF()
+{
+ return valid && feof(stream);
+}
+
+// Read an unsigned long value; warning: not thread safe without locking!
+bool File::readULong(unsigned long& value)
+{
+ if (!valid) return false;
+
+ ByteString ulongVal;
+
+ ulongVal.resize(8);
+
+ if (fread(&ulongVal[0], 1, 8, stream) != 8)
+ {
+ return false;
+ }
+
+ value = ulongVal.long_val();
+
+ return true;
+}
+
+// Read a ByteString value; warning: not thread safe without locking!
+bool File::readByteString(ByteString& value)
+{
+ if (!valid) return false;
+
+ // Retrieve the length to read from the file
+ unsigned long len;
+
+ if (!readULong(len))
+ {
+ return false;
+ }
+
+ // Read the byte string from the file
+ value.resize(len);
+
+ if (len == 0)
+ {
+ return true;
+ }
+
+ if (fread(&value[0], 1, len, stream) != len)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Read a boolean value; warning: not thread safe without locking!
+bool File::readBool(bool& value)
+{
+ if (!valid) return false;
+
+ // Read the boolean from the file
+ unsigned char boolValue;
+
+ if (fread(&boolValue, 1, 1, stream) != 1)
+ {
+ return false;
+ }
+
+ value = boolValue ? true : false;
+
+ return true;
+}
+
+// Read a mechanism type set value; warning: not thread safe without locking!
+bool File::readMechanismTypeSet(std::set<CK_MECHANISM_TYPE>& value)
+{
+ if (!valid) return false;
+
+ unsigned long count;
+ if (!readULong(count)) return false;
+
+ for (unsigned long i = 0; i < count; i++)
+ {
+ unsigned long mechType;
+ if (!readULong(mechType))
+ {
+ return false;
+ }
+
+ value.insert((CK_MECHANISM_TYPE) mechType);
+ }
+
+ return true;
+}
+
+// Read an attribute map value; warning: not thread safe without locking!
+bool File::readAttributeMap(std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& value)
+{
+ if (!valid) return false;
+
+ // Retrieve the length to read from the file
+ unsigned long len;
+
+ if (!readULong(len))
+ {
+ return false;
+ }
+
+ while (len != 0)
+ {
+ unsigned long attrType;
+ if (!readULong(attrType))
+ {
+ return false;
+ }
+ if (8 > len)
+ {
+ return false;
+ }
+ len -= 8;
+
+ unsigned long attrKind;
+ if (!readULong(attrKind))
+ {
+ return false;
+ }
+ if (8 > len)
+ {
+ return false;
+ }
+ len -= 8;
+
+ switch (attrKind)
+ {
+ case akBoolean:
+ {
+ bool val;
+ if (!readBool(val))
+ {
+ return false;
+ }
+ if (1 > len)
+ {
+ return false;
+ }
+ len -= 1;
+
+ value.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, val));
+ }
+ break;
+
+ case akInteger:
+ {
+ unsigned long val;
+ if (!readULong(val))
+ {
+ return false;
+ }
+ if (8 > len)
+ {
+ return false;
+ }
+ len -= 8;
+
+ value.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, val));
+ }
+ break;
+
+ case akBinary:
+ {
+ ByteString val;
+ if (!readByteString(val))
+ {
+ return false;
+ }
+ if (8 + val.size() > len)
+ {
+ return false;
+ }
+ len -= 8 + val.size();
+
+ value.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, val));
+ }
+ break;
+
+ case akMechSet:
+ {
+ std::set<CK_MECHANISM_TYPE> val;
+ if (!readMechanismTypeSet(val))
+ {
+ return false;
+ }
+ if (8 + val.size() * 8 > len)
+ {
+ return false;
+ }
+ len -= 8 + val.size() * 8;
+
+ value.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (attrType, val));
+ }
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Read a string value; warning: not thread safe without locking!
+bool File::readString(std::string& value)
+{
+ if (!valid) return false;
+
+ // Retrieve the length to read from the file
+ unsigned long len;
+
+ if (!readULong(len))
+ {
+ return false;
+ }
+
+ // Read the string from the file
+ value.resize(len);
+
+ if (fread(&value[0], 1, len, stream) != len)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write an unsigned long value; warning: not thread safe without locking!
+bool File::writeULong(const unsigned long value)
+{
+ if (!valid) return false;
+
+ ByteString toWrite(value);
+
+ // Write the value to the file
+ if (fwrite(toWrite.const_byte_str(), 1, toWrite.size(), stream) != toWrite.size())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write a ByteString value; warning: not thread safe without locking!
+bool File::writeByteString(const ByteString& value)
+{
+ if (!valid) return false;
+
+ ByteString toWrite = value.serialise();
+
+ // Write the value to the file
+ if (fwrite(toWrite.const_byte_str(), 1, toWrite.size(), stream) != toWrite.size())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write a string value; warning: not thread safe without locking!
+bool File::writeString(const std::string& value)
+{
+ if (!valid) return false;
+
+ ByteString toWrite((const unsigned long) value.size());
+
+ // Write the value to the file
+ if ((fwrite(toWrite.const_byte_str(), 1, toWrite.size(), stream) != toWrite.size()) ||
+ (fwrite(&value[0], 1, value.size(), stream) != value.size()))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Write a mechanism type set value; warning: not thread safe without locking!
+bool File::writeMechanismTypeSet(const std::set<CK_MECHANISM_TYPE>& value)
+{
+ if (!valid) return false;
+
+ // write length
+ if (!writeULong(value.size()))
+ {
+ return false;
+ }
+
+ // write each value
+ for (std::set<CK_MECHANISM_TYPE>::const_iterator i = value.begin(); i != value.end(); ++i)
+ {
+ if (!writeULong(*i)) return false;
+ }
+
+ return true;
+}
+
+// Write an attribute map value; warning: not thread safe without locking!
+bool File::writeAttributeMap(const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& value)
+{
+ if (!valid) return false;
+
+ // compute length
+ unsigned long len = 0;
+ for (std::map<CK_ATTRIBUTE_TYPE,OSAttribute>::const_iterator i = value.begin(); i != value.end(); ++i)
+ {
+ OSAttribute attr = i->second;
+ // count attribute type and kind
+ len += 8 + 8;
+
+ if (attr.isBooleanAttribute())
+ {
+ len += 1;
+ }
+ else if (attr.isUnsignedLongAttribute())
+ {
+ len += 8;
+ }
+ else if (attr.isByteStringAttribute())
+ {
+ ByteString val = attr.getByteStringValue();
+ len += 8 + val.size();
+ }
+ else if (attr.isMechanismTypeSetAttribute())
+ {
+ std::set<CK_MECHANISM_TYPE> val = attr.getMechanismTypeSetValue();
+ len += 8 + val.size() * 8;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // write length
+ if (!writeULong(len))
+ {
+ return false;
+ }
+
+ // write each attribute
+ for (std::map<CK_ATTRIBUTE_TYPE,OSAttribute>::const_iterator i = value.begin(); i != value.end(); ++i)
+ {
+ OSAttribute attr = i->second;
+ unsigned long attrType = (unsigned long) i->first;
+ if (!writeULong(attrType))
+ {
+ return false;
+ }
+
+ if (attr.isBooleanAttribute())
+ {
+ unsigned long attrKind = akBoolean;
+ if (!writeULong(attrKind))
+ {
+ return false;
+ }
+
+ bool val = attr.getBooleanValue();
+ if (!writeBool(val))
+ {
+ return false;
+ }
+ }
+ else if (attr.isUnsignedLongAttribute())
+ {
+ unsigned long attrKind = akInteger;
+ if (!writeULong(attrKind))
+ {
+ return false;
+ }
+
+ unsigned long val = attr.getUnsignedLongValue();
+ if (!writeULong(val))
+ {
+ return false;
+ }
+ }
+ else if (attr.isByteStringAttribute())
+ {
+ unsigned long attrKind = akBinary;
+ if (!writeULong(attrKind))
+ {
+ return false;
+ }
+
+ ByteString val = attr.getByteStringValue();
+ if (!writeByteString(val))
+ {
+ return false;
+ }
+ }
+ else if (attr.isMechanismTypeSetAttribute())
+ {
+ unsigned long attrKind = akMechSet;
+ if (!writeULong(attrKind))
+ {
+ return false;
+ }
+
+ std::set<CK_MECHANISM_TYPE> val = attr.getMechanismTypeSetValue();
+ if (!writeMechanismTypeSet(val))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// Write a boolean value; warning: not thread safe without locking!
+bool File::writeBool(const bool value)
+{
+ if (!valid) return false;
+
+ unsigned char toWrite = value ? 0xFF : 0x00;
+
+ // Write the value to the file
+ if (fwrite(&toWrite, 1, 1, stream) != 1)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Rewind the file
+bool File::rewind()
+{
+ if (!valid) return false;
+
+ ::rewind(stream);
+
+ return true;
+}
+
+// Truncate the file
+bool File::truncate()
+{
+ if (!valid) return false;
+
+#ifndef _WIN32
+ return (::ftruncate(fileno(stream), 0) == 0);
+#else
+ return (_chsize(_fileno(stream), 0) == 0);
+#endif
+}
+
+// Seek to the specified position relative to the start of the file; if no
+// argument is specified this operation seeks to the end of the file
+bool File::seek(long offset /* = -1 */)
+{
+ if (offset == -1)
+ {
+ return valid && (valid = !fseek(stream, 0, SEEK_END));
+ }
+ else
+ {
+ return valid && (valid = !fseek(stream, offset, SEEK_SET));
+ }
+}
+
+// Lock the file
+bool File::lock(bool block /* = true */)
+{
+#ifndef _WIN32
+ struct flock fl;
+ fl.l_type = isWrite() ? F_WRLCK : F_RDLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_pid = 0;
+
+ if (locked || !valid) return false;
+
+ if (fcntl(fileno(stream), block ? F_SETLKW : F_SETLK, &fl) != 0)
+ {
+ ERROR_MSG("Could not lock the file: %s", strerror(errno));
+ return false;
+ }
+#else
+ HANDLE hFile;
+ DWORD flags = 0;
+ OVERLAPPED o;
+
+ if (isWrite()) flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ if (!block) flags |= LOCKFILE_FAIL_IMMEDIATELY;
+
+ if (locked || !valid) return false;
+
+ hFile = (HANDLE) _get_osfhandle(_fileno(stream));
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ ERROR_MSG("Invalid handle");
+ return false;
+ }
+
+ memset(&o, 0, sizeof(o));
+ if (!LockFileEx(hFile, flags, 0, 1, 0, &o))
+ {
+ DWORD rv = GetLastError();
+
+ ERROR_MSG("Could not lock the file: 0x%08x", rv);
+ return false;
+ }
+#endif
+
+ locked = true;
+
+ return true;
+}
+
+// Unlock the file
+bool File::unlock()
+{
+#ifndef _WIN32
+ struct flock fl;
+ fl.l_type = F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ fl.l_pid = 0;
+
+ if (!locked || !valid) return false;
+
+ if (fcntl(fileno(stream), F_SETLK, &fl) != 0)
+ {
+ valid = false;
+
+ ERROR_MSG("Could not unlock the file: %s", strerror(errno));
+ return false;
+ }
+#else
+ HANDLE hFile;
+ OVERLAPPED o;
+
+ if (!locked || !valid) return false;
+
+ hFile = (HANDLE) _get_osfhandle(_fileno(stream));
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ ERROR_MSG("Invalid handle");
+ return false;
+ }
+
+ memset(&o, 0, sizeof(o));
+ if (!UnlockFileEx(hFile, 0, 1, 0, &o))
+ {
+ DWORD rv = GetLastError();
+
+ valid = false;
+
+ ERROR_MSG("Could not unlock the file: 0x%08x", rv);
+ return false;
+ }
+#endif
+
+
+ locked = false;
+
+ return valid;
+}
+
+// Flush the buffered stream to background storage
+bool File::flush()
+{
+ return valid && !fflush(stream);
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/File.h b/SoftHSMv2/src/lib/object_store/File.h
new file mode 100644
index 0000000..da27af6
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/File.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ File.h
+
+ This class wraps standard C file I/O in a convenient way for the object store
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FILE_H
+#define _SOFTHSM_V2_FILE_H
+
+#include "config.h"
+#include "OSAttribute.h"
+#include <stdio.h>
+#include <string>
+
+class File
+{
+public:
+ // Constructor
+ File(std::string inPath, bool forRead = true, bool forWrite = false, bool create = false, bool truncate = true);
+
+ // Destructor
+ virtual ~File();
+
+ // Check if the file is valid
+ bool isValid();
+
+ // Check if the file is readable
+ bool isRead();
+
+ // Check if the file is writable
+ bool isWrite();
+
+ // Check if the file is empty
+ bool isEmpty();
+
+ // Check if the end-of-file was reached
+ bool isEOF();
+
+ // Read an unsigned long value; warning: not thread safe without locking!
+ bool readULong(unsigned long& value);
+
+ // Read a ByteString value; warning: not thread safe without locking!
+ bool readByteString(ByteString& value);
+
+ // Read a string value; warning: not thread safe without locking!
+ bool readString(std::string& value);
+
+ // Read a boolean value; warning: not thread safe without locking!
+ bool readBool(bool& value);
+
+ // Read a mechanism type set value; warning: not thread safe without locking!
+ bool readMechanismTypeSet(std::set<CK_MECHANISM_TYPE>& value);
+
+ // Read an array value; warning: not thread safe without locking!
+ bool readAttributeMap(std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& value);
+
+ // Write an unsigned long value; warning: not thread safe without locking!
+ bool writeULong(const unsigned long value);
+
+ // Write a ByteString value; warning: not thread safe without locking!
+ bool writeByteString(const ByteString& value);
+
+ // Write a string value; warning: not thread safe without locking!
+ bool writeString(const std::string& value);
+
+ // Write a boolean value; warning: not thread safe without locking!
+ bool writeBool(const bool value);
+
+ // Write a mechanism type set value; warning: not thread safe without locking!
+ bool writeMechanismTypeSet(const std::set<CK_MECHANISM_TYPE>& value);
+
+ // Write an attribute map value; warning: not thread safe without locking!
+ bool writeAttributeMap(const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& value);
+
+ // Rewind the file
+ bool rewind();
+
+ // Truncate the file
+ bool truncate();
+
+ // Seek to the specified position relative to the start of the file; if no
+ // argument is specified this operation seeks to the end of the file
+ bool seek(long offset = -1);
+
+ // Lock the file
+ bool lock(bool block = true);
+
+ // Unlock the file
+ bool unlock();
+
+ // Flush the buffered stream to background storage
+ bool flush();
+
+private:
+ // The file path
+ std::string path;
+
+ // The status
+ bool valid;
+ bool locked;
+
+ // Read, write or both?
+ bool isReadable, isWritable;
+
+ // The FILE stream
+ FILE* stream;
+};
+
+#endif // !_SOFTHSM_V2_FILE_H
+
diff --git a/SoftHSMv2/src/lib/object_store/FindOperation.cpp b/SoftHSMv2/src/lib/object_store/FindOperation.cpp
new file mode 100644
index 0000000..db6dda1
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/FindOperation.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FindOperation.cpp
+
+ This class represents the find operation that can be used to collect
+ objects that match the attributes contained in a given template.
+ *****************************************************************************/
+
+#include "config.h"
+#include "FindOperation.h"
+
+FindOperation::FindOperation()
+{
+}
+
+FindOperation *FindOperation::create()
+{
+ return new FindOperation();
+}
+
+void FindOperation::recycle()
+{
+ delete this;
+}
+
+void FindOperation::setHandles(const std::set<CK_OBJECT_HANDLE> &handles)
+{
+ _handles = handles;
+}
+
+CK_ULONG FindOperation::retrieveHandles(CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulCount)
+{
+ CK_ULONG ulReturn = 0;
+ std::set<CK_OBJECT_HANDLE>::const_iterator it;
+ for (it=_handles.begin(); it != _handles.end(); ++it) {
+ if (ulReturn >= ulCount) break;
+
+ phObject[ulReturn++] = *it;
+ }
+ return ulReturn;
+}
+
+CK_ULONG FindOperation::eraseHandles(CK_ULONG ulIndex, CK_ULONG ulCount)
+{
+ std::set<CK_OBJECT_HANDLE>::const_iterator it;
+ for (it=_handles.begin(); it != _handles.end() && ulIndex != 0; --ulIndex) {
+ ++it;
+ }
+
+ CK_ULONG ulReturn = 0;
+ for ( ; it != _handles.end() && ulReturn < ulCount; ++ulReturn) {
+ _handles.erase(it++);
+ }
+ return ulReturn;
+}
diff --git a/SoftHSMv2/src/lib/object_store/FindOperation.h b/SoftHSMv2/src/lib/object_store/FindOperation.h
new file mode 100644
index 0000000..ea6410a
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/FindOperation.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FindOperation.h
+
+ This class represents the find operation that can be used to collect
+ objects that match the attributes contained in a given template.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FINDOPERATION_H
+#define _SOFTHSM_V2_FINDOPERATION_H
+
+#include "config.h"
+
+#include <set>
+#include "OSObject.h"
+
+class FindOperation
+{
+public:
+ // Factory method creates a new find operation
+ static FindOperation* create();
+
+ // Hand this operation back to the factory for recycling.
+ void recycle();
+
+ // Add the objects from thet set that match the attributes in the given template to the find operation.
+ void setHandles(const std::set<CK_OBJECT_HANDLE> &handles);
+
+ // Retrieve handles
+ CK_ULONG retrieveHandles(CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulCount);
+
+ // Erase handles from the handles set.
+ CK_ULONG eraseHandles(CK_ULONG ulIndex, CK_ULONG ulCount);
+
+protected:
+ // Use a protected constructor to force creation via factory method.
+ FindOperation();
+
+ std::set<CK_OBJECT_HANDLE> _handles;
+};
+
+#endif // _SOFTHSM_V2_FINDOPERATION_H
diff --git a/SoftHSMv2/src/lib/object_store/Generation.cpp b/SoftHSMv2/src/lib/object_store/Generation.cpp
new file mode 100644
index 0000000..196dac2
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/Generation.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Generation.cpp
+
+ Helper for generation number handling.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "Generation.h"
+
+// Factory
+Generation* Generation::create(const std::string path, bool isToken /* = false */)
+{
+ Generation* gen = new Generation(path, isToken);
+ if ((gen != NULL) && isToken && (gen->genMutex == NULL))
+ {
+ delete gen;
+
+ return NULL;
+ }
+ return gen;
+}
+
+// Destructor
+Generation::~Generation()
+{
+ if (isToken)
+ {
+ MutexFactory::i()->recycleMutex(genMutex);
+ }
+}
+
+// Synchronize from locked disk file
+bool Generation::sync(File &objectFile)
+{
+ if (isToken)
+ {
+ ERROR_MSG("Generation sync() called for a token");
+
+ return false;
+ }
+
+ unsigned long onDisk;
+
+ if (!objectFile.readULong(onDisk))
+ {
+ if (objectFile.isEOF())
+ {
+ onDisk = 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ currentValue = onDisk;
+
+ return objectFile.seek(0L);
+}
+
+// Check if the target was updated
+bool Generation::wasUpdated()
+{
+ if (isToken)
+ {
+ MutexLocker lock(genMutex);
+
+ File genFile(path);
+
+ if (!genFile.isValid())
+ {
+ return true;
+ }
+
+ genFile.lock();
+
+ unsigned long onDisk;
+
+ if (!genFile.readULong(onDisk))
+ {
+ return true;
+ }
+
+ if (onDisk != currentValue)
+ {
+ currentValue = onDisk;
+ return true;
+ }
+
+ return false;
+ }
+ else
+ {
+ File objectFile(path);
+
+ if (!objectFile.isValid())
+ {
+ return true;
+ }
+
+ objectFile.lock();
+
+ unsigned long onDisk;
+
+ if (!objectFile.readULong(onDisk))
+ {
+ return true;
+ }
+
+ return (onDisk != currentValue);
+ }
+}
+
+// Update
+void Generation::update()
+{
+ pendingUpdate = true;
+}
+
+// Commit
+void Generation::commit()
+{
+ if (isToken)
+ {
+ MutexLocker lock(genMutex);
+
+ File genFile(path, true, true, true, false);
+
+ if (!genFile.isValid())
+ {
+ return;
+ }
+
+ genFile.lock();
+
+ if (genFile.isEmpty())
+ {
+ currentValue++;
+
+ if (currentValue == 0)
+ {
+ currentValue++;
+ }
+
+ pendingUpdate = false;
+
+ (void) genFile.writeULong(currentValue);
+
+ genFile.unlock();
+
+ return;
+ }
+
+ unsigned long onDisk;
+
+ bool bOK = true;
+
+ bOK = bOK && genFile.readULong(onDisk);
+ bOK = bOK && genFile.seek(0L);
+
+ if (pendingUpdate)
+ {
+ onDisk++;
+
+ if (onDisk == 0)
+ {
+ onDisk++;
+ }
+ }
+
+ bOK = bOK && genFile.writeULong(onDisk);
+
+ if (bOK)
+ {
+ currentValue = onDisk;
+
+ pendingUpdate = false;
+ }
+
+ genFile.unlock();
+ }
+}
+
+// Set the current value when read from disk
+void Generation::set(unsigned long onDisk)
+{
+ currentValue = onDisk;
+}
+
+// Return new value
+unsigned long Generation::get()
+{
+ pendingUpdate = false;
+
+ currentValue++;
+
+ if (currentValue == 0)
+ {
+ currentValue = 1;
+ }
+
+ return currentValue;
+}
+
+// Rollback (called when the new value failed to be written)
+void Generation::rollback()
+{
+ pendingUpdate = true;
+
+ if (currentValue != 1)
+ {
+ currentValue--;
+ }
+}
+
+// Constructor
+Generation::Generation(const std::string inPath, bool inIsToken)
+{
+ path = inPath;
+ isToken = inIsToken;
+ pendingUpdate = false;
+ currentValue = 0;
+ genMutex = NULL;
+
+ if (isToken)
+ {
+ genMutex = MutexFactory::i()->getMutex();
+
+ if (genMutex != NULL)
+ {
+ commit();
+ }
+ }
+}
diff --git a/SoftHSMv2/src/lib/object_store/Generation.h b/SoftHSMv2/src/lib/object_store/Generation.h
new file mode 100644
index 0000000..106f34b
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/Generation.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Generation.h
+
+ Helper for generation number handling.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_GENERATION_H
+#define _SOFTHSM_V2_GENERATION_H
+
+#include "config.h"
+#include <string>
+#include "File.h"
+#include "MutexFactory.h"
+
+class Generation
+{
+public:
+ // Factory
+ static Generation* create(const std::string inPath, bool inIsToken = false);
+
+ // Destructor
+ virtual ~Generation();
+
+ // Synchronize from locked disk file
+ bool sync(File &objectfile);
+
+ // Check if the target was updated
+ bool wasUpdated();
+
+ // Note pending update
+ void update();
+
+ // Commit (for the token case)
+ void commit();
+
+ // Set the current value when read from disk
+ void set(unsigned long onDisk);
+
+ // Return new value
+ unsigned long get();
+
+ // Rollback (called when the new value failed to be written)
+ void rollback();
+
+private:
+ // Constructor
+ Generation(const std::string path, bool isToken);
+
+ // The file path
+ std::string path;
+
+ // isToken
+ bool isToken;
+
+ // Pending update
+ bool pendingUpdate;
+
+ // Current value
+ unsigned long currentValue;
+
+ // For thread safeness
+ Mutex* genMutex;
+};
+
+#endif // !_SOFTHSM_V2_GENERATION_H
+
diff --git a/SoftHSMv2/src/lib/object_store/Makefile.am b/SoftHSMv2/src/lib/object_store/Makefile.am
new file mode 100644
index 0000000..d3e89d3
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/Makefile.am
@@ -0,0 +1,34 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../pkcs11 \
+ @SQLITE3_INCLUDES@
+
+noinst_LTLIBRARIES = libsofthsm_objectstore.la
+libsofthsm_objectstore_la_SOURCES = ObjectStore.cpp \
+ UUID.cpp \
+ Directory.cpp \
+ File.cpp \
+ Generation.cpp \
+ OSAttribute.cpp \
+ OSToken.cpp \
+ ObjectFile.cpp \
+ SessionObject.cpp \
+ SessionObjectStore.cpp \
+ FindOperation.cpp \
+ ObjectStoreToken.cpp
+
+if BUILD_OBJECTSTORE_BACKEND_DB
+libsofthsm_objectstore_la_SOURCES += DB.cpp \
+ DBObject.cpp \
+ DBToken.cpp
+endif
+
+libsofthsm_objectstore_la_LDFLAGS = @SQLITE3_LIBS@
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/object_store/OSAttribute.cpp b/SoftHSMv2/src/lib/object_store/OSAttribute.cpp
new file mode 100644
index 0000000..9d7e5a3
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/OSAttribute.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSAttribute.cpp
+
+ This class represents the object store view on an object's attribute
+ *****************************************************************************/
+
+#include "config.h"
+#include "OSAttribute.h"
+
+// Copy constructor
+OSAttribute::OSAttribute(const OSAttribute& in)
+{
+ attributeType = in.attributeType;
+ boolValue = in.boolValue;
+ ulongValue = in.ulongValue;
+ byteStrValue = in.byteStrValue;
+ mechSetValue = in.mechSetValue;
+ attrMapValue = in.attrMapValue;
+}
+
+// Constructor for a boolean type attribute
+OSAttribute::OSAttribute(const bool value)
+{
+ boolValue = value;
+ attributeType = BOOL;
+
+ ulongValue = 0;
+}
+
+// Constructor for an unsigned long type attribute
+OSAttribute::OSAttribute(const unsigned long value)
+{
+ ulongValue = value;
+ attributeType = ULONG;
+
+ boolValue = false;
+}
+
+// Constructor for a byte string type attribute
+OSAttribute::OSAttribute(const ByteString& value)
+{
+ byteStrValue = value;
+ attributeType = BYTESTR;
+
+ boolValue = false;
+ ulongValue = 0;
+}
+
+// Constructor for a mechanism type set attribute
+OSAttribute::OSAttribute(const std::set<CK_MECHANISM_TYPE>& value)
+{
+ mechSetValue = value;
+ attributeType = MECHSET;
+
+ boolValue = false;
+ ulongValue = 0;
+}
+
+// Constructor for an attribute map type attribute
+OSAttribute::OSAttribute(const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& value)
+{
+ attrMapValue = value;
+ attributeType = ATTRMAP;
+
+ boolValue = false;
+ ulongValue = 0;
+}
+
+// Check the attribute type
+bool OSAttribute::isBooleanAttribute() const
+{
+ return (attributeType == BOOL);
+}
+
+bool OSAttribute::isUnsignedLongAttribute() const
+{
+ return (attributeType == ULONG);
+}
+
+bool OSAttribute::isByteStringAttribute() const
+{
+ return (attributeType == BYTESTR);
+}
+
+bool OSAttribute::isMechanismTypeSetAttribute() const
+{
+ return (attributeType == MECHSET);
+}
+
+bool OSAttribute::isAttributeMapAttribute() const
+{
+ return (attributeType == ATTRMAP);
+}
+
+// Retrieve the attribute value
+bool OSAttribute::getBooleanValue() const
+{
+ return boolValue;
+}
+
+unsigned long OSAttribute::getUnsignedLongValue() const
+{
+ return ulongValue;
+}
+
+const ByteString& OSAttribute::getByteStringValue() const
+{
+ return byteStrValue;
+}
+
+const std::set<CK_MECHANISM_TYPE>& OSAttribute::getMechanismTypeSetValue() const
+{
+ return mechSetValue;
+}
+
+const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& OSAttribute::getAttributeMapValue() const
+{
+ return attrMapValue;
+}
+
+// Helper for template (aka array) matching
+
+bool OSAttribute::peekValue(ByteString& value) const
+{
+ size_t counter = 0;
+ CK_MECHANISM_TYPE mech;
+
+ switch (attributeType)
+ {
+ case BOOL:
+ value.resize(sizeof(boolValue));
+ memcpy(&value[0], &boolValue, value.size());
+ return true;
+
+ case ULONG:
+ value.resize(sizeof(ulongValue));
+ memcpy(&value[0], &ulongValue, value.size());
+ return true;
+
+ case BYTESTR:
+ value.resize(byteStrValue.size());
+ memcpy(&value[0], byteStrValue.const_byte_str(), value.size());
+ return true;
+
+ case MECHSET:
+ value.resize(mechSetValue.size() * sizeof(mech));
+ for (std::set<CK_MECHANISM_TYPE>::const_iterator i = mechSetValue.begin(); i != mechSetValue.end(); ++i)
+ {
+ mech = *i;
+ memcpy(&value[0] + counter * sizeof(mech), &mech, sizeof(mech));
+ counter++;
+ }
+ return true;
+
+ case ATTRMAP:
+ return false;
+
+ default:
+ return false;
+ }
+}
diff --git a/SoftHSMv2/src/lib/object_store/OSAttribute.h b/SoftHSMv2/src/lib/object_store/OSAttribute.h
new file mode 100644
index 0000000..303a5b9
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/OSAttribute.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSAttribute.h
+
+ This class represents the object store view on an object's attribute
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSATTRIBUTE_H
+#define _SOFTHSM_V2_OSATTRIBUTE_H
+
+#include "config.h"
+#include "ByteString.h"
+#include <map>
+#include <set>
+
+class OSAttribute
+{
+public:
+ // Copy constructor
+ OSAttribute(const OSAttribute& in);
+
+ // Constructor for a boolean type attribute
+ OSAttribute(const bool value);
+
+ // Constructor for an unsigned long type attribute
+ OSAttribute(const unsigned long value);
+
+ // Constructor for a byte string type attribute
+ OSAttribute(const ByteString& value);
+
+ // Constructor for a mechanism type set type attribute
+ OSAttribute(const std::set<CK_MECHANISM_TYPE>& value);
+
+ // Constructor for an attribute map type attribute
+ OSAttribute(const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& value);
+
+ // Destructor
+ virtual ~OSAttribute() { }
+
+ // Check the attribute type
+ bool isBooleanAttribute() const;
+ bool isUnsignedLongAttribute() const;
+ bool isByteStringAttribute() const;
+ bool isMechanismTypeSetAttribute() const;
+ bool isAttributeMapAttribute() const;
+
+ // Retrieve the attribute value
+ bool getBooleanValue() const;
+ unsigned long getUnsignedLongValue() const;
+ const ByteString& getByteStringValue() const;
+ const std::set<CK_MECHANISM_TYPE>& getMechanismTypeSetValue() const;
+ const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& getAttributeMapValue() const;
+
+ // Helper for template (aka array) matching
+ bool peekValue(ByteString& value) const;
+
+private:
+ // The attribute type
+ enum
+ {
+ BOOL,
+ ULONG,
+ BYTESTR,
+ MECHSET,
+ ATTRMAP
+ }
+ attributeType;
+
+ // The attribute value
+ bool boolValue;
+ unsigned long ulongValue;
+ ByteString byteStrValue;
+ std::set<CK_MECHANISM_TYPE> mechSetValue;
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrMapValue;
+};
+
+#endif // !_SOFTHSM_V2_OSATTRIBUTE_H
+
diff --git a/SoftHSMv2/src/lib/object_store/OSAttributes.h b/SoftHSMv2/src/lib/object_store/OSAttributes.h
new file mode 100644
index 0000000..dfc5869
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/OSAttributes.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSAttributes.h
+
+ Specifies vendor defined attributes for use in internal object store files
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSATTRIBUTES_H
+#define _SOFTHSM_V2_OSATTRIBUTES_H
+
+#include "config.h"
+#include "cryptoki.h"
+
+// Define vendor tag; presumably the one below is reasonably unique
+#define CKA_VENDOR_SOFTHSM (CKA_VENDOR_DEFINED + 0x5348) // 'SH'
+
+// Vendor defined attribute types for the token file
+#define CKA_OS_TOKENLABEL (CKA_VENDOR_SOFTHSM + 1)
+#define CKA_OS_TOKENSERIAL (CKA_VENDOR_SOFTHSM + 2)
+#define CKA_OS_TOKENFLAGS (CKA_VENDOR_SOFTHSM + 3)
+#define CKA_OS_SOPIN (CKA_VENDOR_SOFTHSM + 4)
+#define CKA_OS_USERPIN (CKA_VENDOR_SOFTHSM + 5)
+
+#endif // !_SOFTHSM_V2_OSATTRIBUTES_H
+
diff --git a/SoftHSMv2/src/lib/object_store/OSObject.h b/SoftHSMv2/src/lib/object_store/OSObject.h
new file mode 100644
index 0000000..6efaa6d
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/OSObject.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSObject.h
+
+ This file contains the abstract interface for ObjectStore objects. It is
+ implemented by persistent objects in the form of the ObjectFile class and
+ by session objects in the form of the SessionObject class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSOBJECT_H
+#define _SOFTHSM_V2_OSOBJECT_H
+
+#include "config.h"
+#include "OSAttribute.h"
+#include "cryptoki.h"
+
+class OSObject
+{
+public:
+ // Destructor
+ virtual ~OSObject() { }
+
+ // Check if the specified attribute exists
+ virtual bool attributeExists(CK_ATTRIBUTE_TYPE type) = 0;
+
+ // Retrieve the specified attribute
+ virtual OSAttribute getAttribute(CK_ATTRIBUTE_TYPE type) = 0;
+ virtual bool getBooleanValue(CK_ATTRIBUTE_TYPE type, bool val) = 0;
+ virtual unsigned long getUnsignedLongValue(CK_ATTRIBUTE_TYPE type, unsigned long val) = 0;
+ virtual ByteString getByteStringValue(CK_ATTRIBUTE_TYPE type) = 0;
+
+ // Retrieve the next attribute type
+ virtual CK_ATTRIBUTE_TYPE nextAttributeType(CK_ATTRIBUTE_TYPE type) = 0;
+
+ // Set the specified attribute
+ virtual bool setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute) = 0;
+
+ // Delete the specified attribute
+ virtual bool deleteAttribute(CK_ATTRIBUTE_TYPE type) = 0;
+
+ // The validity state of the object
+ virtual bool isValid() = 0;
+
+ // Start an attribute set transaction; this method is used when - for
+ // example - a key is generated and all its attributes need to be
+ // persisted in one go.
+ //
+ // N.B.: Starting a transaction locks the object!
+ //
+ // Function returns false in case a transaction is already in progress
+ enum Access {
+ ReadOnly,
+ ReadWrite
+ };
+ virtual bool startTransaction(Access access = ReadWrite) = 0;
+
+ // Commit an attribute transaction; returns false if no transaction is in progress
+ virtual bool commitTransaction() = 0;
+
+ // Abort an attribute transaction; loads back the previous version of the object from disk;
+ // returns false if no transaction was in progress
+ virtual bool abortTransaction() = 0;
+
+ // Destroys the object (warning, any pointers to the object are no longer
+ // valid after this call because delete is called!)
+ virtual bool destroyObject() = 0;
+};
+
+#endif // !_SOFTHSM_V2_OSOBJECT_H
+
diff --git a/SoftHSMv2/src/lib/object_store/OSPathSep.h b/SoftHSMv2/src/lib/object_store/OSPathSep.h
new file mode 100644
index 0000000..f714d24
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/OSPathSep.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSPathSep.h
+
+ Determine the OS specific path separator
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSPATHSEP_H
+#define _SOFTHSM_V2_OSPATHSEP_H
+
+#include "config.h"
+
+#ifdef _WIN32
+#define OS_PATHSEP "\\"
+#else
+#define OS_PATHSEP "/"
+#endif
+
+#endif // !_SOFTHSM_V2_OSPATHSEP_H
+
diff --git a/SoftHSMv2/src/lib/object_store/OSToken.cpp b/SoftHSMv2/src/lib/object_store/OSToken.cpp
new file mode 100644
index 0000000..13b1eaa
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/OSToken.cpp
@@ -0,0 +1,722 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSToken.cpp
+
+ The token class; a token is stored in a directory containing several files.
+ Each object is stored in a separate file and a token object is present that
+ has the token specific attributes
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSAttributes.h"
+#include "OSAttribute.h"
+#include "ObjectFile.h"
+#include "Directory.h"
+#include "Generation.h"
+#include "UUID.h"
+#include "cryptoki.h"
+#include "OSToken.h"
+#include "OSPathSep.h"
+#include <vector>
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+#include <stdio.h>
+
+// Constructor
+OSToken::OSToken(const std::string inTokenPath)
+{
+ tokenPath = inTokenPath;
+
+ tokenDir = new Directory(tokenPath);
+ gen = Generation::create(tokenPath + OS_PATHSEP + "generation", true);
+ tokenObject = new ObjectFile(this, tokenPath + OS_PATHSEP + "token.object", tokenPath + OS_PATHSEP + "token.lock");
+ tokenMutex = MutexFactory::i()->getMutex();
+ valid = (gen != NULL) && (tokenMutex != NULL) && tokenDir->isValid() && tokenObject->valid;
+
+ DEBUG_MSG("Opened token %s", tokenPath.c_str());
+
+ index(true);
+}
+
+// Create a new token
+/*static*/ OSToken* OSToken::createToken(const std::string basePath, const std::string tokenDir, const ByteString& label, const ByteString& serial)
+{
+ Directory baseDir(basePath);
+
+ if (!baseDir.isValid())
+ {
+ ERROR_MSG("Could not create the Directory object");
+ return NULL;
+ }
+
+ // Create the token directory
+ if (!baseDir.mkdir(tokenDir))
+ {
+ // Error msg is generated by mkdir
+ return NULL;
+ }
+
+ // Create the token object
+ ObjectFile tokenObject(NULL, basePath + OS_PATHSEP + tokenDir + OS_PATHSEP + "token.object", basePath + OS_PATHSEP + tokenDir + OS_PATHSEP + "token.lock", true);
+
+ if (!tokenObject.valid)
+ {
+ std::string tokenPath = basePath + OS_PATHSEP + tokenDir + OS_PATHSEP + "token.[object|lock]";
+ ERROR_MSG("Failed to create the token object: %s", tokenPath.c_str());
+
+ baseDir.rmdir(tokenDir);
+
+ return NULL;
+ }
+
+ // Set the initial attributes
+ CK_ULONG flags =
+ CKF_RNG |
+ CKF_LOGIN_REQUIRED | // FIXME: check
+ CKF_RESTORE_KEY_NOT_NEEDED |
+ CKF_TOKEN_INITIALIZED |
+ CKF_SO_PIN_LOCKED |
+ CKF_SO_PIN_TO_BE_CHANGED;
+
+ OSAttribute tokenLabel(label);
+ OSAttribute tokenSerial(serial);
+ OSAttribute tokenFlags(flags);
+
+ if (!tokenObject.setAttribute(CKA_OS_TOKENLABEL, tokenLabel) ||
+ !tokenObject.setAttribute(CKA_OS_TOKENSERIAL, tokenSerial) ||
+ !tokenObject.setAttribute(CKA_OS_TOKENFLAGS, tokenFlags))
+ {
+ ERROR_MSG("Failed to set the token attributes");
+
+ baseDir.remove(tokenDir + OS_PATHSEP + "token.object");
+ baseDir.remove(tokenDir + OS_PATHSEP + "token.lock");
+ baseDir.rmdir(tokenDir);
+
+ return NULL;
+ }
+
+ DEBUG_MSG("Created new token %s", tokenDir.c_str());
+
+ return new OSToken(basePath + OS_PATHSEP + tokenDir);
+}
+
+// Access an existing token
+/*static*/ OSToken *OSToken::accessToken(const std::string &basePath, const std::string &tokenDir)
+{
+ return new OSToken(basePath + OS_PATHSEP + tokenDir);
+}
+
+// Destructor
+OSToken::~OSToken()
+{
+ // Clean up
+ std::set<OSObject*> cleanUp = allObjects;
+ allObjects.clear();
+
+ for (std::set<OSObject*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ delete *i;
+ }
+
+ delete tokenDir;
+ if (gen != NULL) delete gen;
+ MutexFactory::i()->recycleMutex(tokenMutex);
+ delete tokenObject;
+}
+
+// Set the SO PIN
+bool OSToken::setSOPIN(const ByteString& soPINBlob)
+{
+ if (!valid) return false;
+
+ OSAttribute soPIN(soPINBlob);
+
+ CK_ULONG flags;
+
+ if (tokenObject->setAttribute(CKA_OS_SOPIN, soPIN) &&
+ getTokenFlags(flags))
+ {
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ flags &= ~CKF_SO_PIN_FINAL_TRY;
+ flags &= ~CKF_SO_PIN_LOCKED;
+ flags &= ~CKF_SO_PIN_TO_BE_CHANGED;
+
+ return setTokenFlags(flags);
+ }
+
+ return false;
+}
+
+// Get the SO PIN
+bool OSToken::getSOPIN(ByteString& soPINBlob)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ if (tokenObject->attributeExists(CKA_OS_SOPIN))
+ {
+ soPINBlob = tokenObject->getAttribute(CKA_OS_SOPIN).getByteStringValue();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Set the user PIN
+bool OSToken::setUserPIN(ByteString userPINBlob)
+{
+ if (!valid) return false;
+
+ OSAttribute userPIN(userPINBlob);
+
+ CK_ULONG flags;
+
+ if (tokenObject->setAttribute(CKA_OS_USERPIN, userPIN) &&
+ getTokenFlags(flags))
+ {
+ flags |= CKF_USER_PIN_INITIALIZED;
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ flags &= ~CKF_USER_PIN_FINAL_TRY;
+ flags &= ~CKF_USER_PIN_LOCKED;
+ flags &= ~CKF_USER_PIN_TO_BE_CHANGED;
+
+ return setTokenFlags(flags);
+ }
+
+ return false;
+}
+
+// Get the user PIN
+bool OSToken::getUserPIN(ByteString& userPINBlob)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ if (tokenObject->attributeExists(CKA_OS_USERPIN))
+ {
+ userPINBlob = tokenObject->getAttribute(CKA_OS_USERPIN).getByteStringValue();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Retrieve the token label
+bool OSToken::getTokenLabel(ByteString& label)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ if (tokenObject->attributeExists(CKA_OS_TOKENLABEL))
+ {
+ label = tokenObject->getAttribute(CKA_OS_TOKENLABEL).getByteStringValue();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Retrieve the token serial
+bool OSToken::getTokenSerial(ByteString& serial)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ if (tokenObject->attributeExists(CKA_OS_TOKENSERIAL))
+ {
+ serial = tokenObject->getAttribute(CKA_OS_TOKENSERIAL).getByteStringValue();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Get the token flags
+bool OSToken::getTokenFlags(CK_ULONG& flags)
+{
+ if (!valid || !tokenObject->isValid())
+ {
+ return false;
+ }
+
+ if (tokenObject->attributeExists(CKA_OS_TOKENFLAGS))
+ {
+ flags = tokenObject->getAttribute(CKA_OS_TOKENFLAGS).getUnsignedLongValue();
+
+ // Check if the user PIN is initialised
+ if (tokenObject->attributeExists(CKA_OS_USERPIN))
+ {
+ flags |= CKF_USER_PIN_INITIALIZED;
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Set the token flags
+bool OSToken::setTokenFlags(const CK_ULONG flags)
+{
+ if (!valid) return false;
+
+ OSAttribute tokenFlags(flags);
+
+ return tokenObject->setAttribute(CKA_OS_TOKENFLAGS, tokenFlags);
+}
+
+// Retrieve objects
+std::set<OSObject*> OSToken::getObjects()
+{
+ index();
+
+ // Make sure that no other thread is in the process of changing
+ // the object list when we return it
+ MutexLocker lock(tokenMutex);
+
+ return objects;
+}
+
+void OSToken::getObjects(std::set<OSObject*> &inObjects)
+{
+ index();
+
+ // Make sure that no other thread is in the process of changing
+ // the object list when we return it
+ MutexLocker lock(tokenMutex);
+
+ inObjects.insert(objects.begin(),objects.end());
+}
+
+// Create a new object
+OSObject* OSToken::createObject()
+{
+ if (!valid) return NULL;
+
+ // Generate a name for the object
+ std::string objectUUID = UUID::newUUID();
+ std::string objectPath = tokenPath + OS_PATHSEP + objectUUID + ".object";
+ std::string lockPath = tokenPath + OS_PATHSEP + objectUUID + ".lock";
+
+ // Create the new object file
+ ObjectFile* newObject = new ObjectFile(this, objectPath, lockPath, true);
+
+ if (!newObject->valid)
+ {
+ ERROR_MSG("Failed to create new object %s", objectPath.c_str());
+
+ delete newObject;
+
+ return NULL;
+ }
+
+ // Now add it to the set of objects
+ MutexLocker lock(tokenMutex);
+
+ objects.insert(newObject);
+ allObjects.insert(newObject);
+ currentFiles.insert(newObject->getFilename());
+
+ DEBUG_MSG("(0x%08X) Created new object %s (0x%08X)", this, objectPath.c_str(), newObject);
+
+ gen->update();
+
+ gen->commit();
+
+ return newObject;
+}
+
+// Delete an object
+bool OSToken::deleteObject(OSObject* object)
+{
+ if (!valid) return false;
+
+ if (objects.find(object) == objects.end())
+ {
+ ERROR_MSG("Cannot delete non-existent object 0x%08X", object);
+
+ return false;
+ }
+
+ MutexLocker lock(tokenMutex);
+
+ ObjectFile* fileObject = dynamic_cast<ObjectFile*>(object);
+ if (fileObject == NULL)
+ {
+ ERROR_MSG("Object type not compatible with this token class 0x%08X", object);
+
+ return false;
+ }
+
+ // Invalidate the object instance
+ fileObject->invalidate();
+
+ // Retrieve the filename of the object
+ std::string objectFilename = fileObject->getFilename();
+
+ // Attempt to delete the file
+ if (!tokenDir->remove(objectFilename))
+ {
+ ERROR_MSG("Failed to delete object file %s", objectFilename.c_str());
+
+ return false;
+ }
+
+ // Retrieve the filename of the lock
+ std::string lockFilename = fileObject->getLockname();
+
+ // Attempt to delete the lock
+ if (!tokenDir->remove(lockFilename))
+ {
+ ERROR_MSG("Failed to delete lock file %s", lockFilename.c_str());
+
+ return false;
+ }
+
+ objects.erase(object);
+
+ DEBUG_MSG("Deleted object %s", objectFilename.c_str());
+
+ gen->update();
+
+ gen->commit();
+
+ return true;
+}
+
+// Checks if the token is consistent
+bool OSToken::isValid()
+{
+ return valid;
+}
+
+// Invalidate the token (for instance if it is deleted)
+void OSToken::invalidate()
+{
+ valid = false;
+}
+
+// Delete the token
+bool OSToken::clearToken()
+{
+ MutexLocker lock(tokenMutex);
+
+ // Invalidate the token
+ invalidate();
+
+ // First, clear out all objects
+ objects.clear();
+
+ // Now, delete all files in the token directory
+ if (!tokenDir->refresh())
+ {
+ return false;
+ }
+
+ std::vector<std::string> tokenFiles = tokenDir->getFiles();
+
+ for (std::vector<std::string>::iterator i = tokenFiles.begin(); i != tokenFiles.end(); i++)
+ {
+ if (!tokenDir->remove(*i))
+ {
+ ERROR_MSG("Failed to remove %s from token directory %s", i->c_str(), tokenPath.c_str());
+
+ return false;
+ }
+ }
+
+ // Now remove the token directory
+ if (!tokenDir->rmdir(""))
+ {
+ ERROR_MSG("Failed to remove the token directory %s", tokenPath.c_str());
+
+ return false;
+ }
+
+ DEBUG_MSG("Token instance %s was succesfully cleared", tokenPath.c_str());
+
+ return true;
+}
+
+// Reset the token
+bool OSToken::resetToken(const ByteString& label)
+{
+ CK_ULONG flags;
+
+ if (!getTokenFlags(flags))
+ {
+ ERROR_MSG("Failed to get the token attributes");
+
+ return false;
+ }
+
+ // Clean up
+ std::set<OSObject*> cleanUp = getObjects();
+
+ MutexLocker lock(tokenMutex);
+
+ for (std::set<OSObject*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ ObjectFile* fileObject = dynamic_cast<ObjectFile*>(*i);
+ if (fileObject == NULL)
+ {
+ ERROR_MSG("Object type not compatible with this token class 0x%08X", *i);
+
+ return false;
+ }
+
+ // Invalidate the object instance
+ fileObject->invalidate();
+
+ // Retrieve the filename of the object
+ std::string objectFilename = fileObject->getFilename();
+
+ // Attempt to delete the file
+ if (!tokenDir->remove(objectFilename))
+ {
+ ERROR_MSG("Failed to delete object file %s", objectFilename.c_str());
+
+ return false;
+ }
+
+ // Retrieve the filename of the lock
+ std::string lockFilename = fileObject->getLockname();
+
+ // Attempt to delete the lock
+ if (!tokenDir->remove(lockFilename))
+ {
+ ERROR_MSG("Failed to delete lock file %s", lockFilename.c_str());
+
+ return false;
+ }
+
+ objects.erase(*i);
+
+ DEBUG_MSG("Deleted object %s", objectFilename.c_str());
+ }
+
+ // The user PIN has been removed
+ flags &= ~CKF_USER_PIN_INITIALIZED;
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ flags &= ~CKF_USER_PIN_FINAL_TRY;
+ flags &= ~CKF_USER_PIN_LOCKED;
+ flags &= ~CKF_USER_PIN_TO_BE_CHANGED;
+
+ // Set new token attributes
+ OSAttribute tokenLabel(label);
+ OSAttribute tokenFlags(flags);
+
+ if (!tokenObject->setAttribute(CKA_OS_TOKENLABEL, tokenLabel) ||
+ !tokenObject->setAttribute(CKA_OS_TOKENFLAGS, tokenFlags))
+ {
+ ERROR_MSG("Failed to set the token attributes");
+
+ return false;
+ }
+
+ if (tokenObject->attributeExists(CKA_OS_USERPIN) &&
+ !tokenObject->deleteAttribute(CKA_OS_USERPIN))
+ {
+ ERROR_MSG("Failed to remove USERPIN");
+
+ return false;
+ }
+
+ DEBUG_MSG("Token instance %s was succesfully reset", tokenPath.c_str());
+
+ gen->update();
+ gen->commit();
+
+ return true;
+}
+
+// Index the token
+bool OSToken::index(bool isFirstTime /* = false */)
+{
+ // No access to object mutable fields before
+ MutexLocker lock(tokenMutex);
+
+ // Check if re-indexing is required
+ if (!isFirstTime && (!valid || !gen->wasUpdated()))
+ {
+ DEBUG_MSG("No re-indexing is required");
+
+ return true;
+ }
+
+ // Check the integrity
+ if (!tokenDir->refresh() || !tokenObject->valid)
+ {
+ ERROR_MSG("Token integrity check failed");
+
+ valid = false;
+
+ return false;
+ }
+
+ DEBUG_MSG("Token %s has changed", tokenPath.c_str());
+
+ // Retrieve the directory listing
+ std::vector<std::string> tokenFiles = tokenDir->getFiles();
+
+ // Filter out the objects
+ std::set<std::string> newSet;
+
+ for (std::vector<std::string>::iterator i = tokenFiles.begin(); i != tokenFiles.end(); i++)
+ {
+ if ((i->size() > 7) &&
+ (!(i->substr(i->size() - 7).compare(".object"))) &&
+ (i->compare("token.object")))
+ {
+ newSet.insert(*i);
+ }
+ else
+ {
+ DEBUG_MSG("Ignored file %s", i->c_str());
+ }
+ }
+
+ // Compute the changes compared to the last list of files
+ std::set<std::string> addedFiles;
+ std::set<std::string> removedFiles;
+
+ if (!isFirstTime)
+ {
+ // First compute which files were added
+ for (std::set<std::string>::iterator i = newSet.begin(); i != newSet.end(); i++)
+ {
+ if (currentFiles.find(*i) == currentFiles.end())
+ {
+ addedFiles.insert(*i);
+ }
+ }
+
+ // Now compute which files were removed
+ for (std::set<std::string>::iterator i = currentFiles.begin(); i != currentFiles.end(); i++)
+ {
+ if (newSet.find(*i) == newSet.end())
+ {
+ removedFiles.insert(*i);
+ }
+ }
+ }
+ else
+ {
+ addedFiles = newSet;
+ }
+
+ currentFiles = newSet;
+
+ DEBUG_MSG("%d objects were added and %d objects were removed", addedFiles.size(), removedFiles.size());
+ DEBUG_MSG("Current directory set contains %d objects", currentFiles.size());
+
+ // Now update the set of objects
+
+ // Add new objects
+ for (std::set<std::string>::iterator i = addedFiles.begin(); i != addedFiles.end(); i++)
+ {
+ if ((i->find_last_of('.') == std::string::npos) ||
+ (i->substr(i->find_last_of('.')) != ".object"))
+ {
+ continue;
+ }
+
+ std::string lockName(*i);
+ lockName.replace(lockName.find_last_of('.'), std::string::npos, ".lock");
+
+ // Create a new token object for the added file
+ ObjectFile* newObject = new ObjectFile(this, tokenPath + OS_PATHSEP + *i, tokenPath + OS_PATHSEP + lockName);
+
+ // Add the object, even invalid ones.
+ // This is so the we can read the attributes once
+ // the other process has finished writing to disc.
+ DEBUG_MSG("(0x%08X) New object %s (0x%08X) added", this, newObject->getFilename().c_str(), newObject);
+ objects.insert(newObject);
+ allObjects.insert(newObject);
+ }
+
+ // Remove deleted objects
+ std::set<OSObject*> newObjects;
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ObjectFile* fileObject = dynamic_cast<ObjectFile*>((*i));
+ if (fileObject == NULL)
+ {
+ ERROR_MSG("Object type not compatible with this token class 0x%08X", (*i));
+
+ return false;
+ }
+
+ DEBUG_MSG("Processing %s (0x%08X)", fileObject->getFilename().c_str(), *i);
+
+ if (removedFiles.find(fileObject->getFilename()) == removedFiles.end())
+ {
+ DEBUG_MSG("Adding object %s", fileObject->getFilename().c_str());
+ // This object gets to stay in the set
+ newObjects.insert(*i);
+ }
+ else
+ {
+ fileObject->invalidate();
+ }
+ }
+
+ // Set the new objects
+ objects = newObjects;
+
+ DEBUG_MSG("The token now contains %d objects", objects.size());
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/OSToken.h b/SoftHSMv2/src/lib/object_store/OSToken.h
new file mode 100644
index 0000000..4ba5b2c
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/OSToken.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSToken.h
+
+ The token class; a token is stored in a directory containing several files.
+ Each object is stored in a separate file and a token object is present that
+ has the token specific attributes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSTOKEN_H
+#define _SOFTHSM_V2_OSTOKEN_H
+
+#include "config.h"
+#include "ObjectStoreToken.h"
+#include "OSAttribute.h"
+#include "ObjectFile.h"
+#include "Directory.h"
+#include "Generation.h"
+#include "UUID.h"
+#include "MutexFactory.h"
+#include "cryptoki.h"
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+
+class OSToken : public ObjectStoreToken
+{
+public:
+ // Constructor
+ OSToken(const std::string inTokenPath);
+
+ // Create a new token
+ static OSToken* createToken(const std::string basePath, const std::string tokenDir, const ByteString& label, const ByteString& serial);
+
+ // Access an existing token
+ static OSToken* accessToken(const std::string &basePath, const std::string &tokenDir);
+
+ // Constructor for new tokens
+ OSToken(const std::string tokenPath, const ByteString& label, const ByteString& serialNumber);
+
+ // Set the SO PIN
+ virtual bool setSOPIN(const ByteString& soPINBlob);
+
+ // Get the SO PIN
+ virtual bool getSOPIN(ByteString& soPINBlob);
+
+ // Set the user PIN
+ virtual bool setUserPIN(ByteString userPINBlob);
+
+ // Get the user PIN
+ virtual bool getUserPIN(ByteString& userPINBlob);
+
+ // Get the token flags
+ virtual bool getTokenFlags(CK_ULONG& flags);
+
+ // Set the token flags
+ virtual bool setTokenFlags(const CK_ULONG flags);
+
+ // Retrieve the token label
+ virtual bool getTokenLabel(ByteString& label);
+
+ // Retrieve the token serial
+ virtual bool getTokenSerial(ByteString& serial);
+
+ // Retrieve objects
+ virtual std::set<OSObject*> getObjects();
+
+ // Insert objects into the given set
+ virtual void getObjects(std::set<OSObject*> &inObjects);
+
+ // Create a new object
+ virtual OSObject* createObject();
+
+ // Delete an object
+ virtual bool deleteObject(OSObject* object);
+
+ // Destructor
+ virtual ~OSToken();
+
+ // Checks if the token is consistent
+ virtual bool isValid();
+
+ // Invalidate the token (for instance if it is deleted)
+ virtual void invalidate();
+
+ // Delete the token
+ virtual bool clearToken();
+
+ // Reset the token
+ virtual bool resetToken(const ByteString& label);
+
+private:
+ // ObjectFile instances can call the index() function
+ friend class ObjectFile;
+
+ // Index the token
+ bool index(bool isFirstTime = false);
+
+ // Is the token consistent and valid?
+ bool valid;
+
+ // The token path
+ std::string tokenPath;
+
+ // The current objects of the token
+ std::set<OSObject*> objects;
+
+ // All the objects ever associated with this token
+ //
+ // This set is kept to be able to clean up when the token
+ // instance is discarded; in case the contents of a token
+ // change, some objects may disappear but we cannot simply
+ // delete them since they may still be referenced from an
+ // object outside of this class.
+ std::set<OSObject*> allObjects;
+
+ // The current list of files
+ std::set<std::string> currentFiles;
+
+ // The token object
+ ObjectFile* tokenObject;
+
+ // Generation control
+ Generation* gen;
+
+ // The directory object for this token
+ Directory* tokenDir;
+
+ // For thread safeness
+ Mutex* tokenMutex;
+};
+
+#endif // !_SOFTHSM_V2_OSTOKEN_H
+
diff --git a/SoftHSMv2/src/lib/object_store/ObjectFile.cpp b/SoftHSMv2/src/lib/object_store/ObjectFile.cpp
new file mode 100644
index 0000000..f3becbe
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/ObjectFile.cpp
@@ -0,0 +1,870 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectFile.h
+
+ This class represents object files
+ *****************************************************************************/
+
+#include "config.h"
+#include "ObjectFile.h"
+#include "OSToken.h"
+#include "OSPathSep.h"
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <set>
+
+// Attribute types
+#define BOOLEAN_ATTR 0x1
+#define ULONG_ATTR 0x2
+#define BYTESTR_ATTR 0x3
+#define ATTRMAP_ATTR 0x4
+#define MECHSET_ATTR 0x5
+
+// Constructor
+ObjectFile::ObjectFile(OSToken* parent, std::string inPath, std::string inLockpath, bool isNew /* = false */)
+{
+ path = inPath;
+ gen = Generation::create(path);
+ objectMutex = MutexFactory::i()->getMutex();
+ valid = (gen != NULL) && (objectMutex != NULL);
+ token = parent;
+ inTransaction = false;
+ transactionLockFile = NULL;
+ lockpath = inLockpath;
+
+ if (!valid) return;
+
+ if (!isNew)
+ {
+ DEBUG_MSG("Opened existing object %s", path.c_str());
+
+ refresh(true);
+ }
+ else
+ {
+ DEBUG_MSG("Created new object %s", path.c_str());
+
+ // Create an empty object file
+ store();
+ }
+
+}
+
+// Destructor
+ObjectFile::~ObjectFile()
+{
+ discardAttributes();
+
+ if (gen != NULL)
+ {
+ delete gen;
+ }
+
+ MutexFactory::i()->recycleMutex(objectMutex);
+}
+
+// Check if the specified attribute exists
+bool ObjectFile::attributeExists(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ return valid && (attributes[type] != NULL);
+}
+
+// Retrieve the specified attribute
+OSAttribute ObjectFile::getAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ OSAttribute* attr = attributes[type];
+ if (attr == NULL)
+ {
+ ERROR_MSG("The attribute does not exist: 0x%08X", type);
+ return OSAttribute((unsigned long)0);
+ }
+
+ return *attr;
+}
+
+bool ObjectFile::getBooleanValue(CK_ATTRIBUTE_TYPE type, bool val)
+{
+ MutexLocker lock(objectMutex);
+
+ OSAttribute* attr = attributes[type];
+ if (attr == NULL)
+ {
+ ERROR_MSG("The attribute does not exist: 0x%08X", type);
+ return val;
+ }
+
+ if (attr->isBooleanAttribute())
+ {
+ return attr->getBooleanValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not a boolean: 0x%08X", type);
+ return val;
+ }
+}
+
+unsigned long ObjectFile::getUnsignedLongValue(CK_ATTRIBUTE_TYPE type, unsigned long val)
+{
+ MutexLocker lock(objectMutex);
+
+ OSAttribute* attr = attributes[type];
+ if (attr == NULL)
+ {
+ ERROR_MSG("The attribute does not exist: 0x%08X", type);
+ return val;
+ }
+
+ if (attr->isUnsignedLongAttribute())
+ {
+ return attr->getUnsignedLongValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not an unsigned long: 0x%08X", type);
+ return val;
+ }
+}
+
+ByteString ObjectFile::getByteStringValue(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ ByteString val;
+
+ OSAttribute* attr = attributes[type];
+ if (attr == NULL)
+ {
+ ERROR_MSG("The attribute does not exist: 0x%08X", type);
+ return val;
+ }
+
+ if (attr->isByteStringAttribute())
+ {
+ return attr->getByteStringValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not a byte string: 0x%08X", type);
+ return val;
+ }
+}
+
+// Retrieve the next attribute type
+CK_ATTRIBUTE_TYPE ObjectFile::nextAttributeType(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*>::iterator n = attributes.upper_bound(type);
+
+ // skip null attributes
+ while ((n != attributes.end()) && (n->second == NULL))
+ ++n;
+
+ // return type or CKA_CLASS (= 0)
+ if (n == attributes.end())
+ {
+ return CKA_CLASS;
+ }
+ else
+ {
+ return n->first;
+ }
+}
+
+// Set the specified attribute
+bool ObjectFile::setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute)
+{
+ if (!valid)
+ {
+ DEBUG_MSG("Cannot update invalid object %s", path.c_str());
+
+ return false;
+ }
+
+ {
+ MutexLocker lock(objectMutex);
+
+ if (attributes[type] != NULL)
+ {
+ delete attributes[type];
+
+ attributes[type] = NULL;
+ }
+
+ attributes[type] = new OSAttribute(attribute);
+ }
+
+ store();
+
+ return valid;
+}
+
+// Delete the specified attribute
+bool ObjectFile::deleteAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ if (!valid)
+ {
+ DEBUG_MSG("Cannot update invalid object %s", path.c_str());
+
+ return false;
+ }
+
+ {
+ MutexLocker lock(objectMutex);
+
+ if (attributes[type] == NULL)
+ {
+ DEBUG_MSG("Cannot delete attribute that doesn't exist in object %s", path.c_str());
+
+ return false;
+ }
+
+ delete attributes[type];
+ attributes.erase(type);
+ }
+
+ store();
+
+ return valid;
+}
+
+// The validity state of the object (refresh from disk as a side effect)
+bool ObjectFile::isValid()
+{
+ refresh();
+
+ return valid;
+}
+
+// Invalidate the object file externally; this method is normally
+// only called by the OSToken class in case an object file has
+// been deleted.
+void ObjectFile::invalidate()
+{
+ valid = false;
+
+ discardAttributes();
+}
+
+// Refresh the object if necessary
+void ObjectFile::refresh(bool isFirstTime /* = false */)
+{
+ // Check if we're in the middle of a transaction
+ if (inTransaction)
+ {
+ DEBUG_MSG("The object is in a transaction");
+
+ return;
+ }
+
+ // Refresh the associated token if set
+ if (!isFirstTime && (token != NULL))
+ {
+ // This may cause this instance to become invalid
+ token->index();
+ }
+
+ // Check the generation
+ if (!isFirstTime && (gen == NULL || !gen->wasUpdated()))
+ {
+ DEBUG_MSG("The object generation has not been updated");
+
+ return;
+ }
+
+ File objectFile(path);
+
+ if (!objectFile.isValid())
+ {
+ DEBUG_MSG("Object %s is invalid", path.c_str());
+
+ valid = false;
+
+ return;
+ }
+
+ objectFile.lock();
+
+ if (objectFile.isEmpty())
+ {
+ DEBUG_MSG("Object %s is empty", path.c_str());
+
+ valid = false;
+
+ return;
+ }
+
+ DEBUG_MSG("Object %s has changed", path.c_str());
+
+ // Discard the existing set of attributes
+ discardAttributes();
+
+ MutexLocker lock(objectMutex);
+
+ // Read back the generation number
+ unsigned long curGen;
+
+ if (!objectFile.readULong(curGen))
+ {
+ if (!objectFile.isEOF())
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+ }
+ else
+ {
+ gen->set(curGen);
+ }
+
+ // Read back the attributes
+ while (!objectFile.isEOF())
+ {
+ unsigned long p11AttrType;
+ unsigned long osAttrType;
+
+ if (!objectFile.readULong(p11AttrType))
+ {
+ if (objectFile.isEOF())
+ {
+ break;
+ }
+
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ if (!objectFile.readULong(osAttrType))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ // Depending on the type, read back the actual value
+ if (osAttrType == BOOLEAN_ATTR)
+ {
+ bool value;
+
+ if (!objectFile.readBool(value))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ if (attributes[p11AttrType] != NULL)
+ {
+ delete attributes[p11AttrType];
+ }
+
+ attributes[p11AttrType] = new OSAttribute(value);
+ }
+ else if (osAttrType == ULONG_ATTR)
+ {
+ unsigned long value;
+
+ if (!objectFile.readULong(value))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ if (attributes[p11AttrType] != NULL)
+ {
+ delete attributes[p11AttrType];
+ }
+
+ attributes[p11AttrType] = new OSAttribute(value);
+ }
+ else if (osAttrType == BYTESTR_ATTR)
+ {
+ ByteString value;
+
+ if (!objectFile.readByteString(value))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ if (attributes[p11AttrType] != NULL)
+ {
+ delete attributes[p11AttrType];
+ }
+
+ attributes[p11AttrType] = new OSAttribute(value);
+ }
+ else if (osAttrType == MECHSET_ATTR)
+ {
+ std::set<CK_MECHANISM_TYPE> value;
+
+ if (!objectFile.readMechanismTypeSet(value))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ if (attributes[p11AttrType] != NULL)
+ {
+ delete attributes[p11AttrType];
+ }
+
+ attributes[p11AttrType] = new OSAttribute(value);
+ }
+ else if (osAttrType == ATTRMAP_ATTR)
+ {
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> value;
+
+ if (!objectFile.readAttributeMap(value))
+ {
+ DEBUG_MSG("Corrupt object file %s", path.c_str());
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+
+ if (attributes[p11AttrType] != NULL)
+ {
+ delete attributes[p11AttrType];
+ }
+
+ attributes[p11AttrType] = new OSAttribute(value);
+ }
+ else
+ {
+ DEBUG_MSG("Corrupt object file %s with unknown attribute of type %d", path.c_str(), osAttrType);
+
+ valid = false;
+
+ objectFile.unlock();
+
+ return;
+ }
+ }
+
+ objectFile.unlock();
+
+ valid = true;
+}
+
+// Common write part in store()
+// called with objectFile locked and returns with objectFile unlocked
+bool ObjectFile::writeAttributes(File &objectFile)
+{
+ if (!gen->sync(objectFile))
+ {
+ DEBUG_MSG("Failed to synchronize generation number from object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+
+ if (!objectFile.truncate())
+ {
+ DEBUG_MSG("Failed to reset object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+
+ gen->update();
+
+ unsigned long newGen = gen->get();
+
+ if (!objectFile.writeULong(newGen))
+ {
+ DEBUG_MSG("Failed to write new generation number to object %s", path.c_str());
+
+ gen->rollback();
+
+ objectFile.unlock();
+
+ return false;
+ }
+
+
+ for (std::map<CK_ATTRIBUTE_TYPE, OSAttribute*>::iterator i = attributes.begin(); i != attributes.end(); i++)
+ {
+ if (i->second == NULL)
+ {
+ continue;
+ }
+
+ unsigned long p11AttrType = i->first;
+
+ if (!objectFile.writeULong(p11AttrType))
+ {
+ DEBUG_MSG("Failed to write PKCS #11 attribute type to object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+
+ if (i->second->isBooleanAttribute())
+ {
+ unsigned long osAttrType = BOOLEAN_ATTR;
+ bool value = i->second->getBooleanValue();
+
+ if (!objectFile.writeULong(osAttrType) || !objectFile.writeBool(value))
+ {
+ DEBUG_MSG("Failed to write attribute to object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+ }
+ else if (i->second->isUnsignedLongAttribute())
+ {
+ unsigned long osAttrType = ULONG_ATTR;
+ unsigned long value = i->second->getUnsignedLongValue();
+
+ if (!objectFile.writeULong(osAttrType) || !objectFile.writeULong(value))
+ {
+ DEBUG_MSG("Failed to write attribute to object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+ }
+ else if (i->second->isByteStringAttribute())
+ {
+ unsigned long osAttrType = BYTESTR_ATTR;
+ const ByteString& value = i->second->getByteStringValue();
+
+ if (!objectFile.writeULong(osAttrType) || !objectFile.writeByteString(value))
+ {
+ DEBUG_MSG("Failed to write attribute to object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+ }
+ else if (i->second->isMechanismTypeSetAttribute())
+ {
+ unsigned long osAttrType = MECHSET_ATTR;
+ const std::set<CK_MECHANISM_TYPE>& value = i->second->getMechanismTypeSetValue();
+
+ if (!objectFile.writeULong(osAttrType) || !objectFile.writeMechanismTypeSet(value))
+ {
+ DEBUG_MSG("Failed to write attribute to object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+ }
+ else if (i->second->isAttributeMapAttribute())
+ {
+ unsigned long osAttrType = ATTRMAP_ATTR;
+ const std::map<CK_ATTRIBUTE_TYPE,OSAttribute>& value = i->second->getAttributeMapValue();
+
+ if (!objectFile.writeULong(osAttrType) || !objectFile.writeAttributeMap(value))
+ {
+ DEBUG_MSG("Failed to write attribute to object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+ }
+ else
+ {
+ DEBUG_MSG("Unknown attribute type for object %s", path.c_str());
+
+ objectFile.unlock();
+
+ return false;
+ }
+ }
+
+ objectFile.unlock();
+
+ return true;
+}
+
+// Write the object to background storage
+void ObjectFile::store(bool isCommit /* = false */)
+{
+ // Check if we're in the middle of a transaction
+ if (!isCommit && inTransaction)
+ {
+ return;
+ }
+
+ if (!valid)
+ {
+ DEBUG_MSG("Cannot write back an invalid object %s", path.c_str());
+
+ return;
+ }
+
+ File objectFile(path, true, true, true, false);
+
+ if (!objectFile.isValid())
+ {
+ DEBUG_MSG("Cannot open object %s for writing", path.c_str());
+
+ valid = false;
+
+ return;
+ }
+
+ objectFile.lock();
+
+ if (!isCommit) {
+ MutexLocker lock(objectMutex);
+ File lockFile(lockpath, false, true, true);
+
+ if (!writeAttributes(objectFile))
+ {
+ valid = false;
+
+ return;
+ }
+ }
+ else
+ {
+ if (!writeAttributes(objectFile))
+ {
+ valid = false;
+
+ return;
+ }
+ }
+
+ valid = true;
+}
+
+// Discard the cached attributes
+void ObjectFile::discardAttributes()
+{
+ MutexLocker lock(objectMutex);
+
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*> cleanUp = attributes;
+ attributes.clear();
+
+ for (std::map<CK_ATTRIBUTE_TYPE, OSAttribute*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if (i->second == NULL)
+ {
+ continue;
+ }
+
+ delete i->second;
+ i->second = NULL;
+ }
+}
+
+
+// Returns the file name of the object
+std::string ObjectFile::getFilename() const
+{
+ if ((path.find_last_of(OS_PATHSEP) != std::string::npos) &&
+ (path.find_last_of(OS_PATHSEP) < path.size()))
+ {
+ return path.substr(path.find_last_of(OS_PATHSEP) + 1);
+ }
+ else
+ {
+ return path;
+ }
+}
+
+// Returns the file name of the lock
+std::string ObjectFile::getLockname() const
+{
+ if ((lockpath.find_last_of(OS_PATHSEP) != std::string::npos) &&
+ (lockpath.find_last_of(OS_PATHSEP) < lockpath.size()))
+ {
+ return lockpath.substr(lockpath.find_last_of(OS_PATHSEP) + 1);
+ }
+ else
+ {
+ return lockpath;
+ }
+}
+
+// Start an attribute set transaction; this method is used when - for
+// example - a key is generated and all its attributes need to be
+// persisted in one go.
+//
+// N.B.: Starting a transaction locks the object!
+bool ObjectFile::startTransaction(Access)
+{
+ MutexLocker lock(objectMutex);
+
+ if (inTransaction)
+ {
+ return false;
+ }
+
+ transactionLockFile = new File(lockpath, false, true, true);
+
+ if (!transactionLockFile->isValid() || !transactionLockFile->lock())
+ {
+ delete transactionLockFile;
+ transactionLockFile = NULL;
+
+ ERROR_MSG("Failed to lock file %s for attribute transaction", lockpath.c_str());
+
+ return false;
+ }
+
+ inTransaction = true;
+
+ return true;
+}
+
+// Commit an attribute transaction
+bool ObjectFile::commitTransaction()
+{
+ MutexLocker lock(objectMutex);
+
+ if (!inTransaction)
+ {
+ return false;
+ }
+
+ if (transactionLockFile == NULL)
+ {
+ ERROR_MSG("Transaction lock file instance invalid!");
+
+ return false;
+ }
+
+ // Special store case
+ store(true);
+
+ if (!valid)
+ {
+ return false;
+ }
+
+ transactionLockFile->unlock();
+
+ delete transactionLockFile;
+ transactionLockFile = NULL;
+ inTransaction = false;
+
+ return true;
+}
+
+// Abort an attribute transaction; loads back the previous version of the object from disk
+bool ObjectFile::abortTransaction()
+{
+ {
+ MutexLocker lock(objectMutex);
+
+ if (!inTransaction)
+ {
+ return false;
+ }
+
+ if (transactionLockFile == NULL)
+ {
+ ERROR_MSG("Transaction lock file instance invalid!");
+
+ return false;
+ }
+
+ transactionLockFile->unlock();
+
+ delete transactionLockFile;
+ transactionLockFile = NULL;
+ inTransaction = false;
+ }
+
+ // Force reload from disk
+ refresh(true);
+
+ return true;
+}
+
+// Destroy the object; WARNING: pointers to the object become invalid after this call
+bool ObjectFile::destroyObject()
+{
+ if (token == NULL)
+ {
+ ERROR_MSG("Cannot destroy an object that is not associated with a token");
+
+ return false;
+ }
+
+ return token->deleteObject(this);
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/ObjectFile.h b/SoftHSMv2/src/lib/object_store/ObjectFile.h
new file mode 100644
index 0000000..a13d835
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/ObjectFile.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectFile.h
+
+ This class represents object files
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTFILE_H
+#define _SOFTHSM_V2_OBJECTFILE_H
+
+#include "config.h"
+#include "File.h"
+#include "Generation.h"
+#include "ByteString.h"
+#include "OSAttribute.h"
+#include "MutexFactory.h"
+#include <string>
+#include <map>
+#include <time.h>
+#include "cryptoki.h"
+#include "OSObject.h"
+
+// OSToken forward declaration
+class OSToken;
+
+class ObjectFile : public OSObject
+{
+public:
+ // Constructor
+ ObjectFile(OSToken* parent, const std::string inPath, const std::string inLockpath, bool isNew = false);
+
+ // Destructor
+ virtual ~ObjectFile();
+
+ // Check if the specified attribute exists
+ virtual bool attributeExists(CK_ATTRIBUTE_TYPE type);
+
+ // Retrieve the specified attribute
+ virtual OSAttribute getAttribute(CK_ATTRIBUTE_TYPE type);
+ virtual bool getBooleanValue(CK_ATTRIBUTE_TYPE type, bool val);
+ virtual unsigned long getUnsignedLongValue(CK_ATTRIBUTE_TYPE type, unsigned long val);
+ virtual ByteString getByteStringValue(CK_ATTRIBUTE_TYPE type);
+
+ // Retrieve the next attribute type
+ virtual CK_ATTRIBUTE_TYPE nextAttributeType(CK_ATTRIBUTE_TYPE type);
+
+ // Set the specified attribute
+ virtual bool setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute);
+
+ // Delete the specified attribute
+ virtual bool deleteAttribute(CK_ATTRIBUTE_TYPE type);
+
+ // The validity state of the object (refresh from disk as a side effect)
+ virtual bool isValid();
+
+ // Invalidate the object file externally; this method is normally
+ // only called by the OSToken class in case an object file has
+ // been deleted.
+ void invalidate();
+
+ // Returns the file name of the object
+ std::string getFilename() const;
+
+ // Returns the file name of the lock
+ std::string getLockname() const;
+
+ // Start an attribute set transaction; this method is used when - for
+ // example - a key is generated and all its attributes need to be
+ // persisted in one go.
+ //
+ // N.B.: Starting a transaction locks the object!
+ //
+ // Function returns false in case a transaction is already in progress
+ virtual bool startTransaction(Access access);
+
+ // Commit an attribute transaction; returns false if no transaction is in progress
+ virtual bool commitTransaction();
+
+ // Abort an attribute transaction; loads back the previous version of the object from disk;
+ // returns false if no transaction was in progress
+ virtual bool abortTransaction();
+
+ // Destroys the object; WARNING: pointers to the object become invalid after this
+ // call!
+ virtual bool destroyObject();
+
+private:
+ // OSToken instances can read valid (vs calling IsValid() from index())
+ friend class OSToken;
+
+ // Refresh the object if necessary
+ void refresh(bool isFirstTime = false);
+
+ // Write the object to background storage
+ void store(bool isCommit = false);
+
+ // Store subroutine
+ bool writeAttributes(File &objectFile);
+
+ // Discard the cached attributes
+ void discardAttributes();
+
+ // The path to the file
+ std::string path;
+
+ // The Generation object that is used to detect changes in the
+ // object file from other SoftHSM instances
+ Generation* gen;
+
+ // The object's raw attributes
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*> attributes;
+
+ // The object's validity state
+ bool valid;
+
+ // The token this object is associated with
+ OSToken* token;
+
+ // Mutex object for thread-safeness
+ Mutex* objectMutex;
+
+ // Is the object undergoing an attribute transaction?
+ bool inTransaction;
+ File* transactionLockFile;
+ std::string lockpath;
+};
+
+#endif // !_SOFTHSM_V2_OBJECTFILE_H
+
diff --git a/SoftHSMv2/src/lib/object_store/ObjectStore.cpp b/SoftHSMv2/src/lib/object_store/ObjectStore.cpp
new file mode 100644
index 0000000..3855d9d
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/ObjectStore.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStore.h
+
+ The object store manages the separate tokens that the SoftHSM supports. Each
+ token is organised as a directory containing files that are contain the
+ token's objects. The object store is initialised with a root directory from
+ which it enumerates the tokens.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "ObjectStore.h"
+#include "Directory.h"
+#include "ObjectStoreToken.h"
+#include "OSPathSep.h"
+#include "UUID.h"
+#include <stdio.h>
+
+// Constructor
+ObjectStore::ObjectStore(std::string inStorePath)
+{
+ storePath = inStorePath;
+ valid = false;
+ storeMutex = MutexFactory::i()->getMutex();
+
+ MutexLocker lock(storeMutex);
+
+ // Find all tokens in the specified path
+ Directory storeDir(storePath);
+
+ if (!storeDir.isValid())
+ {
+ WARNING_MSG("Failed to enumerate object store in %s", storePath.c_str());
+
+ return;
+ }
+
+ // Assume that all subdirectories are tokens
+ std::vector<std::string> dirs = storeDir.getSubDirs();
+
+ for (std::vector<std::string>::iterator i = dirs.begin(); i != dirs.end(); i++)
+ {
+ // Create a token instance
+ ObjectStoreToken* token = ObjectStoreToken::accessToken(storePath, *i);
+
+ if (!token->isValid())
+ {
+ ERROR_MSG("Failed to open token %s", i->c_str());
+
+ delete token;
+
+ // Silently ignore tokens that we do not have access to
+ continue;
+ }
+
+ tokens.push_back(token);
+ allTokens.push_back(token);
+ }
+
+ valid = true;
+}
+
+// Destructor
+ObjectStore::~ObjectStore()
+{
+ {
+ MutexLocker lock(storeMutex);
+
+ // Clean up
+ tokens.clear();
+
+ for (std::vector<ObjectStoreToken*>::iterator i = allTokens.begin(); i != allTokens.end(); i++)
+ {
+ delete *i;
+ }
+ }
+
+ MutexFactory::i()->recycleMutex(storeMutex);
+}
+
+// Check if the object store is valid
+bool ObjectStore::isValid()
+{
+ return valid;
+}
+
+// Return the number of tokens that is present
+size_t ObjectStore::getTokenCount()
+{
+ MutexLocker lock(storeMutex);
+
+ return tokens.size();
+}
+
+// Return a pointer to the n-th token (counting starts at 0)
+ObjectStoreToken* ObjectStore::getToken(size_t whichToken)
+{
+ MutexLocker lock(storeMutex);
+
+ if (whichToken >= tokens.size())
+ {
+ return NULL;
+ }
+
+ return tokens[whichToken];
+}
+
+// Create a new token
+ObjectStoreToken* ObjectStore::newToken(const ByteString& label)
+{
+ MutexLocker lock(storeMutex);
+
+ // Generate a UUID for the token
+ std::string tokenUUID = UUID::newUUID();
+
+ // Convert the UUID to a serial number
+ std::string serialNumber = tokenUUID.substr(19, 4) + tokenUUID.substr(24);
+ ByteString serial((const unsigned char*) serialNumber.c_str(), serialNumber.size());
+
+ // Create the token
+ ObjectStoreToken* newToken = ObjectStoreToken::createToken(storePath, tokenUUID, label, serial);
+
+ if (newToken != NULL)
+ {
+ tokens.push_back(newToken);
+ allTokens.push_back(newToken);
+ }
+
+ return newToken;
+}
+
+// Destroy a token
+bool ObjectStore::destroyToken(ObjectStoreToken *token)
+{
+ MutexLocker lock(storeMutex);
+
+ // Find the token
+ for (std::vector<ObjectStoreToken*>::iterator i = tokens.begin(); i != tokens.end(); i++)
+ {
+ if (*i == token)
+ {
+ // Found the token, now destroy the token
+ if (!token->clearToken())
+ {
+ ERROR_MSG("Failed to clear token instance");
+
+ return false;
+ }
+
+ // And remove it from the vector
+ tokens.erase(i);
+
+ return true;
+ }
+ }
+
+ ERROR_MSG("Could not find the token instance to destroy");
+
+ return false;
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/ObjectStore.h b/SoftHSMv2/src/lib/object_store/ObjectStore.h
new file mode 100644
index 0000000..e8ecd1a
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/ObjectStore.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStore.h
+
+ The object store manages the separate tokens that the SoftHSM supports. Each
+ token is organised as a directory containing files that are contain the
+ token's objects. The object store is initialised with a root directory from
+ which it enumerates the tokens.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTSTORE_H
+#define _SOFTHSM_V2_OBJECTSTORE_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStoreToken.h"
+#include "MutexFactory.h"
+#include <string>
+#include <vector>
+
+class ObjectStore
+{
+public:
+ // Constructor
+ ObjectStore(std::string inStorePath);
+
+ // Destructor
+ virtual ~ObjectStore();
+
+ // Return the number of tokens that is present
+ size_t getTokenCount();
+
+ // Return a pointer to the n-th token (counting starts at 0)
+ ObjectStoreToken* getToken(size_t whichToken);
+
+ // Create a new token
+ ObjectStoreToken* newToken(const ByteString& label);
+
+ // Destroy a token
+ bool destroyToken(ObjectStoreToken* token);
+
+ // Check if the object store is valid
+ bool isValid();
+
+private:
+ // The tokens
+ std::vector<ObjectStoreToken*> tokens;
+
+ // All tokens
+ std::vector<ObjectStoreToken*> allTokens;
+
+ // The object store root directory
+ std::string storePath;
+
+ // The status
+ bool valid;
+
+ // Object store synchronisation
+ Mutex* storeMutex;
+};
+
+#endif // !_SOFTHSM_V2_OBJECTSTORE_H
+
diff --git a/SoftHSMv2/src/lib/object_store/ObjectStoreToken.cpp b/SoftHSMv2/src/lib/object_store/ObjectStoreToken.cpp
new file mode 100644
index 0000000..24c2049
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/ObjectStoreToken.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStoreToken.cpp
+
+ The object store abstract token base class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "ObjectStoreToken.h"
+
+// OSToken is a concrete implementation of ObjectStoreToken base class.
+#include "OSToken.h"
+
+#ifdef HAVE_OBJECTSTORE_BACKEND_DB
+// DBToken is a concrete implementation of ObjectSToreToken that stores the objects and attributes in an SQLite3 database.
+#include "DBToken.h"
+#endif
+
+typedef ObjectStoreToken* (*CreateToken)(const std::string , const std::string , const ByteString& , const ByteString& );
+typedef ObjectStoreToken* (*AccessToken)(const std::string &, const std::string &);
+
+static CreateToken static_createToken = reinterpret_cast<CreateToken>(OSToken::createToken);
+static AccessToken static_accessToken = reinterpret_cast<AccessToken>(OSToken::accessToken);
+
+// Create a new token
+/*static*/ bool ObjectStoreToken::selectBackend(const std::string &backend)
+{
+ if (backend == "file")
+ {
+ static_createToken = reinterpret_cast<CreateToken>(OSToken::createToken);
+ static_accessToken = reinterpret_cast<AccessToken>(OSToken::accessToken);
+ }
+#ifdef HAVE_OBJECTSTORE_BACKEND_DB
+ else if (backend == "db")
+ {
+ static_createToken = reinterpret_cast<CreateToken>(DBToken::createToken);
+ static_accessToken = reinterpret_cast<AccessToken>(DBToken::accessToken);
+ }
+#endif
+ else
+ {
+ ERROR_MSG("Unknown value (%s) for objectstore.backend in configuration", backend.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+ObjectStoreToken* ObjectStoreToken::createToken(const std::string basePath, const std::string tokenDir, const ByteString& label, const ByteString& serial)
+{
+ return static_createToken(basePath,tokenDir,label,serial);
+}
+
+// Access an existing token
+/*static*/ ObjectStoreToken *ObjectStoreToken::accessToken(const std::string &basePath, const std::string &tokenDir)
+{
+ return static_accessToken(basePath, tokenDir);
+}
diff --git a/SoftHSMv2/src/lib/object_store/ObjectStoreToken.h b/SoftHSMv2/src/lib/object_store/ObjectStoreToken.h
new file mode 100644
index 0000000..668dccc
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/ObjectStoreToken.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStoreToken.h
+
+ The object store abstract token base class;
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTSTORETOKEN_H
+#define _SOFTHSM_V2_OBJECTSTORETOKEN_H
+
+#include "config.h"
+#include "OSObject.h"
+#include <string>
+#include <set>
+
+class ObjectStoreToken
+{
+public:
+ // Select the type of backend to use for storing token objects.
+ static bool selectBackend(const std::string& backend);
+
+ // Create a new token
+ static ObjectStoreToken* createToken(const std::string basePath, const std::string tokenDir, const ByteString& label, const ByteString& serial);
+
+ // Access an existing token
+ static ObjectStoreToken* accessToken(const std::string &basePath, const std::string &tokenDir);
+
+ // Set the SO PIN
+ virtual bool setSOPIN(const ByteString& soPINBlob) = 0;
+
+ // Get the SO PIN
+ virtual bool getSOPIN(ByteString& soPINBlob) = 0;
+
+ // Set the user PIN
+ virtual bool setUserPIN(ByteString userPINBlob) = 0;
+
+ // Get the user PIN
+ virtual bool getUserPIN(ByteString& userPINBlob) = 0;
+
+ // Get the token flags
+ virtual bool getTokenFlags(CK_ULONG& flags) = 0;
+
+ // Set the token flags
+ virtual bool setTokenFlags(const CK_ULONG flags) = 0;
+
+ // Retrieve the token label
+ virtual bool getTokenLabel(ByteString& label) = 0;
+
+ // Retrieve the token serial
+ virtual bool getTokenSerial(ByteString& serial) = 0;
+
+ // Retrieve objects
+ virtual std::set<OSObject*> getObjects() = 0;
+
+ // Insert objects into the given set
+ virtual void getObjects(std::set<OSObject*> &objects) = 0;
+
+ // Create a new object
+ virtual OSObject* createObject() = 0;
+
+ // Delete an object
+ virtual bool deleteObject(OSObject* object) = 0;
+
+ // Destructor
+ virtual ~ObjectStoreToken() {};
+
+ // Checks if the token is consistent
+ virtual bool isValid() = 0;
+
+ // Invalidate the token (for instance if it is deleted)
+ virtual void invalidate() = 0;
+
+ // Delete the token
+ virtual bool clearToken() = 0;
+
+ // Reset the token
+ virtual bool resetToken(const ByteString& label) = 0;
+};
+
+#endif // !_SOFTHSM_V2_OBJECTSTORETOKEN_H
+
diff --git a/SoftHSMv2/src/lib/object_store/SessionObject.cpp b/SoftHSMv2/src/lib/object_store/SessionObject.cpp
new file mode 100644
index 0000000..49dfa7d
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/SessionObject.cpp
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObject.cpp
+
+ This class implements session objects (i.e. objects that are non-persistent)
+ *****************************************************************************/
+
+#include "config.h"
+#include "SessionObject.h"
+#include "SessionObjectStore.h"
+
+// Constructor
+SessionObject::SessionObject(SessionObjectStore* inParent, CK_SLOT_ID inSlotID, CK_SESSION_HANDLE inHSession, bool inIsPrivate)
+{
+ hSession = inHSession;
+ slotID = inSlotID;
+ isPrivate = inIsPrivate;
+ objectMutex = MutexFactory::i()->getMutex();
+ valid = (objectMutex != NULL);
+ parent = inParent;
+}
+
+// Destructor
+SessionObject::~SessionObject()
+{
+ discardAttributes();
+
+ MutexFactory::i()->recycleMutex(objectMutex);
+}
+
+// Check if the specified attribute exists
+bool SessionObject::attributeExists(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ return valid && (attributes[type] != NULL);
+}
+
+// Retrieve the specified attribute
+OSAttribute SessionObject::getAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ OSAttribute* attr = attributes[type];
+ if (attr == NULL)
+ {
+ ERROR_MSG("The attribute does not exist: 0x%08X", type);
+ return OSAttribute((unsigned long)0);
+ }
+
+ return *attr;
+}
+
+bool SessionObject::getBooleanValue(CK_ATTRIBUTE_TYPE type, bool val)
+{
+ MutexLocker lock(objectMutex);
+
+ OSAttribute* attr = attributes[type];
+ if (attr == NULL)
+ {
+ ERROR_MSG("The attribute does not exist: 0x%08X", type);
+ return val;
+ }
+
+ if (attr->isBooleanAttribute())
+ {
+ return attr->getBooleanValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not a boolean: 0x%08X", type);
+ return val;
+ }
+}
+
+unsigned long SessionObject::getUnsignedLongValue(CK_ATTRIBUTE_TYPE type, unsigned long val)
+{
+ MutexLocker lock(objectMutex);
+
+ OSAttribute* attr = attributes[type];
+ if (attr == NULL)
+ {
+ ERROR_MSG("The attribute does not exist: 0x%08X", type);
+ return val;
+ }
+
+ if (attr->isUnsignedLongAttribute())
+ {
+ return attr->getUnsignedLongValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not an unsigned long: 0x%08X", type);
+ return val;
+ }
+}
+
+ByteString SessionObject::getByteStringValue(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ ByteString val;
+
+ OSAttribute* attr = attributes[type];
+ if (attr == NULL)
+ {
+ ERROR_MSG("The attribute does not exist: 0x%08X", type);
+ return val;
+ }
+
+ if (attr->isByteStringAttribute())
+ {
+ return attr->getByteStringValue();
+ }
+ else
+ {
+ ERROR_MSG("The attribute is not a byte string: 0x%08X", type);
+ return val;
+ }
+}
+
+// Retrieve the next attribute type
+CK_ATTRIBUTE_TYPE SessionObject::nextAttributeType(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*>::iterator n = attributes.upper_bound(type);
+
+ // skip null attributes
+ while ((n != attributes.end()) && (n->second == NULL))
+ ++n;
+
+
+ // return type or CKA_CLASS (= 0)
+ if (n == attributes.end())
+ {
+ return CKA_CLASS;
+ }
+ else
+ {
+ return n->first;
+ }
+}
+
+// Set the specified attribute
+bool SessionObject::setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute)
+{
+ MutexLocker lock(objectMutex);
+
+ if (!valid)
+ {
+ DEBUG_MSG("Cannot update invalid session object 0x%08X", this);
+
+ return false;
+ }
+
+ if (attributes[type] != NULL)
+ {
+ delete attributes[type];
+
+ attributes[type] = NULL;
+ }
+
+ attributes[type] = new OSAttribute(attribute);
+
+ return true;
+}
+
+// Delete the specified attribute
+bool SessionObject::deleteAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ MutexLocker lock(objectMutex);
+
+ if (!valid)
+ {
+ DEBUG_MSG("Cannot update invalid session object 0x%08X", this);
+
+ return false;
+ }
+
+ if (attributes[type] == NULL)
+ {
+ DEBUG_MSG("Cannot delete attribute that doesn't exist in object 0x%08X", this);
+
+ return false;
+ }
+
+ delete attributes[type];
+ attributes.erase(type);
+
+ return true;
+}
+
+// The validity state of the object
+bool SessionObject::isValid()
+{
+ return valid;
+}
+
+bool SessionObject::hasSlotID(CK_SLOT_ID inSlotID)
+{
+ return slotID == inSlotID;
+}
+
+// Called by the session object store when a session is closed. If it's the
+// session this object was associated with, the function returns true and the
+// object is invalidated
+bool SessionObject::removeOnSessionClose(CK_SESSION_HANDLE inHSession)
+{
+ if (hSession == inHSession)
+ {
+ // Save space
+ discardAttributes();
+
+ valid = false;
+
+ return true;
+ }
+
+ return false;
+}
+
+// Called by the session object store when a token is logged out.
+// Remove when this session object is a private object for this token.
+bool SessionObject::removeOnAllSessionsClose(CK_SLOT_ID inSlotID)
+{
+ if (slotID == inSlotID)
+ {
+ discardAttributes();
+
+ valid = false;
+
+ return true;
+ }
+
+ return false;
+}
+
+// Called by the session object store when a token is logged out.
+// Remove when this session object is a private object for this token.
+bool SessionObject::removeOnTokenLogout(CK_SLOT_ID inSlotID)
+{
+ if (slotID == inSlotID && isPrivate)
+ {
+ discardAttributes();
+
+ valid = false;
+
+ return true;
+ }
+
+ return false;
+}
+
+// Discard the object's attributes
+void SessionObject::discardAttributes()
+{
+ MutexLocker lock(objectMutex);
+
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*> cleanUp = attributes;
+ attributes.clear();
+
+ for (std::map<CK_ATTRIBUTE_TYPE, OSAttribute*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if (i->second == NULL)
+ {
+ continue;
+ }
+
+ delete i->second;
+ i->second = NULL;
+ }
+}
+
+// These functions are just stubs for session objects
+bool SessionObject::startTransaction(Access)
+{
+ return true;
+}
+
+bool SessionObject::commitTransaction()
+{
+ return true;
+}
+
+bool SessionObject::abortTransaction()
+{
+ return true;
+}
+
+bool SessionObject::destroyObject()
+{
+ if (parent == NULL)
+ {
+ ERROR_MSG("Cannot destroy object that is not associated with a session object store");
+
+ return false;
+ }
+
+ return parent->deleteObject(this);
+}
+
+// Invalidate the object
+void SessionObject::invalidate()
+{
+ valid = false;
+ discardAttributes();
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/SessionObject.h b/SoftHSMv2/src/lib/object_store/SessionObject.h
new file mode 100644
index 0000000..caadb64
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/SessionObject.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObject.h
+
+ This class implements session objects (i.e. objects that are non-persistent)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECT_H
+#define _SOFTHSM_V2_SESSIONOBJECT_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "OSAttribute.h"
+#include "MutexFactory.h"
+#include <string>
+#include <map>
+#include "cryptoki.h"
+#include "OSObject.h"
+
+// Forward declaration of the session object store
+class SessionObjectStore;
+
+class SessionObject : public OSObject
+{
+public:
+ // Constructor
+ SessionObject(SessionObjectStore* inParent, CK_SLOT_ID inSlotID, CK_SESSION_HANDLE inHSession, bool inIsPrivate = false);
+
+ // Destructor
+ virtual ~SessionObject();
+
+ // Check if the specified attribute exists
+ virtual bool attributeExists(CK_ATTRIBUTE_TYPE type);
+
+ // Retrieve the specified attribute
+ virtual OSAttribute getAttribute(CK_ATTRIBUTE_TYPE type);
+ virtual bool getBooleanValue(CK_ATTRIBUTE_TYPE type, bool val);
+ virtual unsigned long getUnsignedLongValue(CK_ATTRIBUTE_TYPE type, unsigned long val);
+ virtual ByteString getByteStringValue(CK_ATTRIBUTE_TYPE type);
+
+ // Retrieve the next attribute type
+ virtual CK_ATTRIBUTE_TYPE nextAttributeType(CK_ATTRIBUTE_TYPE type);
+
+ // Set the specified attribute
+ virtual bool setAttribute(CK_ATTRIBUTE_TYPE type, const OSAttribute& attribute);
+
+ // Delete the specified attribute
+ virtual bool deleteAttribute(CK_ATTRIBUTE_TYPE type);
+
+ // The validity state of the object
+ virtual bool isValid();
+
+ bool hasSlotID(CK_SLOT_ID inSlotID);
+
+ // Called by the session object store when a session is closed. If it's the
+ // session this object was associated with, the function returns true and the
+ // object is invalidated
+ bool removeOnSessionClose(CK_SESSION_HANDLE inHSession);
+
+ // Called by the session object store when all the sessions for a token
+ // have been closed.
+ bool removeOnAllSessionsClose(CK_SLOT_ID inSlotID);
+
+ // Called by the session object store when a token is logged out.
+ // Remove when this session object is a private object for this token.
+ bool removeOnTokenLogout(CK_SLOT_ID inSlotID);
+
+ // These functions are just stubs for session objects
+ virtual bool startTransaction(Access access);
+ virtual bool commitTransaction();
+ virtual bool abortTransaction();
+
+ // Destroys the object; WARNING: pointers to the object become invalid after this
+ // call!
+ virtual bool destroyObject();
+
+ // Invalidate the object
+ void invalidate();
+
+private:
+ // Discard the object's attributes
+ void discardAttributes();
+
+ // The object's raw attributes
+ std::map<CK_ATTRIBUTE_TYPE, OSAttribute*> attributes;
+
+ // The object's validity state
+ bool valid;
+
+ // Mutex object for thread-safeness
+ Mutex* objectMutex;
+
+ // The slotID of the object is associated with.
+ CK_SLOT_ID slotID;
+
+ // The session the object is associated with.
+ CK_SESSION_HANDLE hSession;
+
+ // Indicates whether this object is private
+ bool isPrivate;
+
+ // The parent SessionObjectStore
+ SessionObjectStore* parent;
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECT_H
+
diff --git a/SoftHSMv2/src/lib/object_store/SessionObjectStore.cpp b/SoftHSMv2/src/lib/object_store/SessionObjectStore.cpp
new file mode 100644
index 0000000..3370d20
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/SessionObjectStore.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStore.cpp
+
+ The token class; a token is stored in a directory containing several files.
+ Each object is stored in a separate file and a token object is present that
+ has the token specific attributes
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "OSAttributes.h"
+#include "OSAttribute.h"
+#include "SessionObject.h"
+#include "cryptoki.h"
+#include "SessionObjectStore.h"
+#include <vector>
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+
+// Constructor
+SessionObjectStore::SessionObjectStore()
+{
+ storeMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+SessionObjectStore::~SessionObjectStore()
+{
+ // Clean up
+ objects.clear();
+ std::set<SessionObject*> cleanUp = allObjects;
+ allObjects.clear();
+
+ for (std::set<SessionObject*>::iterator i = cleanUp.begin(); i != cleanUp.end(); i++)
+ {
+ if ((*i) == NULL) continue;
+
+ SessionObject* that = *i;
+ delete that;
+ }
+
+ MutexFactory::i()->recycleMutex(storeMutex);
+}
+
+// Retrieve objects
+std::set<SessionObject*> SessionObjectStore::getObjects()
+{
+ // Make sure that no other thread is in the process of changing
+ // the object list when we return it
+ MutexLocker lock(storeMutex);
+
+ return objects;
+}
+
+void SessionObjectStore::getObjects(CK_SLOT_ID slotID, std::set<OSObject*> &inObjects)
+{
+ // Make sure that no other thread is in the process of changing
+ // the object list when we return it
+ MutexLocker lock(storeMutex);
+
+ std::set<SessionObject*>::iterator it;
+ for (it=objects.begin(); it!=objects.end(); ++it) {
+ if ((*it)->hasSlotID(slotID))
+ inObjects.insert(*it);
+ }
+}
+
+// Create a new object
+SessionObject* SessionObjectStore::createObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate)
+{
+ // Create the new object file
+ SessionObject* newObject = new SessionObject(this, slotID, hSession, isPrivate);
+
+ if (!newObject->isValid())
+ {
+ ERROR_MSG("Failed to create new object");
+
+ delete newObject;
+
+ return NULL;
+ }
+
+ // Now add it to the set of objects
+ MutexLocker lock(storeMutex);
+
+ objects.insert(newObject);
+ allObjects.insert(newObject);
+
+ DEBUG_MSG("(0x%08X) Created new object (0x%08X)", this, newObject);
+
+ return newObject;
+}
+
+// Delete an object
+bool SessionObjectStore::deleteObject(SessionObject* object)
+{
+ if (objects.find(object) == objects.end())
+ {
+ ERROR_MSG("Cannot delete non-existent object 0x%08X", object);
+
+ return false;
+ }
+
+ MutexLocker lock(storeMutex);
+
+ // Invalidate the object instance
+ object->invalidate();
+
+ objects.erase(object);
+
+ return true;
+}
+
+// Indicate that a session has been closed; invalidates all objects
+// associated with this session
+void SessionObjectStore::sessionClosed(CK_SESSION_HANDLE hSession)
+{
+ MutexLocker lock(storeMutex);
+
+ std::set<SessionObject*> checkObjects = objects;
+
+ for (std::set<SessionObject*>::iterator i = checkObjects.begin(); i != checkObjects.end(); i++)
+ {
+ if ((*i)->removeOnSessionClose(hSession))
+ {
+ // Since the object remains in the allObjects set, any pointers to it will
+ // remain valid but it will no longer be returned when the set of objects
+ // is requested
+ objects.erase(*i);
+ }
+ }
+}
+
+void SessionObjectStore::allSessionsClosed(CK_SLOT_ID slotID)
+{
+ MutexLocker lock(storeMutex);
+
+ std::set<SessionObject*> checkObjects = objects;
+
+ for (std::set<SessionObject*>::iterator i = checkObjects.begin(); i != checkObjects.end(); i++)
+ {
+ if ((*i)->removeOnAllSessionsClose(slotID))
+ {
+ // Since the object remains in the allObjects set, any pointers to it will
+ // remain valid but it will no longer be returned when the set of objects
+ // is requested
+ objects.erase(*i);
+ }
+ }
+}
+
+void SessionObjectStore::tokenLoggedOut(CK_SLOT_ID slotID)
+{
+ MutexLocker lock(storeMutex);
+
+ std::set<SessionObject*> checkObjects = objects;
+
+ for (std::set<SessionObject*>::iterator i = checkObjects.begin(); i != checkObjects.end(); i++)
+ {
+ if ((*i)->removeOnTokenLogout(slotID))
+ {
+ // Since the object remains in the allObjects set, any pointers to it will
+ // remain valid but it will no longer be returned when the set of objects
+ // is requested
+ objects.erase(*i);
+ }
+ }
+}
+
+// Clear the whole store
+void SessionObjectStore::clearStore()
+{
+ MutexLocker lock(storeMutex);
+
+ objects.clear();
+ std::set<SessionObject*> clearObjects = allObjects;
+ allObjects.clear();
+
+ for (std::set<SessionObject*>::iterator i = clearObjects.begin(); i != clearObjects.end(); i++)
+ {
+ delete *i;
+ }
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/SessionObjectStore.h b/SoftHSMv2/src/lib/object_store/SessionObjectStore.h
new file mode 100644
index 0000000..2ec4bc5
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/SessionObjectStore.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStore.h
+
+ The token class; a token is stored in a directory containing several files.
+ Each object is stored in a separate file and a token object is present that
+ has the token specific attributes
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECTSTORE_H
+#define _SOFTHSM_V2_SESSIONOBJECTSTORE_H
+
+#include "config.h"
+#include "OSAttribute.h"
+#include "SessionObject.h"
+#include "MutexFactory.h"
+#include "cryptoki.h"
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+#include <memory>
+
+class SessionObjectStore
+{
+public:
+ // Constructor
+ SessionObjectStore();
+
+ // Retrieve objects
+ std::set<SessionObject*> getObjects();
+
+ // Insert the session objects for the given slotID into the given OSObject set
+ void getObjects(CK_SLOT_ID slotID, std::set<OSObject*> &inObjects);
+
+ // Create a new object
+ SessionObject* createObject(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, bool isPrivate = false);
+
+ // Delete an object
+ bool deleteObject(SessionObject* object);
+
+ // Indicate that a session has been closed; invalidates all objects
+ // associated with this session.
+ void sessionClosed(CK_SESSION_HANDLE hSession);
+
+ // Indicate that for a token all sessions have been closed.
+ // Invalidates all objects associated with the token.
+ void allSessionsClosed(CK_SLOT_ID slotID);
+
+ // Indicate that a token has been logged out; invalidates all private
+ // objects associated with this token.
+ void tokenLoggedOut(CK_SLOT_ID slotID);
+
+ // Destructor
+ virtual ~SessionObjectStore();
+
+ // Clears the store; should be called when all sessions are closed
+ void clearStore();
+
+private:
+ // The current objects in the store
+ std::set<SessionObject*> objects;
+
+ // All the objects ever kept in the store
+ std::set<SessionObject*> allObjects;
+
+ // The current list of files
+ std::set<std::string> currentFiles;
+
+ // For thread safeness
+ Mutex* storeMutex;
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECTSTORE_H
+
diff --git a/SoftHSMv2/src/lib/object_store/UUID.cpp b/SoftHSMv2/src/lib/object_store/UUID.cpp
new file mode 100644
index 0000000..9e9f541
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/UUID.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUID.cpp
+
+ UUID generation helper functions
+ *****************************************************************************/
+
+#include "config.h"
+#include "UUID.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
+// Generate a new UUID string
+std::string UUID::newUUID()
+{
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ ByteString uuid;
+
+ if (!rng->generateRandom(uuid, 16))
+ {
+ ERROR_MSG("Fatal, could not generate random UUID");
+
+ throw -1;
+ }
+
+ // Convert it to a string
+ char uuidStr[37];
+
+ sprintf(uuidStr, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5],
+ uuid[6], uuid[7],
+ uuid[8], uuid[9],
+ uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
+
+ return std::string(uuidStr);
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/UUID.h b/SoftHSMv2/src/lib/object_store/UUID.h
new file mode 100644
index 0000000..569bc00
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/UUID.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUID.h
+
+ UUID generation helper functions; for now, this just wraps the OSF/DCE's
+ UUID generation implementation, but if SoftHSM gets ported to non UNIX/BSD-
+ like OSes this may incorporate other implementations
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_UUID_H
+#define _SOFTHSM_V2_UUID_H
+
+#include "config.h"
+#include <string>
+
+namespace UUID
+{
+ // Generate a new UUID string
+ std::string newUUID();
+};
+
+#endif // !_SOFTHSM_V2_UUID_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.cpp b/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.cpp
new file mode 100644
index 0000000..2cc8360
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObjectStoreTests.cpp
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBObjectStoreTests.h"
+
+#include <cstdio>
+
+#ifndef HAVE_SQLITE3_H
+#error expected sqlite3 to be available
+#endif
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_newly_created_object_store);
+
+void test_a_newly_created_object_store::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+
+ ObjectStoreToken::selectBackend("db");
+
+ store = new ObjectStore("testdir");
+ nulltoken = NULL;
+}
+
+void test_a_newly_created_object_store::tearDown()
+{
+ delete store;
+
+ ObjectStoreToken::selectBackend("file");
+
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+
+void test_a_newly_created_object_store::contains_no_items()
+{
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)0);
+}
+
+void test_a_newly_created_object_store::can_create_a_new_token()
+{
+ ByteString label1 = "DEADC0FFEE";
+
+ ObjectStoreToken *token1 = store->newToken(label1);
+ CPPUNIT_ASSERT(token1 != nulltoken);
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)1);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_newly_created_object_store_containing_two_tokens);
+
+
+void test_a_newly_created_object_store_containing_two_tokens::setUp()
+{
+ test_a_newly_created_object_store::setUp();
+
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+
+ ObjectStoreToken* token1 = store->newToken(label1);
+ CPPUNIT_ASSERT(token1 != nulltoken);
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)1);
+
+ ObjectStoreToken* token2 = store->newToken(label2);
+ CPPUNIT_ASSERT(token2 != nulltoken);
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)2);
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::tearDown()
+{
+ ObjectStoreToken* token1 = store->getToken(0);
+ ObjectStoreToken* token2 = store->getToken(1);
+ CPPUNIT_ASSERT(store->destroyToken(token1));
+ CPPUNIT_ASSERT(store->destroyToken(token2));
+
+ test_a_newly_created_object_store::tearDown();
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::has_two_tokens()
+{
+ CPPUNIT_ASSERT_EQUAL(store->getTokenCount(), (size_t)2);
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::can_access_both_tokens()
+{
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* token1 = store->getToken(0);
+ ObjectStoreToken* token2 = store->getToken(1);
+
+ CPPUNIT_ASSERT(token1 != nulltoken);
+ CPPUNIT_ASSERT(token2 != nulltoken);
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::assigned_labels_correctly_to_tokens()
+{
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* token1 = store->getToken(0);
+ ObjectStoreToken* token2 = store->getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2;
+
+ CPPUNIT_ASSERT(token1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(token2->getTokenLabel(retrieveLabel2));
+
+ CPPUNIT_ASSERT(label1 == retrieveLabel1 || label1 == retrieveLabel2);
+ CPPUNIT_ASSERT(label2 == retrieveLabel1 || label2 == retrieveLabel2);
+ CPPUNIT_ASSERT(label1 != label2);
+}
+
+void test_a_newly_created_object_store_containing_two_tokens::assigned_a_unique_serial_number_to_each_token()
+{
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* token1 = store->getToken(0);
+ ObjectStoreToken* token2 = store->getToken(1);
+
+ ByteString retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(token1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(token2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+}
diff --git a/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.h b/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.h
new file mode 100644
index 0000000..7d100c8
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBObjectStoreTests.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObjectStoreTests.h
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBOBJECTSTORETESTS_H
+#define _SOFTHSM_V2_DBOBJECTSTORETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectStore.h"
+#include "ObjectStoreToken.h"
+
+class test_a_newly_created_object_store : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_a_newly_created_object_store);
+ CPPUNIT_TEST(contains_no_items);
+ CPPUNIT_TEST(can_create_a_new_token);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void contains_no_items();
+ void can_create_a_new_token();
+protected:
+ ObjectStore *store;
+ ObjectStoreToken *nulltoken;
+
+private:
+};
+
+class test_a_newly_created_object_store_containing_two_tokens : public test_a_newly_created_object_store
+{
+ CPPUNIT_TEST_SUITE(test_a_newly_created_object_store_containing_two_tokens);
+ CPPUNIT_TEST(has_two_tokens);
+ CPPUNIT_TEST(can_access_both_tokens);
+ CPPUNIT_TEST(assigned_labels_correctly_to_tokens);
+ CPPUNIT_TEST(assigned_a_unique_serial_number_to_each_token);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void has_two_tokens();
+ void can_access_both_tokens();
+ void assigned_labels_correctly_to_tokens();
+ void assigned_a_unique_serial_number_to_each_token();
+};
+
+#endif // !_SOFTHSM_V2_DBOBJECTSTORETESTS_H
diff --git a/SoftHSMv2/src/lib/object_store/test/DBObjectTests.cpp b/SoftHSMv2/src/lib/object_store/test/DBObjectTests.cpp
new file mode 100644
index 0000000..d856b06
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBObjectTests.cpp
@@ -0,0 +1,816 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObjectTests.cpp
+
+ Contains test cases to test the database token object implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBObjectTests.h"
+#include "DBObject.h"
+
+#include <cstdio>
+
+#ifndef HAVE_SQLITE3_H
+#error expected sqlite3 to be available
+#endif
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_dbobject);
+
+void test_a_dbobject::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ connection = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection != NULL);
+ CPPUNIT_ASSERT(connection->connect("<1>"));
+ connection->setBusyTimeout(10);
+
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.startTransaction(DBObject::ReadWrite));
+ CPPUNIT_ASSERT(testObject.createTables());
+ CPPUNIT_ASSERT(testObject.commitTransaction());
+
+ connection2 = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection2 != NULL);
+ CPPUNIT_ASSERT(connection2->connect("<2>"));
+ connection2->setBusyTimeout(10);
+}
+
+void test_a_dbobject::tearDown()
+{
+ CPPUNIT_ASSERT(connection != NULL);
+ connection->close();
+ delete connection;
+
+ CPPUNIT_ASSERT(connection2 != NULL);
+ connection2->close();
+ delete connection2;
+
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void test_a_dbobject::should_be_insertable()
+{
+ DBObject tokenObject(connection);
+ CPPUNIT_ASSERT(!tokenObject.isValid());
+ CPPUNIT_ASSERT(tokenObject.insert());
+ CPPUNIT_ASSERT(tokenObject.isValid());
+ CPPUNIT_ASSERT_EQUAL(tokenObject.objectId(), (long long)1);
+}
+
+void test_a_dbobject::should_be_selectable()
+{
+ should_be_insertable();
+
+ DBObject tokenObject(connection);
+ CPPUNIT_ASSERT(tokenObject.find(1));
+ CPPUNIT_ASSERT(tokenObject.isValid());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_dbobject_with_an_object);
+
+void test_a_dbobject_with_an_object::setUp()
+{
+ test_a_dbobject::setUp();
+ DBObject tokenObject(connection);
+ CPPUNIT_ASSERT(tokenObject.startTransaction(DBObject::ReadWrite));
+ CPPUNIT_ASSERT(!tokenObject.isValid());
+ CPPUNIT_ASSERT(tokenObject.insert());
+ CPPUNIT_ASSERT(tokenObject.isValid());
+ CPPUNIT_ASSERT_EQUAL(tokenObject.objectId(), (long long)1);
+ CPPUNIT_ASSERT(tokenObject.commitTransaction());
+
+}
+
+void test_a_dbobject_with_an_object::tearDown()
+{
+ test_a_dbobject::tearDown();
+}
+
+void test_a_dbobject_with_an_object::should_store_boolean_attributes()
+{
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ bool value2 = false;
+ bool value3 = true;
+ bool value4 = true;
+ bool value5 = false;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SENSITIVE, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_EXTRACTABLE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_NEVER_EXTRACTABLE, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr5));
+ }
+
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SENSITIVE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_NEVER_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue());
+ CPPUNIT_ASSERT(!testObject.getAttribute(CKA_SENSITIVE).getBooleanValue());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).getBooleanValue());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).getBooleanValue());
+ CPPUNIT_ASSERT(!testObject.getAttribute(CKA_SIGN).getBooleanValue());
+
+ bool value6 = true;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VERIFY, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).isBooleanAttribute());
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_VERIFY).getBooleanValue(), value6);
+ CPPUNIT_ASSERT_EQUAL(testObject.getBooleanValue(CKA_VERIFY, false), value6);
+ }
+}
+
+
+void test_a_dbobject_with_an_object::should_store_unsigned_long_attributes()
+{
+ // Add unsigned long attributes to the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ unsigned long value1 = 0x12345678;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0x01010101;
+ unsigned long value4 = 0x10101010;
+ unsigned long value5 = 0xABCDEF;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS_BITS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_AUTH_PIN_FLAGS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBPRIME_BITS, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_KEY_TYPE, attr5));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_AUTH_PIN_FLAGS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBPRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_KEY_TYPE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).isUnsignedLongAttribute());
+
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_MODULUS_BITS).getUnsignedLongValue(), (unsigned long)0x12345678);
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue(), (unsigned long)0x87654321);
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).getUnsignedLongValue(), (unsigned long)0x01010101);
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_SUBPRIME_BITS).getUnsignedLongValue(), (unsigned long)0x10101010);
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_KEY_TYPE).getUnsignedLongValue(), (unsigned long)0xABCDEF);
+
+ unsigned long value6 = 0x90909090;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_CLASS, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_CLASS).getUnsignedLongValue(), value6);
+ CPPUNIT_ASSERT_EQUAL(testObject.getUnsignedLongValue(CKA_CLASS, 0x0), value6);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_binary_attributes()
+{
+ ByteString value1 = "010203040506070809";
+ ByteString value2 = "ABABABABABABABABABABABABABABABABAB";
+ unsigned long value3 = 0xBDED;
+ ByteString value4 = "98A7E5D798A7E5D798A7E5D798A7E5D798A7E5D798A7E5D7";
+ ByteString value5 = "ABCDABCDABCDABCDABCDABCDABCDABCD";
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_COEFFICIENT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PUBLIC_EXPONENT, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr5));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_COEFFICIENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PUBLIC_EXPONENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).getByteStringValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value5);
+
+ ByteString value6 = "909090908080808080807070707070FF";
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ISSUER, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getByteStringValue(CKA_ISSUER) == value6);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_mechtypeset_attributes()
+{
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ std::set<CK_MECHANISM_TYPE> set;
+ set.insert(CKM_SHA256);
+ set.insert(CKM_SHA512);
+ OSAttribute attr(set);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ std::set<CK_MECHANISM_TYPE> retrieved =
+ testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue();
+
+ CPPUNIT_ASSERT(retrieved.size() == 2);
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA256) != retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA384) == retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA512) != retrieved.end());
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_attrmap_attributes()
+{
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattr;
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_TOKEN, attr1));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_PRIME_BITS, attr2));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_VALUE, attr3));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_ALLOWED_MECHANISMS, attr4));
+ OSAttribute attra(mattr);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_WRAP_TEMPLATE, attra));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_WRAP_TEMPLATE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_UNWRAP_TEMPLATE));
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattrb =
+ testObject.getAttribute(CKA_WRAP_TEMPLATE).getAttributeMapValue();
+ CPPUNIT_ASSERT(mattrb.size() == 4);
+ CPPUNIT_ASSERT(mattrb.find(CKA_TOKEN) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(mattrb.find(CKA_PRIME_BITS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(mattrb.find(CKA_VALUE) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(mattrb.find(CKA_ALLOWED_MECHANISMS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_mixed_attributes()
+{
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0xBDEBDBED;
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue());
+ CPPUNIT_ASSERT_EQUAL(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue(), value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_store_double_attributes()
+{
+ bool value1 = true;
+ bool value1a = false;
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue());
+
+ OSAttribute attr1(value1a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
+ }
+
+ // Now re-read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
+ }
+}
+
+void test_a_dbobject_with_an_object::can_refresh_attributes()
+{
+ bool value1 = true;
+ bool value1a = false;
+ ByteString value2 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value2a = "466487346943785684957634";
+ ByteString value3 = "0102010201020102010201020102010201020102";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+ std::set<CK_MECHANISM_TYPE> value4a;
+ value4a.insert(CKM_SHA384);
+ value4a.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ OSAttribute attr1(value1a);
+ OSAttribute attr2(value2a);
+ OSAttribute attr4(value4a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Open the object a second time
+ DBObject testObject2(connection);
+ CPPUNIT_ASSERT(testObject2.find(1));
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check the attributes on the second instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SIGN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SIGN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_SUBJECT).getByteStringValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Add an attribute on the second object
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr3));
+
+ // Check the attribute
+ CPPUNIT_ASSERT(testObject2.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value3);
+
+ // Now check that the first instance also knows about it
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value3);
+ }
+}
+
+void test_a_dbobject_with_an_object::should_cleanup_statements_during_transactions()
+{
+ // Create an object for accessing object 1 on the first connection.
+ DBObject testObject(connection);
+ // check transaction start(ro)/abort sequence
+ CPPUNIT_ASSERT(testObject.startTransaction(OSObject::ReadOnly));
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+ CPPUNIT_ASSERT(testObject.abortTransaction());
+}
+
+void test_a_dbobject_with_an_object::should_use_transactions()
+{
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0xBDEBDBED;
+ ByteString value4 = "AAAAAAAAAAAAAAAFFFFFFFFFFFFFFF";
+ std::set<CK_MECHANISM_TYPE> value5;
+ value5.insert(CKM_SHA256);
+ value5.insert(CKM_SHA512);
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr5));
+
+ // Create secondary instance for the same object.
+ // This needs to have a different connection to the database to simulate
+ // another process accessing the data.
+ DBObject testObject2(connection2);
+ CPPUNIT_ASSERT(testObject2.find(1));
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check that it has the same attributes
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // Check that the attributes have the same values as set on testObject.
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5);
+
+ // New values
+ bool value1a = false;
+ unsigned long value2a = 0x12345678;
+ unsigned long value3a = 0xABABABAB;
+ ByteString value4a = "EDEDEDEDEDEDEDEDEDEDEDEDEDEDED";
+ std::set<CK_MECHANISM_TYPE> value5a;
+ value5a.insert(CKM_SHA384);
+ value5a.insert(CKM_SHA512);
+
+ OSAttribute attr1a(value1a);
+ OSAttribute attr2a(value2a);
+ OSAttribute attr3a(value3a);
+ OSAttribute attr4a(value4a);
+ OSAttribute attr5a(value5a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction(DBObject::ReadWrite));
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr5a));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5a);
+
+ // Verify that they are unchanged on the other instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5);
+
+ // Commit the transaction
+ CPPUNIT_ASSERT(testObject.commitTransaction());
+
+ // Verify that non-modifiable attributes did not propagate but modifiable attributes
+ // have now changed on the other instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // NOTE: 3 attributes below cannot be modified after creation and therefore are not required to propagate.
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() != value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() != value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() != value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() != value5a);
+
+ // CKA_ID attribute can be modified after creation and therefore should have propagated.
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == value4a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction(DBObject::ReadWrite));
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ID, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr5));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5);
+
+ // Create a fresh third instance for the same object to force the data to be retrieved from the database.
+ DBObject testObject3(connection2);
+ CPPUNIT_ASSERT(testObject3.find(1));
+ CPPUNIT_ASSERT(testObject3.isValid());
+
+ // Verify that they are unchanged on the other instance, while the transaction is still in progress.
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // Verify that the attributes from the database are still hodling the same value as when the transaction started.
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).getByteStringValue() == value4a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5a);
+
+ // Abort the transaction
+ CPPUNIT_ASSERT(testObject.abortTransaction());
+
+ // Verify that after aborting the transaction the values in testObject have reverted back to their
+ // original state.
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // After aborting a transaction the testObject should be back to pre transaction state.
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == value4a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5a);
+
+ // Verify that testObject3 still has the original values.
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ // Verify that testObject3 still has the original values.
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_VALUE_BITS).getUnsignedLongValue() == value3a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ID).getByteStringValue() == value4a);
+ CPPUNIT_ASSERT(testObject3.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value5a);
+}
+
+void test_a_dbobject_with_an_object::should_fail_to_delete()
+{
+ DBObject testObject(connection);
+ CPPUNIT_ASSERT(testObject.find(1));
+ CPPUNIT_ASSERT(testObject.isValid());
+ // We don't attach the object to a token, and therefore should not be able to destroy it.
+ CPPUNIT_ASSERT(!testObject.destroyObject());
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/DBObjectTests.h b/SoftHSMv2/src/lib/object_store/test/DBObjectTests.h
new file mode 100644
index 0000000..136fa81
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBObjectTests.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBObjectTests.h
+
+ Contains test cases to test the database token object implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBOBJECTTESTS_H
+#define _SOFTHSM_V2_DBOBJECTTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "DB.h"
+
+class test_a_dbobject : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_a_dbobject);
+ CPPUNIT_TEST(should_be_insertable);
+ CPPUNIT_TEST(should_be_selectable);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void should_be_insertable();
+ void should_be_selectable();
+
+protected:
+ DB::Connection *connection;
+ DB::Connection *connection2;
+
+private:
+};
+
+class test_a_dbobject_with_an_object : public test_a_dbobject
+{
+ CPPUNIT_TEST_SUITE(test_a_dbobject_with_an_object);
+ CPPUNIT_TEST(should_store_boolean_attributes);
+ CPPUNIT_TEST(should_store_unsigned_long_attributes);
+ CPPUNIT_TEST(should_store_binary_attributes);
+ CPPUNIT_TEST(should_store_mechtypeset_attributes);
+ CPPUNIT_TEST(should_store_attrmap_attributes);
+ CPPUNIT_TEST(should_store_mixed_attributes);
+ CPPUNIT_TEST(should_store_double_attributes);
+ CPPUNIT_TEST(can_refresh_attributes);
+ CPPUNIT_TEST(should_cleanup_statements_during_transactions);
+ CPPUNIT_TEST(should_use_transactions);
+ CPPUNIT_TEST(should_fail_to_delete);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void should_store_boolean_attributes();
+ void should_store_unsigned_long_attributes();
+ void should_store_binary_attributes();
+ void should_store_mechtypeset_attributes();
+ void should_store_attrmap_attributes();
+ void should_store_mixed_attributes();
+ void should_store_double_attributes();
+ void can_refresh_attributes();
+ void should_cleanup_statements_during_transactions();
+ void should_use_transactions();
+ void should_fail_to_delete();
+};
+
+#endif // !_SOFTHSM_V2_DBOBJECTTESTS_H
diff --git a/SoftHSMv2/src/lib/object_store/test/DBTests.cpp b/SoftHSMv2/src/lib/object_store/test/DBTests.cpp
new file mode 100644
index 0000000..d787a83
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBTests.cpp
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBTests.cpp
+
+ Contains lowest level test cases for the database backend implementation.
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_db);
+
+static int dummy_print(const char *, va_list )
+{
+ return 0;
+}
+
+void test_a_db::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ null = NULL;
+}
+
+void test_a_db::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void test_a_db::checks_for_empty_connection_parameters()
+{
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+
+ DB::Connection *connection = DB::Connection::Create("","TestToken");
+ CPPUNIT_ASSERT_EQUAL(connection, null);
+
+ connection = DB::Connection::Create("testdir","");
+ CPPUNIT_ASSERT_EQUAL(connection, null);
+
+ connection = DB::Connection::Create("","");
+ CPPUNIT_ASSERT_EQUAL(connection, null);
+
+ DB::setLogErrorHandler(eh);
+}
+
+void test_a_db::can_be_connected_to_database()
+{
+
+ DB::Connection *connection = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection != null);
+ bool isConnected = connection->connect();
+ delete connection;
+ CPPUNIT_ASSERT(isConnected);
+#ifndef _WIN32
+ CPPUNIT_ASSERT_EQUAL(system("test -f ./testdir/TestToken"), 0);
+#else
+ CPPUNIT_ASSERT(GetFileAttributes("testdir\\TestToken") != INVALID_FILE_ATTRIBUTES);
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_db_with_a_connection);
+
+void test_a_db_with_a_connection::setUp()
+{
+ test_a_db::setUp();
+ connection = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection != null);
+ CPPUNIT_ASSERT(connection->connect());
+}
+
+void test_a_db_with_a_connection::tearDown()
+{
+ CPPUNIT_ASSERT(connection != null);
+ connection->close();
+ delete connection;
+ test_a_db::tearDown();
+}
+
+void test_a_db_with_a_connection::can_prepare_statements()
+{
+ DB::Statement statement = connection->prepare("PRAGMA database_list;");
+ CPPUNIT_ASSERT(statement.isValid());
+}
+
+void test_a_db_with_a_connection::can_perform_statements()
+{
+ DB::Statement statement = connection->prepare("PRAGMA database_list;");
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+ // only expect a single row in the result, so nextRow should now fail
+ CPPUNIT_ASSERT(!result.nextRow());
+}
+
+void test_a_db_with_a_connection::maintains_correct_refcounts()
+{
+ DB::Statement statement = connection->prepare("PRAGMA database_list;");
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 1);
+ {
+ DB::Statement statement1 = statement;
+ DB::Statement statement2 = statement;
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 3);
+ CPPUNIT_ASSERT(statement1.isValid());
+ CPPUNIT_ASSERT(statement2.isValid());
+ }
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 1);
+
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // Statement is referenced by the result because it provides the query record cursor state.
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 2);
+
+ result = DB::Result();
+ CPPUNIT_ASSERT_EQUAL(statement.refcount(), 1);
+}
+void test_a_db_with_a_connection::can_create_tables()
+{
+ CPPUNIT_ASSERT(!connection->tableExists("object"));
+ DB::Statement cr_object = connection->prepare("create table object (id integer primary key autoincrement);");
+ CPPUNIT_ASSERT(connection->execute(cr_object));
+ CPPUNIT_ASSERT(connection->tableExists("object"));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_db_with_a_connection_with_tables);
+
+void test_a_db_with_a_connection_with_tables::setUp()
+{
+ test_a_db_with_a_connection::setUp();
+ can_create_tables();
+
+ // attribute_text
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_text"));
+ DB::Statement cr_attr_text = connection->prepare(
+ "create table attribute_text ("
+ "value text,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_text));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_text"));
+
+ // attribute_integer
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_integer"));
+ DB::Statement cr_attr_integer = connection->prepare(
+ "create table attribute_integer ("
+ "value integer,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_integer));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_integer"));
+
+ // attribute_blob
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_blob"));
+ DB::Statement cr_attr_blob = connection->prepare(
+ "create table attribute_blob ("
+ "value blob,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_blob));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_blob"));
+
+ // attribute_boolean
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_boolean"));
+ DB::Statement cr_attr_boolean = connection->prepare(
+ "create table attribute_boolean ("
+ "value boolean,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_boolean));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_boolean"));
+
+ // attribute_datetime
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_datetime"));
+ DB::Statement cr_attr_datetime = connection->prepare(
+ "create table attribute_datetime ("
+ "value datetime,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_datetime));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_datetime"));
+
+ // attribute_real
+ CPPUNIT_ASSERT(!connection->tableExists("attribute_real"));
+ DB::Statement cr_attr_real = connection->prepare(
+ "create table attribute_real ("
+ "value real,"
+ "type integer,"
+ "object_id integer references object(id) on delete cascade,"
+ "id integer primary key autoincrement)"
+ );
+ CPPUNIT_ASSERT(connection->execute(cr_attr_real));
+ CPPUNIT_ASSERT(connection->tableExists("attribute_real"));
+}
+
+void test_a_db_with_a_connection_with_tables::tearDown()
+{
+ test_a_db_with_a_connection::tearDown();
+}
+
+void test_a_db_with_a_connection_with_tables::can_insert_records()
+{
+ DB::Statement statement = connection->prepare("insert into object default values");
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ statement = connection->prepare(
+ "insert into attribute_text (value,type,object_id) values ('%s',%d,%lld)",
+ "testing testing testing",
+ 1234,
+ object_id);
+ CPPUNIT_ASSERT(connection->execute(statement));
+}
+
+void test_a_db_with_a_connection_with_tables::can_retrieve_records()
+{
+ can_insert_records();
+
+ DB::Statement statement = connection->prepare(
+ "select value from attribute_text as t where t.type=%d",
+ 1234);
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT_EQUAL(std::string(result.getString(1)), std::string("testing testing testing"));
+}
+
+void test_a_db_with_a_connection_with_tables::can_cascade_delete_objects_and_attributes()
+{
+ can_insert_records();
+
+ DB::Statement statement = connection->prepare("select id from object");
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ long long object_id = result.getLongLong(1);
+
+ statement = connection->prepare("delete from object where id=%lld",object_id);
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ statement = connection->prepare("select * from attribute_text where object_id=%lld",object_id);
+ result = connection->perform(statement);
+
+ // Check cascade delete was successful.
+ CPPUNIT_ASSERT(!result.isValid());
+}
+
+
+void test_a_db_with_a_connection_with_tables::can_update_text_attribute()
+{
+ can_insert_records();
+
+ // query all objects
+ DB::Statement statement = connection->prepare("select id from object");
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ long long object_id = result.getLongLong(1); // field indices start at 1
+
+ statement = connection->prepare(
+ "update attribute_text set value='test test test' where type=%d and object_id=%lld",
+ 1234,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+}
+
+void test_a_db_with_a_connection_with_tables::can_update_text_attribute_bound_value()
+{
+ can_insert_records();
+
+ // query all objects
+ DB::Statement statement = connection->prepare("select id from object");
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ long long object_id = result.getLongLong(1); // field indices start at 1
+
+ statement = connection->prepare(
+ "update attribute_text set value=? where type=%d and object_id=%lld",
+ 1234,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ std::string msg("testing quote ' and accents é.");
+
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindText(1,msg.c_str(),msg.size(),NULL));
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ statement = connection->prepare(
+ "select value from attribute_text as t where t.type=%d and t.object_id=%lld",
+ 1234,
+ object_id);
+ result = connection->perform(statement);
+ CPPUNIT_ASSERT_EQUAL(std::string(result.getString(1)), msg);
+}
+
+void test_a_db_with_a_connection_with_tables::can_update_integer_attribute_bound_value()
+{
+ // insert new object
+ DB::Statement statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // insert integer attribute
+ statement = connection->prepare(
+ "insert into attribute_integer (value,type,object_id) values (%lld,%d,%lld)",
+ 1111,
+ 1235,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // prepare update integer attribute statement
+ statement = connection->prepare(
+ "update attribute_integer set value=? where type=%d and object_id=%lld",
+ 1235,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ // bind long long value to the parameter an update the record
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindInt64(1,2222));
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // Retrieve the value from the record
+ DB::Statement retrieveStmt = connection->prepare(
+ "select value from attribute_integer as t where t.type=%d and t.object_id=%lld",
+ 1235,
+ object_id);
+ CPPUNIT_ASSERT(retrieveStmt.isValid());
+ DB::Result result = connection->perform(retrieveStmt);
+ CPPUNIT_ASSERT_EQUAL(result.getLongLong(1), (long long)2222);
+
+ // verify that binding to a parameter before resetting the statement will fail.
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+ DB::Bindings bindings(statement);
+ CPPUNIT_ASSERT(!bindings.bindInt(1,3333));
+ DB::setLogErrorHandler(eh);
+
+ // reset statement and bind another value to the statement
+ CPPUNIT_ASSERT(bindings.reset());
+ CPPUNIT_ASSERT(bindings.bindInt(1,3333));
+
+ // perform the update statement again with the newly bound value
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // reset the retrieve statement and perform it again to get the latest value of the integer attribute
+ CPPUNIT_ASSERT(retrieveStmt.reset());
+ result = connection->perform(retrieveStmt);
+ CPPUNIT_ASSERT(result.isValid());
+ CPPUNIT_ASSERT_EQUAL(result.getLongLong(1), (long long)3333);
+}
+
+void test_a_db_with_a_connection_with_tables::can_update_blob_attribute_bound_value()
+{
+ // insert new object
+ DB::Statement statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // insert blob attribute
+ statement = connection->prepare(
+ "insert into attribute_blob (value,type,object_id) values (X'012345',%d,%lld)",
+ 1236,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // prepare update blob attribute statement
+ statement = connection->prepare(
+ "update attribute_blob set value=? where type=%d and object_id=%lld",
+ 1236,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ // bind blob (with embedded zero!) to the parameter
+ const char data[] = {10,11,0,12,13,14,15,16};
+ std::string msg(data,sizeof(data));
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindBlob(1,msg.data(),msg.size(),NULL));
+
+ // update the blob value of the attribute
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // retrieve the blob value from the attribute
+ statement = connection->prepare(
+ "select value from attribute_blob as t where t.type=%d and t.object_id=%lld",
+ 1236,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // check that the retrieved blob value matches the original data.
+ CPPUNIT_ASSERT_EQUAL(result.getFieldLength(1), sizeof(data));
+ std::string msgstored((const char *)result.getBinary(1),result.getFieldLength(1));
+ CPPUNIT_ASSERT_EQUAL(msg, msgstored);
+}
+
+
+void test_a_db_with_a_connection_with_tables::will_not_insert_non_existing_attribute_on_update()
+{
+ DB::Statement statement;
+ DB::Result result;
+
+ // Insert new object
+ statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // Updating an attribute before it is created will succeed, but will not insert an attribute.
+ statement = connection->prepare(
+ "update attribute_boolean set value=1 where type=%d and object_id=%lld",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // Retrieve the boolean value from the attribute should fail
+ statement = connection->prepare(
+ "select value from attribute_boolean as t where t.type=%d and t.object_id=%lld",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ result = connection->perform(statement);
+ CPPUNIT_ASSERT(!result.isValid());
+}
+
+
+void test_a_db_with_a_connection_with_tables::can_update_boolean_attribute_bound_value()
+{
+ //SQLite doesn't have a boolean data type, use 0 (false) and 1 (true)
+
+ DB::Statement statement;
+ DB::Result result;
+
+ // Insert new object
+ statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // insert boolean attribute
+ statement = connection->prepare(
+ "insert into attribute_boolean (value,type,object_id) values (1,%d,%lld)",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // prepare update boolean attribute statement
+ statement = connection->prepare(
+ "update attribute_boolean set value=? where type=%d and object_id=%lld",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ // Bind 0 (false) to the first parameter
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindInt(1,0));
+
+ // Execute the statement to update the attribute value.
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // Retrieve the boolean value from the attribute
+ statement = connection->prepare(
+ "select value from attribute_boolean as t where t.type=%d and t.object_id=%lld",
+ 1237,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // check that the retrieved value matches the original value
+ CPPUNIT_ASSERT_EQUAL(result.getInt(1), 0);
+}
+
+
+void test_a_db_with_a_connection_with_tables::can_update_real_attribute_bound_value()
+{
+ // insert new object
+ DB::Statement statement = connection->prepare(
+ "insert into object default values");
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+ long long object_id = connection->lastInsertRowId();
+ CPPUNIT_ASSERT(object_id != 0);
+
+ // insert real value
+ statement = connection->prepare(
+ "insert into attribute_real (value,type,object_id) values(%f,%d,%lld)",
+ 1.238,
+ 1238,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // prepare update real attribute statement
+ statement = connection->prepare(
+ "update attribute_real set value=? where type=%d and object_id=%lld",
+ 1238,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+
+ // Bind 3333.3333 to the first parameter
+ CPPUNIT_ASSERT(DB::Bindings(statement).bindDouble(1,3333.3333));
+
+ // Execute the statement to update the attribute value
+ CPPUNIT_ASSERT(connection->execute(statement));
+
+ // Retrieve the double value from the attribute
+ statement = connection->prepare(
+ "select value from attribute_real as t where t.type=%d and t.object_id=%lld",
+ 1238,
+ object_id);
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // check that the retrieved value matches the original value.
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(result.getDouble(1), 3333.3333, 0.00001);
+}
+
+void test_a_db_with_a_connection_with_tables::supports_transactions()
+{
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+ CPPUNIT_ASSERT(!connection->rollbackTransaction());
+ DB::setLogErrorHandler(eh);
+
+ CPPUNIT_ASSERT(connection->beginTransactionRW());
+ CPPUNIT_ASSERT(connection->rollbackTransaction());
+
+ eh = DB::setLogErrorHandler(dummy_print);
+ CPPUNIT_ASSERT(!connection->commitTransaction());
+ DB::setLogErrorHandler(eh);
+
+ CPPUNIT_ASSERT(connection->beginTransactionRW());
+ can_update_real_attribute_bound_value();
+ CPPUNIT_ASSERT(connection->commitTransaction());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_db_with_a_connection_with_tables_with_a_second_connection_open);
+
+void test_a_db_with_a_connection_with_tables_with_a_second_connection_open::setUp()
+{
+ test_a_db_with_a_connection_with_tables::setUp();
+ connection2 = DB::Connection::Create("testdir","TestToken");
+ CPPUNIT_ASSERT(connection2 != null);
+ CPPUNIT_ASSERT(connection2->connect());
+ connection2->setBusyTimeout(10);
+}
+
+void test_a_db_with_a_connection_with_tables_with_a_second_connection_open::tearDown()
+{
+ CPPUNIT_ASSERT(connection2 != null);
+ connection2->close();
+ delete connection2;
+ test_a_db_with_a_connection_with_tables::tearDown();
+}
+
+void test_a_db_with_a_connection_with_tables_with_a_second_connection_open::handles_nested_transactions()
+{
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+
+ DB::Connection *connection1 = connection;
+
+ CPPUNIT_ASSERT(connection1->beginTransactionRW());
+
+ CPPUNIT_ASSERT(connection2->beginTransactionRO());
+ CPPUNIT_ASSERT(connection2->rollbackTransaction());
+ CPPUNIT_ASSERT(!connection2->beginTransactionRW());
+
+ CPPUNIT_ASSERT(connection1->commitTransaction());
+
+ DB::setLogErrorHandler(eh);
+}
+
+
+void test_a_db_with_a_connection_with_tables_with_a_second_connection_open::supports_transactions_with_other_connections_open()
+{
+ CPPUNIT_ASSERT(connection2->beginTransactionRO());
+
+ supports_transactions();
+
+ // Retrieve the double value from the attribute
+ DB::Statement statement = connection2->prepare(
+ "select value from attribute_real as t where t.type=%d and t.object_id=%lld",
+ 1238,
+ connection->lastInsertRowId());
+ CPPUNIT_ASSERT(statement.isValid());
+ DB::Result result = connection2->perform(statement);
+ CPPUNIT_ASSERT(result.isValid());
+
+ // check that the retrieved value matches the original value.
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(result.getDouble(1), 3333.3333, 0.00001);
+
+ CPPUNIT_ASSERT(connection2->commitTransaction());
+}
diff --git a/SoftHSMv2/src/lib/object_store/test/DBTests.h b/SoftHSMv2/src/lib/object_store/test/DBTests.h
new file mode 100644
index 0000000..422cbce
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBTests.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBTests.h
+
+ Contains lowest level test cases for the database backend implementation.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBTESTS_H
+#define _SOFTHSM_V2_DBTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "DB.h"
+
+class test_a_db : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_a_db);
+ CPPUNIT_TEST(checks_for_empty_connection_parameters);
+ CPPUNIT_TEST(can_be_connected_to_database);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void checks_for_empty_connection_parameters();
+ void can_be_connected_to_database();
+
+ void setUp();
+ void tearDown();
+
+protected:
+ DB::Connection *null;
+
+private:
+};
+
+class test_a_db_with_a_connection : public test_a_db
+{
+ CPPUNIT_TEST_SUITE(test_a_db_with_a_connection);
+ CPPUNIT_TEST(can_prepare_statements);
+ CPPUNIT_TEST(can_perform_statements);
+ CPPUNIT_TEST(maintains_correct_refcounts);
+ CPPUNIT_TEST(can_create_tables);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp();
+ void tearDown();
+
+ void can_prepare_statements();
+ void can_perform_statements();
+ void maintains_correct_refcounts();
+ void can_create_tables();
+protected:
+ DB::Connection *connection;
+
+private:
+};
+
+class test_a_db_with_a_connection_with_tables : public test_a_db_with_a_connection
+{
+ CPPUNIT_TEST_SUITE(test_a_db_with_a_connection_with_tables);
+ CPPUNIT_TEST(can_insert_records);
+ CPPUNIT_TEST(can_retrieve_records);
+ CPPUNIT_TEST(can_cascade_delete_objects_and_attributes);
+ CPPUNIT_TEST(can_update_text_attribute);
+ CPPUNIT_TEST(can_update_text_attribute_bound_value);
+ CPPUNIT_TEST(can_update_integer_attribute_bound_value);
+ CPPUNIT_TEST(can_update_blob_attribute_bound_value);
+ CPPUNIT_TEST(will_not_insert_non_existing_attribute_on_update);
+ CPPUNIT_TEST(can_update_boolean_attribute_bound_value);
+ CPPUNIT_TEST(can_update_real_attribute_bound_value);
+ CPPUNIT_TEST(supports_transactions);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp();
+ void tearDown();
+
+ void can_insert_records();
+ void can_retrieve_records();
+ void can_cascade_delete_objects_and_attributes();
+ void can_update_text_attribute();
+ void can_update_text_attribute_bound_value();
+ void can_update_integer_attribute_bound_value();
+ void can_update_blob_attribute_bound_value();
+ void will_not_insert_non_existing_attribute_on_update();
+ void can_update_boolean_attribute_bound_value();
+ void can_update_real_attribute_bound_value();
+ void supports_transactions();
+protected:
+
+private:
+};
+
+class test_a_db_with_a_connection_with_tables_with_a_second_connection_open : public test_a_db_with_a_connection_with_tables
+{
+ CPPUNIT_TEST_SUITE(test_a_db_with_a_connection_with_tables_with_a_second_connection_open);
+ CPPUNIT_TEST(handles_nested_transactions);
+ CPPUNIT_TEST(supports_transactions_with_other_connections_open);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp();
+ void tearDown();
+
+ void handles_nested_transactions();
+ void supports_transactions_with_other_connections_open();
+protected:
+ DB::Connection *connection2;
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_DBTESTS_H
diff --git a/SoftHSMv2/src/lib/object_store/test/DBTokenTests.cpp b/SoftHSMv2/src/lib/object_store/test/DBTokenTests.cpp
new file mode 100644
index 0000000..ab0cff1
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBTokenTests.cpp
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBTokenTests.cpp
+
+ Contains test cases to test the database token implementation
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBTokenTests.h"
+#include "DBToken.h"
+#include "DB.h"
+
+#include <cstdio>
+
+#ifndef HAVE_SQLITE3_H
+#error expected sqlite3 to be available
+#endif
+
+CPPUNIT_TEST_SUITE_REGISTRATION(test_a_dbtoken);
+
+static int dummy_print(const char *, va_list )
+{
+ return 0;
+}
+
+void test_a_dbtoken::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void test_a_dbtoken::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void test_a_dbtoken::should_be_creatable()
+{
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+ ObjectStoreToken* newToken = new DBToken("testdir", "newToken", label, serial);
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ CPPUNIT_ASSERT(newToken->isValid());
+
+ delete newToken;
+}
+
+void test_a_dbtoken::should_support_pin_setting_getting()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+ ObjectStoreToken* newToken = new DBToken("testdir", "newToken", label, serial);
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ CPPUNIT_ASSERT(newToken->isValid());
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)( CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED));
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ delete newToken;
+
+ // Now reopen the newly created token
+ DBToken reopenedToken("testdir","newToken");
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+}
+
+void test_a_dbtoken::should_allow_object_enumeration()
+{
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+ ByteString soPIN = "31323334"; // 1234
+ ByteString userPIN = "30303030"; // 0000
+ ByteString id[3] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB" };
+
+ {
+ // Instantiate a new token
+ ObjectStoreToken* newToken = new DBToken("testdir", "existingToken", label, serial);
+ CPPUNIT_ASSERT(newToken != NULL);
+ CPPUNIT_ASSERT(newToken->isValid());
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ // Test IDs
+ OSAttribute idAtt[3] = { id[0], id[1], id[2] };
+
+ // Create 3 objects on the token
+ OSObject* obj1 = newToken->createObject();
+ CPPUNIT_ASSERT(obj1 != NULL);
+ OSObject* obj2 = newToken->createObject();
+ CPPUNIT_ASSERT(obj2 != NULL);
+ OSObject* obj3 = newToken->createObject();
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->startTransaction(OSObject::ReadWrite);
+ CPPUNIT_ASSERT(obj1->setAttribute(CKA_ID, idAtt[0]));
+ obj1->commitTransaction();
+
+ obj2->startTransaction(OSObject::ReadWrite);
+ CPPUNIT_ASSERT(obj2->setAttribute(CKA_ID, idAtt[1]));
+ obj2->commitTransaction();
+
+ obj3->startTransaction(OSObject::ReadWrite);
+ CPPUNIT_ASSERT(obj3->setAttribute(CKA_ID, idAtt[2]));
+ obj3->commitTransaction();
+
+ delete newToken;
+ }
+
+ // Now open the token
+ DBToken existingToken("testdir","existingToken");
+
+ CPPUNIT_ASSERT(existingToken.isValid());
+
+ // Retrieve SO PIN, user PIN, label, serial number and flags
+ ByteString retrievedSOPIN, retrievedUserPIN, retrievedLabel, retrievedSerial;
+ CK_ULONG flags;
+
+ CPPUNIT_ASSERT(existingToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(existingToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(existingToken.getTokenLabel(retrievedLabel));
+ CPPUNIT_ASSERT(existingToken.getTokenSerial(retrievedSerial));
+ CPPUNIT_ASSERT(existingToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(retrievedLabel == label);
+ CPPUNIT_ASSERT(retrievedSerial == serial);
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT_EQUAL(existingToken.getObjects().size(), (size_t)3);
+
+ // Check that all the tokens are presented
+ bool present[3] = { false, false, false };
+ std::set<OSObject*> objects = existingToken.getObjects();
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present[0] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[1])
+ {
+ present[1] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present[2] = true;
+ }
+ }
+
+ CPPUNIT_ASSERT(present[0]);
+ CPPUNIT_ASSERT(present[1]);
+ CPPUNIT_ASSERT(present[2]);
+}
+
+void test_a_dbtoken::should_fail_to_open_nonexistant_tokens()
+{
+ DBToken doesntExist("testdir","doesntExist");
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+}
+
+void test_a_dbtoken::support_create_delete_objects()
+{
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+ ByteString label = "AABBCCDDEEFF";
+ ByteString serial = "1234567890";
+
+ // Instantiate a new token
+ ObjectStoreToken* testToken = new DBToken("testdir", "testToken", label, serial);
+ CPPUNIT_ASSERT(testToken != NULL);
+ CPPUNIT_ASSERT(testToken->isValid());
+
+ // Open the same token
+ DBToken sameToken("testdir","testToken");
+ CPPUNIT_ASSERT(sameToken.isValid());
+
+ // Create 3 objects on the token
+ OSObject* obj1 = testToken->createObject();
+ CPPUNIT_ASSERT(obj1 != NULL);
+ OSObject* obj2 = testToken->createObject();
+ CPPUNIT_ASSERT(obj2 != NULL);
+ OSObject* obj3 = testToken->createObject();
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT_EQUAL(testToken->getObjects().size(), (size_t)3);
+
+ // Check that all three objects are distinct and present
+ std::set<OSObject*> objects = testToken->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j]);
+ }
+
+ // Now check that the same objects are present in the other instance of the same token
+ std::set<OSObject*> otherObjects = sameToken.getObjects();
+ CPPUNIT_ASSERT_EQUAL(otherObjects.size(), (size_t)3);
+
+ bool present2[3] = { false, false, false };
+
+ for (std::set<OSObject*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present2[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present2[j]);
+ }
+
+ // Now delete the second object
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[1])
+ {
+ CPPUNIT_ASSERT(testToken->deleteObject(*i));
+ break;
+ }
+ }
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT_EQUAL(testToken->getObjects().size(),(size_t)2);
+
+ objects = testToken->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j]);
+ }
+
+ // Now check the other instance
+ CPPUNIT_ASSERT_EQUAL(sameToken.getObjects().size(), (size_t)2);
+
+ otherObjects = sameToken.getObjects();
+ bool present4[2] = { false, false };
+
+ for (std::set<OSObject*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present4[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present4[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present4[j]);
+ }
+
+
+ // Release the test token
+ delete testToken;
+}
+
+void test_a_dbtoken::support_clearing_a_token()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+ ObjectStoreToken* newToken = new DBToken("testdir", "newToken", label, serial);
+
+ CPPUNIT_ASSERT(newToken != NULL);
+ CPPUNIT_ASSERT(newToken->isValid());
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED));
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ CPPUNIT_ASSERT(newToken->createObject() != NULL);
+
+ delete newToken;
+
+#if 1
+ // Reopen the newly created token and keep a reference around.
+ DBToken referencingToken("testdir", "newToken");
+ CPPUNIT_ASSERT(referencingToken.isValid());
+#endif
+ // Now reopen the newly created token
+ DBToken reopenedToken("testdir","newToken");
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ // Now reset the token
+ CPPUNIT_ASSERT(reopenedToken.resetToken(label));
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(!reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT_EQUAL(flags, (CK_ULONG)(CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED));
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Now clear the token
+ CPPUNIT_ASSERT(reopenedToken.clearToken());
+ CPPUNIT_ASSERT(!reopenedToken.isValid());
+
+ DB::LogErrorHandler eh = DB::setLogErrorHandler(dummy_print);
+
+ // Try to open it once more and make sure it has been deleted.
+ DBToken clearedToken("testdir","newToken");
+ CPPUNIT_ASSERT(!clearedToken.isValid());
+
+#if 1
+ // Verify that it is no longer possible to access the database...
+ CPPUNIT_ASSERT(!referencingToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+
+ std::set<OSObject *> objects = referencingToken.getObjects();
+ CPPUNIT_ASSERT_EQUAL(objects.size(), (size_t)0);
+
+ CPPUNIT_ASSERT(!referencingToken.isValid());
+#endif
+
+ DB::setLogErrorHandler(eh);
+}
diff --git a/SoftHSMv2/src/lib/object_store/test/DBTokenTests.h b/SoftHSMv2/src/lib/object_store/test/DBTokenTests.h
new file mode 100644
index 0000000..de25195
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DBTokenTests.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DBTokenTests.h
+
+ Contains test cases to test the database token implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DBTOKENTESTS_H
+#define _SOFTHSM_V2_DBTOKENTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "DBToken.h"
+
+class test_a_dbtoken : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(test_a_dbtoken);
+ CPPUNIT_TEST(should_be_creatable);
+ CPPUNIT_TEST(should_support_pin_setting_getting);
+ CPPUNIT_TEST(should_allow_object_enumeration);
+ CPPUNIT_TEST(should_fail_to_open_nonexistant_tokens);
+ CPPUNIT_TEST(support_create_delete_objects);
+ CPPUNIT_TEST(support_clearing_a_token);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void should_be_creatable();
+ void should_support_pin_setting_getting();
+ void should_allow_object_enumeration();
+ void should_fail_to_open_nonexistant_tokens();
+ void support_create_delete_objects();
+ void support_clearing_a_token();
+
+protected:
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_DBTOKENTESTS_H
diff --git a/SoftHSMv2/src/lib/object_store/test/DirectoryTests.cpp b/SoftHSMv2/src/lib/object_store/test/DirectoryTests.cpp
new file mode 100644
index 0000000..2b56a5a
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DirectoryTests.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DirectoryTests.cpp
+
+ Contains test cases to test the directory implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "DirectoryTests.h"
+#include "Directory.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DirectoryTests);
+
+void DirectoryTests::setUp()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir2"));
+ CPPUNIT_ASSERT(!system("mkdir testdir/anotherdir3"));
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/afile"));
+ CPPUNIT_ASSERT(!system("echo someOtherStuff > testdir/anotherFile"));
+ CPPUNIT_ASSERT(!system("echo justStuff > testdir/justaFile"));
+#else
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir\\anotherdir"));
+ CPPUNIT_ASSERT(!system("mkdir testdir\\anotherdir2"));
+ CPPUNIT_ASSERT(!system("mkdir testdir\\anotherdir3"));
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir\\afile"));
+ CPPUNIT_ASSERT(!system("echo someOtherStuff > testdir\\anotherFile"));
+ CPPUNIT_ASSERT(!system("echo justStuff > testdir\\justaFile"));
+#endif
+}
+
+void DirectoryTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void DirectoryTests::testDirectory()
+{
+#ifndef _WIN32
+ Directory testdir("./testdir");
+#else
+ Directory testdir(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(testdir.isValid());
+
+ std::vector<std::string> files = testdir.getFiles();
+ std::vector<std::string> subDirs = testdir.getSubDirs();
+
+ CPPUNIT_ASSERT(files.size() == 3);
+ CPPUNIT_ASSERT(subDirs.size() == 3);
+
+ CPPUNIT_ASSERT(testdir.refresh());
+
+ CPPUNIT_ASSERT(files.size() == 3);
+ CPPUNIT_ASSERT(subDirs.size() == 3);
+
+ bool fileSeen[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare("afile"))
+ {
+ fileSeen[0] = true;
+ }
+ else if (!i->compare("anotherFile"))
+ {
+ fileSeen[1] = true;
+ }
+ else if (!i->compare("justaFile"))
+ {
+ fileSeen[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(fileSeen[0] && fileSeen[1] && fileSeen[2]);
+
+ bool dirSeen[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen[0] = true;
+ }
+ else if (!i->compare("anotherdir2"))
+ {
+ dirSeen[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen[0] && dirSeen[1] && dirSeen[2]);
+
+ // Create a directory
+ CPPUNIT_ASSERT(testdir.mkdir("newDir"));
+
+ subDirs = testdir.getSubDirs();
+
+ bool dirSeen2[4] = { false, false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen2[0] = true;
+ }
+ else if (!i->compare("anotherdir2"))
+ {
+ dirSeen2[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen2[2] = true;
+ }
+ else if (!i->compare("newDir"))
+ {
+ dirSeen2[3] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen2[0] && dirSeen2[1] && dirSeen2[2] && dirSeen2[3]);
+
+ // Remove a directory
+ CPPUNIT_ASSERT(testdir.rmdir("anotherdir2", true));
+
+ subDirs = testdir.getSubDirs();
+
+ bool dirSeen3[3] = { false, false, false };
+
+ for (std::vector<std::string>::iterator i = subDirs.begin(); i != subDirs.end(); i++)
+ {
+ if (!i->compare("anotherdir"))
+ {
+ dirSeen3[0] = true;
+ }
+ else if (!i->compare("newDir"))
+ {
+ dirSeen3[1] = true;
+ }
+ else if (!i->compare("anotherdir3"))
+ {
+ dirSeen3[2] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(dirSeen3[0] && dirSeen3[1] && dirSeen3[2]);
+
+ // Remove a file
+ CPPUNIT_ASSERT(testdir.remove("anotherFile"));
+
+ files = testdir.getFiles();
+
+ bool fileSeen2[2] = { false, false };
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare("afile"))
+ {
+ fileSeen2[0] = true;
+ }
+ else if (!i->compare("justaFile"))
+ {
+ fileSeen2[1] = true;
+ }
+ else
+ {
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ CPPUNIT_ASSERT(fileSeen2[0] && fileSeen2[1]);
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/DirectoryTests.h b/SoftHSMv2/src/lib/object_store/test/DirectoryTests.h
new file mode 100644
index 0000000..777f1a8
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/DirectoryTests.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DirectoryTests.h
+
+ Contains test cases to test the Directory implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DIRECTORYTESTS_H
+#define _SOFTHSM_V2_DIRECTORYTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class DirectoryTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(DirectoryTests);
+ CPPUNIT_TEST(testDirectory);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testDirectory();
+
+ void setUp();
+ void tearDown();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_DIRECTORYTESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/FileTests.cpp b/SoftHSMv2/src/lib/object_store/test/FileTests.cpp
new file mode 100644
index 0000000..9ac0979
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/FileTests.cpp
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FileTests.cpp
+
+ Contains test cases to test the file implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "FileTests.h"
+#include "File.h"
+#include "Directory.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FileTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void FileTests::setUp()
+{
+#ifndef _WIN32
+ int rv = system("rm -rf testdir");
+#else
+ int rv = system("rmdir /s /q testdir 2> nul");
+#endif
+ (void) rv;
+
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void FileTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void FileTests::testExistNotExist()
+{
+ // Test pre-condition
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+
+ // Attempt to open a file known not to exist
+#ifndef _WIN32
+ File doesntExist("testdir/nonExistentFile");
+#else
+ File doesntExist("testdir\\nonExistentFile");
+#endif
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+
+ // Attempt to open a file known to exist
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/existingFile"));
+#else
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir\\existingFile"));
+#endif
+ CPPUNIT_ASSERT(exists("existingFile"));
+
+#ifndef _WIN32
+ File exists("testdir/existingFile");
+#else
+ File exists("testdir\\existingFile");
+#endif
+
+ CPPUNIT_ASSERT(exists.isValid());
+}
+
+void FileTests::testCreateNotCreate()
+{
+ // Test pre-condition
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+ CPPUNIT_ASSERT(!exists("nonExistentFile2"));
+
+ // Attempt to open a file known not to exist
+#ifndef _WIN32
+ File doesntExist("testdir/nonExistentFile", true, true, false);
+#else
+ File doesntExist("testdir\\nonExistentFile", true, true, false);
+#endif
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+ CPPUNIT_ASSERT(!exists("nonExistentFile"));
+
+ // Attempt to open a file known not to exist in create mode
+#ifndef _WIN32
+ File willBeCreated("testdir/nonExistentFile2", true, true, true);
+#else
+ File willBeCreated("testdir\\nonExistentFile2", true, true, true);
+#endif
+
+ CPPUNIT_ASSERT(willBeCreated.isValid());
+ CPPUNIT_ASSERT(exists("nonExistentFile2"));
+}
+
+void FileTests::testLockUnlock()
+{
+ // Create pre-condition
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir/existingFile"));
+#else
+ CPPUNIT_ASSERT(!system("echo someStuff > testdir\\existingFile"));
+#endif
+ CPPUNIT_ASSERT(exists("existingFile"));
+
+#ifndef _WIN32
+ File file1("testdir/existingFile");
+ File file2("testdir/existingFile");
+#else
+ File file1("testdir\\existingFile");
+ File file2("testdir\\existingFile");
+#endif
+
+ CPPUNIT_ASSERT(file1.lock(false));
+ CPPUNIT_ASSERT(!file1.lock(false));
+ CPPUNIT_ASSERT(file2.lock(false));
+ CPPUNIT_ASSERT(file2.unlock());
+ CPPUNIT_ASSERT(file1.unlock());
+ CPPUNIT_ASSERT(file1.lock());
+ CPPUNIT_ASSERT(file2.lock());
+ CPPUNIT_ASSERT(file2.unlock());
+ CPPUNIT_ASSERT(file1.unlock());
+}
+
+void FileTests::testWriteRead()
+{
+ // Generate some test data
+ RNG* rng = CryptoFactory::i()->getRNG();
+
+ ByteString testData1;
+
+ CPPUNIT_ASSERT(rng->generateRandom(testData1, 187));
+
+ // More test data
+ std::string testString = "This is a test of the File class";
+ std::set<CK_MECHANISM_TYPE> testSet;
+ testSet.insert(CKM_RSA_PKCS);
+ testSet.insert(CKM_SHA256_RSA_PKCS);
+
+ // Create a file for writing
+ {
+#ifndef _WIN32
+ File newFile("testdir/newFile", false, true);
+#else
+ File newFile("testdir\\newFile", false, true);
+#endif
+
+ CPPUNIT_ASSERT(newFile.isValid());
+
+ // Write two booleans into the file
+ CPPUNIT_ASSERT(newFile.writeBool(true));
+ CPPUNIT_ASSERT(newFile.writeBool(false));
+
+ // Write an ulong into the file
+ CPPUNIT_ASSERT(newFile.writeULong(0x12345678));
+
+ // Write a ByteString into the file
+ CPPUNIT_ASSERT(newFile.writeByteString(testData1));
+
+ // Write a string into the file
+ CPPUNIT_ASSERT(newFile.writeString(testString));
+
+ // Write a set into the file
+ CPPUNIT_ASSERT(newFile.writeMechanismTypeSet(testSet));
+ }
+
+ CPPUNIT_ASSERT(exists("newFile"));
+
+ // Read the created file back
+ {
+#ifndef _WIN32
+ File newFile("testdir/newFile");
+#else
+ File newFile("testdir\\newFile");
+#endif
+
+ CPPUNIT_ASSERT(newFile.isValid());
+
+ // Read back the two booleans
+ bool b1, b2;
+
+ CPPUNIT_ASSERT(newFile.readBool(b1) && newFile.readBool(b2));
+ CPPUNIT_ASSERT(b1 && !b2);
+
+ // Read back the ulong
+ unsigned long ulongValue;
+
+ CPPUNIT_ASSERT(newFile.readULong(ulongValue));
+ CPPUNIT_ASSERT(ulongValue == 0x12345678);
+
+ // Read back the byte string
+ ByteString bsValue;
+
+ CPPUNIT_ASSERT(newFile.readByteString(bsValue));
+ CPPUNIT_ASSERT(bsValue == testData1);
+
+ // Read back the string value
+ std::string stringVal;
+
+ CPPUNIT_ASSERT(newFile.readString(stringVal));
+ CPPUNIT_ASSERT(!testString.compare(stringVal));
+
+ // Read back the set value
+ std::set<CK_MECHANISM_TYPE> setVal;
+
+ CPPUNIT_ASSERT(newFile.readMechanismTypeSet(setVal));
+ CPPUNIT_ASSERT(setVal == testSet);
+
+ // Check for EOF
+ CPPUNIT_ASSERT(!newFile.readBool(b1));
+ CPPUNIT_ASSERT(newFile.isEOF());
+ }
+}
+
+void FileTests::testSeek()
+{
+ ByteString t1 = "112233445566778899"; // 9 long
+ ByteString t2 = "AABBCCDDEEFFAABBCCDDEEFF"; // 12 long
+
+ {
+ // Create the test file
+#ifndef _WIN32
+ File testFile("testdir/testFile", false, true, true);
+#else
+ File testFile("testdir\\testFile", false, true, true);
+#endif
+
+ CPPUNIT_ASSERT(testFile.isValid());
+
+ // Write the test data to the test file
+ CPPUNIT_ASSERT(testFile.writeByteString(t1) && testFile.writeByteString(t2));
+ }
+
+ // Open the test file for reading
+#ifndef _WIN32
+ File testFile("testdir/testFile");
+#else
+ File testFile("testdir\\testFile");
+#endif
+
+ CPPUNIT_ASSERT(testFile.isValid());
+
+ // First, read back the test data
+ ByteString tr1, tr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(tr1) && testFile.readByteString(tr2));
+ CPPUNIT_ASSERT(tr1 == t1);
+ CPPUNIT_ASSERT(tr2 == t2);
+
+ // Seek to the length field of the second byte string
+ CPPUNIT_ASSERT(testFile.seek(8+9));
+
+ // Read back the size as an ulong value
+ unsigned long value;
+ unsigned long expectedValue = (unsigned long)0x1122334455667788ULL;
+
+ CPPUNIT_ASSERT(testFile.readULong(value));
+ CPPUNIT_ASSERT(value == 12);
+
+ // Seek to the start of the first byte string's data
+ CPPUNIT_ASSERT(testFile.seek(8));
+
+ // Read back the ulong value stored there
+ CPPUNIT_ASSERT(testFile.readULong(value));
+
+ CPPUNIT_ASSERT(value == expectedValue);
+
+ // Seek to the start of second byte string
+ CPPUNIT_ASSERT(testFile.seek(8+9));
+
+ // Read it
+ ByteString trr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(trr2));
+ CPPUNIT_ASSERT(trr2 == t2);
+
+ // Rewind the file
+ CPPUNIT_ASSERT(testFile.rewind());
+
+ // Read back both byte strings
+ ByteString trrr1, trrr2;
+
+ CPPUNIT_ASSERT(testFile.readByteString(trrr1) && testFile.readByteString(trrr2));
+ CPPUNIT_ASSERT(trrr1 == t1);
+ CPPUNIT_ASSERT(trrr2 == t2);
+}
+
+bool FileTests::exists(std::string name)
+{
+#ifndef _WIN32
+ Directory dir("./testdir");
+#else
+ Directory dir(".\\testdir");
+#endif
+
+
+ CPPUNIT_ASSERT(dir.isValid());
+
+ std::vector<std::string> files = dir.getFiles();
+
+ for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); i++)
+ {
+ if (!i->compare(name))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/FileTests.h b/SoftHSMv2/src/lib/object_store/test/FileTests.h
new file mode 100644
index 0000000..0b87f26
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/FileTests.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ FileTests.h
+
+ Contains test cases to test the File implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_FILETESTS_H
+#define _SOFTHSM_V2_FILETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class FileTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(FileTests);
+ CPPUNIT_TEST(testExistNotExist);
+ CPPUNIT_TEST(testCreateNotCreate);
+ CPPUNIT_TEST(testLockUnlock);
+ CPPUNIT_TEST(testWriteRead);
+ CPPUNIT_TEST(testSeek);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testExistNotExist();
+ void testCreateNotCreate();
+ void testLockUnlock();
+ void testWriteRead();
+ void testSeek();
+
+ void setUp();
+ void tearDown();
+
+private:
+ bool exists(std::string path);
+};
+
+#endif // !_SOFTHSM_V2_FILETESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/Makefile.am b/SoftHSMv2/src/lib/object_store/test/Makefile.am
new file mode 100644
index 0000000..71de7dd
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/Makefile.am
@@ -0,0 +1,39 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../pkcs11 \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ @CPPUNIT_CFLAGS@ \
+ @CRYPTO_INCLUDES@
+
+check_PROGRAMS = objstoretest
+
+objstoretest_SOURCES = objstoretest.cpp \
+ DirectoryTests.cpp \
+ UUIDTests.cpp \
+ FileTests.cpp \
+ ObjectFileTests.cpp \
+ OSTokenTests.cpp \
+ ObjectStoreTests.cpp \
+ SessionObjectTests.cpp \
+ SessionObjectStoreTests.cpp
+
+if BUILD_OBJECTSTORE_BACKEND_DB
+objstoretest_SOURCES += DBTests.cpp \
+ DBObjectTests.cpp \
+ DBTokenTests.cpp \
+ DBObjectStoreTests.cpp
+endif
+
+objstoretest_LDADD = ../../libsofthsm_convarch.la
+
+objstoretest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install -pthread
+
+TESTS = objstoretest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/object_store/test/OSTokenTests.cpp b/SoftHSMv2/src/lib/object_store/test/OSTokenTests.cpp
new file mode 100644
index 0000000..5afd583
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/OSTokenTests.cpp
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSTokenTests.cpp
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "OSTokenTests.h"
+#include "OSToken.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(OSTokenTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void OSTokenTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void OSTokenTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void OSTokenTests::testNewToken()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+#ifndef _WIN32
+ OSToken* newToken = OSToken::createToken("./testdir", "newToken", label, serial);
+#else
+ OSToken* newToken = OSToken::createToken(".\\testdir", "newToken", label, serial);
+#endif
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED));
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ delete newToken;
+
+ // Now reopen the newly created token
+#ifndef _WIN32
+ OSToken reopenedToken("./testdir/newToken");
+#else
+ OSToken reopenedToken(".\\testdir\\newToken");
+#endif
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+}
+
+void OSTokenTests::testExistingToken()
+{
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+ ByteString soPIN = "31323334"; // 1234
+ ByteString userPIN = "30303030"; // 0000
+ ByteString id1 = "ABCDEF";
+ ByteString id2 = "FEDCBA";
+ ByteString id3 = "AABBCC";
+
+ {
+ // Create the token dir
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("mkdir testdir/existingToken"));
+#else
+ CPPUNIT_ASSERT(!system("mkdir testdir\\existingToken"));
+#endif
+
+ // Create the token object
+#ifndef _WIN32
+ ObjectFile tokenObject(NULL, "./testdir/existingToken/token.object", "./testdir/existingToken/token.lock", true);
+#else
+ ObjectFile tokenObject(NULL, ".\\testdir\\existingToken\\token.object", ".\\testdir\\existingToken\\token.lock", true);
+#endif
+
+ OSAttribute labelAtt(label);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENLABEL, labelAtt));
+ OSAttribute serialAtt(serial);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENSERIAL, serialAtt));
+ OSAttribute soPINAtt(soPIN);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_SOPIN, soPINAtt));
+ OSAttribute userPINAtt(userPIN);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_USERPIN, userPINAtt));
+ CK_ULONG flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED;
+ OSAttribute flagsAtt(flags);
+ CPPUNIT_ASSERT(tokenObject.setAttribute(CKA_OS_TOKENFLAGS, flagsAtt));
+
+ // Create 3 objects
+#ifndef _WIN32
+ ObjectFile obj1(NULL, "./testdir/existingToken/1.object", "./testdir/existingToken/1.lock", true);
+ ObjectFile obj2(NULL, "./testdir/existingToken/2.object", "./testdir/existingToken/2.lock", true);
+ ObjectFile obj3(NULL, "./testdir/existingToken/3.object", "./testdir/existingToken/3.lock", true);
+#else
+ ObjectFile obj1(NULL, ".\\testdir\\existingToken\\1.object", ".\\testdir\\existingToken\\1.lock", true);
+ ObjectFile obj2(NULL, ".\\testdir\\existingToken\\2.object", ".\\testdir\\existingToken\\2.lock", true);
+ ObjectFile obj3(NULL, ".\\testdir\\existingToken\\3.object", ".\\testdir\\existingToken\\3.lock", true);
+#endif
+
+ OSAttribute id1Att(id1);
+ OSAttribute id2Att(id2);
+ OSAttribute id3Att(id3);
+
+ CPPUNIT_ASSERT(obj1.setAttribute(CKA_ID, id1));
+ CPPUNIT_ASSERT(obj2.setAttribute(CKA_ID, id2));
+ CPPUNIT_ASSERT(obj3.setAttribute(CKA_ID, id3));
+ }
+
+ // Now open the token
+#ifndef _WIN32
+ OSToken existingToken("./testdir/existingToken");
+#else
+ OSToken existingToken(".\\testdir\\existingToken");
+#endif
+
+
+ CPPUNIT_ASSERT(existingToken.isValid());
+
+ // Retrieve SO PIN, user PIN, label, serial number and flags
+ ByteString retrievedSOPIN, retrievedUserPIN, retrievedLabel, retrievedSerial;
+ CK_ULONG flags;
+
+ CPPUNIT_ASSERT(existingToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(existingToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(existingToken.getTokenLabel(retrievedLabel));
+ CPPUNIT_ASSERT(existingToken.getTokenSerial(retrievedSerial));
+ CPPUNIT_ASSERT(existingToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(retrievedLabel == label);
+ CPPUNIT_ASSERT(retrievedSerial == serial);
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT(existingToken.getObjects().size() == 3);
+
+ // Check that all the tokens are presented
+ bool present[3] = { false, false, false };
+ std::set<OSObject*> objects = existingToken.getObjects();
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id1)
+ {
+ present[0] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id2)
+ {
+ present[1] = true;
+ }
+ else if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id3)
+ {
+ present[2] = true;
+ }
+ }
+
+ CPPUNIT_ASSERT(present[0] == true);
+ CPPUNIT_ASSERT(present[1] == true);
+ CPPUNIT_ASSERT(present[2] == true);
+}
+
+void OSTokenTests::testNonExistentToken()
+{
+#ifndef _WIN32
+ OSToken doesntExist("./testdir/doesntExist");
+#else
+ OSToken doesntExist(".\\testdir\\doesntExist");
+#endif
+
+ CPPUNIT_ASSERT(!doesntExist.isValid());
+}
+
+void OSTokenTests::testCreateDeleteObjects()
+{
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+ ByteString label = "AABBCCDDEEFF";
+ ByteString serial = "1234567890";
+
+ // Instantiate a new token
+#ifndef _WIN32
+ OSToken* testToken = OSToken::createToken("./testdir", "testToken", label, serial);
+#else
+ OSToken* testToken = OSToken::createToken(".\\testdir", "testToken", label, serial);
+#endif
+
+ CPPUNIT_ASSERT(testToken != NULL);
+ CPPUNIT_ASSERT(testToken->isValid());
+
+ // Open the same token
+#ifndef _WIN32
+ OSToken sameToken("./testdir/testToken");
+#else
+ OSToken sameToken(".\\testdir\\testToken");
+#endif
+
+ CPPUNIT_ASSERT(sameToken.isValid());
+
+ // Create 3 objects on the token
+ OSObject* obj1 = testToken->createObject();
+ CPPUNIT_ASSERT(obj1 != NULL);
+ OSObject* obj2 = testToken->createObject();
+ CPPUNIT_ASSERT(obj2 != NULL);
+ OSObject* obj3 = testToken->createObject();
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the token contains 3 objects
+ CPPUNIT_ASSERT(testToken->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<OSObject*> objects = testToken->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now check that the same objects are present in the other instance of the same token
+ std::set<OSObject*> otherObjects = sameToken.getObjects();
+ CPPUNIT_ASSERT(otherObjects.size() == 3);
+
+ bool present2[3] = { false, false, false };
+
+ for (std::set<OSObject*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present2[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present2[j] == true);
+ }
+
+ // Now delete the second object
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[1])
+ {
+ CPPUNIT_ASSERT(testToken->deleteObject(*i));
+ break;
+ }
+ }
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(testToken->getObjects().size() == 2);
+
+ objects = testToken->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+
+ // Now check the other instance
+ CPPUNIT_ASSERT(sameToken.getObjects().size() == 2);
+
+ otherObjects = sameToken.getObjects();
+ bool present4[2] = { false, false };
+
+ for (std::set<OSObject*>::iterator i = otherObjects.begin(); i != otherObjects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present4[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present4[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present4[j] == true);
+ }
+
+
+ // Release the test token
+ delete testToken;
+}
+
+void OSTokenTests::testClearToken()
+{
+ // Create a new token
+ ByteString label = "40414243"; // ABCD
+ ByteString serial = "0102030405060708";
+
+#ifndef _WIN32
+ OSToken* newToken = OSToken::createToken("./testdir", "newToken", label, serial);
+#else
+ OSToken* newToken = OSToken::createToken(".\\testdir", "newToken", label, serial);
+#endif
+
+ CPPUNIT_ASSERT(newToken != NULL);
+
+ // Check the flags
+ CK_ULONG flags;
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED));
+
+ // Set the SO PIN
+ ByteString soPIN = "3132333435363738"; // 12345678
+
+ CPPUNIT_ASSERT(newToken->setSOPIN(soPIN));
+
+ // Set the user PIN
+ ByteString userPIN = "31323334"; // 1234
+
+ CPPUNIT_ASSERT(newToken->setUserPIN(userPIN));
+
+ CPPUNIT_ASSERT(newToken->getTokenFlags(flags));
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ delete newToken;
+
+ // Now reopen the newly created token
+#ifndef _WIN32
+ OSToken reopenedToken("./testdir/newToken");
+#else
+ OSToken reopenedToken(".\\testdir\\newToken");
+#endif
+
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Retrieve the flags, user PIN and so PIN
+ ByteString retrievedSOPIN, retrievedUserPIN;
+
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(retrievedUserPIN == userPIN);
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED));
+
+ // Now reset the token
+ CPPUNIT_ASSERT(reopenedToken.resetToken(label));
+ CPPUNIT_ASSERT(reopenedToken.getSOPIN(retrievedSOPIN));
+ CPPUNIT_ASSERT(!reopenedToken.getUserPIN(retrievedUserPIN));
+ CPPUNIT_ASSERT(reopenedToken.getTokenFlags(flags));
+ CPPUNIT_ASSERT(retrievedSOPIN == soPIN);
+ CPPUNIT_ASSERT(flags == (CKF_RNG | CKF_LOGIN_REQUIRED | CKF_RESTORE_KEY_NOT_NEEDED | CKF_TOKEN_INITIALIZED));
+ CPPUNIT_ASSERT(reopenedToken.isValid());
+
+ // Now clear the token
+ CPPUNIT_ASSERT(reopenedToken.clearToken());
+ CPPUNIT_ASSERT(!reopenedToken.isValid());
+
+ // Try to open it once more
+#ifndef _WIN32
+ OSToken clearedToken("./testdir/newToken");
+#else
+ OSToken clearedToken(".\\testdir\\newToken");
+#endif
+
+ CPPUNIT_ASSERT(!clearedToken.isValid());
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/OSTokenTests.h b/SoftHSMv2/src/lib/object_store/test/OSTokenTests.h
new file mode 100644
index 0000000..1155fcf
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/OSTokenTests.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSTokenTests.h
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSTOKENTESTS_H
+#define _SOFTHSM_V2_OSTOKENTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class OSTokenTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(OSTokenTests);
+ CPPUNIT_TEST(testNewToken);
+ CPPUNIT_TEST(testExistingToken);
+ CPPUNIT_TEST(testNonExistentToken);
+ CPPUNIT_TEST(testCreateDeleteObjects);
+ CPPUNIT_TEST(testClearToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testNewToken();
+ void testExistingToken();
+ void testNonExistentToken();
+ void testCreateDeleteObjects();
+ void testClearToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OSTOKENTESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.cpp b/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.cpp
new file mode 100644
index 0000000..9f0f5bd
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.cpp
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectObjectFileTests.cpp
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectFileTests.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectFileTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void ObjectFileTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void ObjectFileTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void ObjectFileTests::testBoolAttr()
+{
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ bool value2 = false;
+ bool value3 = true;
+ bool value4 = true;
+ bool value5 = false;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SENSITIVE, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_EXTRACTABLE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_NEVER_EXTRACTABLE, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr5));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SENSITIVE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_NEVER_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).getBooleanValue() == false);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == false);
+
+ bool value6 = true;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VERIFY, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).getBooleanValue() == value6);
+ CPPUNIT_ASSERT(testObject.getBooleanValue(CKA_VERIFY, false) == value6);
+ }
+}
+
+void ObjectFileTests::testULongAttr()
+{
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ unsigned long value1 = 0x12345678;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0x01010101;
+ unsigned long value4 = 0x10101010;
+ unsigned long value5 = 0xABCDEF;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS_BITS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_AUTH_PIN_FLAGS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBPRIME_BITS, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_KEY_TYPE, attr5));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_AUTH_PIN_FLAGS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBPRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_KEY_TYPE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).isUnsignedLongAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).getUnsignedLongValue() == 0x12345678);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).getUnsignedLongValue() == 0x01010101);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).getUnsignedLongValue() == 0x10101010);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).getUnsignedLongValue() == 0xABCDEF);
+
+ unsigned long value6 = 0x90909090;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_CLASS, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).getUnsignedLongValue() == value6);
+ CPPUNIT_ASSERT(testObject.getUnsignedLongValue(CKA_CLASS, 0x0) == value6);
+ }
+}
+
+void ObjectFileTests::testByteStrAttr()
+{
+ ByteString value1 = "010203040506070809";
+ ByteString value2 = "ABABABABABABABABABABABABABABABABAB";
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value4 = "98A7E5D798A7E5D798A7E5D798A7E5D798A7E5D798A7E5D7";
+ ByteString value5 = "ABCDABCDABCDABCDABCDABCDABCDABCD";
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_COEFFICIENT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PUBLIC_EXPONENT, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr5));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_COEFFICIENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PUBLIC_EXPONENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).getByteStringValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value5);
+
+ ByteString value6 = "909090908080808080807070707070FF";
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ISSUER, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getByteStringValue(CKA_ISSUER) == value6);
+ }
+}
+
+void ObjectFileTests::testMechTypeSetAttr()
+{
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ std::set<CK_MECHANISM_TYPE> set;
+ set.insert(CKM_SHA256);
+ set.insert(CKM_SHA512);
+ OSAttribute attr(set);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ std::set<CK_MECHANISM_TYPE> retrieved =
+ testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue();
+
+ CPPUNIT_ASSERT(retrieved.size() == 2);
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA256) != retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA384) == retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA512) != retrieved.end());
+ }
+}
+
+void ObjectFileTests::testAttrMapAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattr;
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_TOKEN, attr1));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_PRIME_BITS, attr2));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_VALUE, attr3));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_ALLOWED_MECHANISMS, attr4));
+ OSAttribute attra(mattr);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_WRAP_TEMPLATE, attra));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_WRAP_TEMPLATE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_UNWRAP_TEMPLATE));
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattrb =
+ testObject.getAttribute(CKA_WRAP_TEMPLATE).getAttributeMapValue();
+ CPPUNIT_ASSERT(mattrb.size() == 4);
+ CPPUNIT_ASSERT(mattrb.find(CKA_TOKEN) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(mattrb.find(CKA_PRIME_BITS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(mattrb.find(CKA_VALUE) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(mattrb.find(CKA_ALLOWED_MECHANISMS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+ }
+}
+
+void ObjectFileTests::testMixedAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+ }
+}
+
+void ObjectFileTests::testDoubleAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+ std::set<CK_MECHANISM_TYPE> value4a;
+ value4a.insert(CKM_SHA384);
+ value4a.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3a);
+ OSAttribute attr4(value4a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+ }
+
+ // Now re-read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+ }
+}
+
+void ObjectFileTests::testRefresh()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+ std::set<CK_MECHANISM_TYPE> value4a;
+ value4a.insert(CKM_SHA384);
+ value4a.insert(CKM_SHA512);
+
+ // Create the test object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+ }
+
+ // Now read back the object
+ {
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ bool value1 = false;
+ unsigned long value2 = 0x76767676;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3a);
+ OSAttribute attr4(value4a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Open the object a second time
+#ifndef _WIN32
+ ObjectFile testObject2(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject2(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check the attributes on the second instance
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Add an attribute on the second object
+ ByteString id = "0102010201020102010201020102010201020102";
+
+ OSAttribute attr5(id);
+
+ CPPUNIT_ASSERT(testObject2.setAttribute(CKA_ID, attr5));
+
+ // Check the attribute
+ CPPUNIT_ASSERT(testObject2.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ID).getByteStringValue() == id);
+
+ // Now check that the first instance also knows about it
+ CPPUNIT_ASSERT(testObject.isValid());
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ID));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ID).getByteStringValue() == id);
+
+ // Now change another attribute
+ unsigned long value2a = 0x89898989;
+
+ OSAttribute attr2a(value2a);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+
+ // Check the attribute
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+
+ // Now check that the second instance also knows about the change
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ }
+}
+
+void ObjectFileTests::testCorruptFile()
+{
+#ifndef _WIN32
+ FILE* stream = fopen("testdir/test.object", "w");
+#else
+ FILE* stream = fopen("testdir\\test.object", "wb");
+#endif
+ RNG* rng = CryptoFactory::i()->getRNG();
+ ByteString randomData;
+
+ CPPUNIT_ASSERT(stream != NULL);
+ CPPUNIT_ASSERT(rng->generateRandom(randomData, 312));
+ CPPUNIT_ASSERT(fwrite(randomData.const_byte_str(), 1, randomData.size(), stream) == randomData.size());
+ CPPUNIT_ASSERT(!fclose(stream));
+
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(!testObject.isValid());
+}
+
+void ObjectFileTests::testTransactions()
+{
+ // Create test object instance
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ std::set<CK_MECHANISM_TYPE> value4;
+ value4.insert(CKM_SHA256);
+ value4.insert(CKM_SHA512);
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Create secondary instance for the same object
+#ifndef _WIN32
+ ObjectFile testObject2(NULL, "testdir/test.object", "testdir/test.lock");
+#else
+ ObjectFile testObject2(NULL, "testdir\\test.object", "testdir\\test.lock");
+#endif
+
+ CPPUNIT_ASSERT(testObject2.isValid());
+
+ // Check that it has the same attributes
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ // New values
+ bool value1a = false;
+ unsigned long value2a = 0x12345678;
+ ByteString value3a = "ABABABABABABABABABABABABABABAB";
+ std::set<CK_MECHANISM_TYPE> value4a;
+ value4a.insert(CKM_SHA384);
+ value4a.insert(CKM_SHA512);
+
+ OSAttribute attr1a(value1a);
+ OSAttribute attr2a(value2a);
+ OSAttribute attr3a(value3a);
+ OSAttribute attr4a(value4a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction(ObjectFile::ReadWrite));
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4a));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Verify that they are unchanged on the other instance
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ // Commit the transaction
+ CPPUNIT_ASSERT(testObject.commitTransaction());
+
+ // Verify that they have now changed on the other instance
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Start transaction on object
+ CPPUNIT_ASSERT(testObject.startTransaction(ObjectFile::ReadWrite));
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr4));
+
+ // Verify that the attributes were set
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4);
+
+ // Verify that they are unchanged on the other instance
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ // Abort the transaction
+ CPPUNIT_ASSERT(testObject.abortTransaction());
+
+ // Verify that they are unchanged on both instances
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+
+ CPPUNIT_ASSERT(testObject2.isValid());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_VALUE).getByteStringValue() == value3a);
+ CPPUNIT_ASSERT(testObject2.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue() == value4a);
+}
+
+void ObjectFileTests::testDestroyObjectFails()
+{
+ // Create test object instance
+#ifndef _WIN32
+ ObjectFile testObject(NULL, "testdir/test.object", "testdir/test.lock", true);
+#else
+ ObjectFile testObject(NULL, "testdir\\test.object", "testdir\\test.lock", true);
+#endif
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSObject* testIF = (OSObject*) &testObject;
+
+ CPPUNIT_ASSERT(!testIF->destroyObject());
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.h b/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.h
new file mode 100644
index 0000000..8342a64
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/ObjectFileTests.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectFileTests.h
+
+ Contains test cases to test the object file implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTFILETESTS_H
+#define _SOFTHSM_V2_OBJECTFILETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ObjectFileTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ObjectFileTests);
+ CPPUNIT_TEST(testBoolAttr);
+ CPPUNIT_TEST(testULongAttr);
+ CPPUNIT_TEST(testByteStrAttr);
+ CPPUNIT_TEST(testMechTypeSetAttr);
+ CPPUNIT_TEST(testAttrMapAttr);
+ CPPUNIT_TEST(testMixedAttr);
+ CPPUNIT_TEST(testDoubleAttr);
+ CPPUNIT_TEST(testRefresh);
+ CPPUNIT_TEST(testCorruptFile);
+ CPPUNIT_TEST(testTransactions);
+ CPPUNIT_TEST(testDestroyObjectFails);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testBoolAttr();
+ void testULongAttr();
+ void testByteStrAttr();
+ void testMechTypeSetAttr();
+ void testAttrMapAttr();
+ void testMixedAttr();
+ void testDoubleAttr();
+ void testRefresh();
+ void testCorruptFile();
+ void testTransactions();
+ void testDestroyObjectFails();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OBJECTFILETESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.cpp b/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.cpp
new file mode 100644
index 0000000..0cad27b
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStoreTests.cpp
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "ObjectStoreTests.h"
+#include "ObjectStore.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectStoreTests);
+
+// FIXME: all pathnames in this file are *NIX/BSD specific
+
+void ObjectStoreTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void ObjectStoreTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void ObjectStoreTests::testEmptyStore()
+{
+ // Create the store for an empty dir
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 0);
+}
+
+void ObjectStoreTests::testNewTokens()
+{
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+
+ {
+ // Create an empty store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 0);
+
+ // Create a new token
+ ObjectStoreToken* token1 = store.newToken(label1);
+
+ CPPUNIT_ASSERT(token1 != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 1);
+
+ // Create another new token
+ ObjectStoreToken* token2 = store.newToken(label2);
+
+ CPPUNIT_ASSERT(token2 != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+ }
+
+ // Now reopen that same store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* token1 = store.getToken(0);
+ ObjectStoreToken* token2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2;
+
+ CPPUNIT_ASSERT(token1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(token2->getTokenLabel(retrieveLabel2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel2 == label1));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+
+ ByteString retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(token1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(token2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+}
+
+void ObjectStoreTests::testExistingTokens()
+{
+ // Create some tokens
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+ ByteString serial1 = "0011001100110011";
+ ByteString serial2 = "2233223322332233";
+
+#ifndef _WIN32
+ ObjectStoreToken* token1 = ObjectStoreToken::createToken("./testdir", "token1", label1, serial1);
+ ObjectStoreToken* token2 = ObjectStoreToken::createToken("./testdir", "token2", label2, serial2);
+#else
+ ObjectStoreToken* token1 = ObjectStoreToken::createToken(".\\testdir", "token1", label1, serial1);
+ ObjectStoreToken* token2 = ObjectStoreToken::createToken(".\\testdir", "token2", label2, serial2);
+#endif
+
+ CPPUNIT_ASSERT((token1 != NULL) && (token2 != NULL));
+
+ delete token1;
+ delete token2;
+
+ // Now associate a store with the test directory
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* retrieveToken1 = store.getToken(0);
+ ObjectStoreToken* retrieveToken2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2, retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(retrieveToken1 != NULL);
+ CPPUNIT_ASSERT(retrieveToken2 != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel1 == label2));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+ CPPUNIT_ASSERT((retrieveSerial1 == serial1) || (retrieveSerial1 == serial2));
+ CPPUNIT_ASSERT((retrieveSerial2 == serial1) || (retrieveSerial2 == serial2));
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+}
+
+void ObjectStoreTests::testDeleteToken()
+{
+ // Create some tokens
+ ByteString label1 = "DEADC0FFEE";
+ ByteString label2 = "DEADBEEF";
+ ByteString serial1 = "0011001100110011";
+ ByteString serial2 = "2233223322332233";
+
+#ifndef _WIN32
+ ObjectStoreToken* token1 = ObjectStoreToken::createToken("./testdir", "token1", label1, serial1);
+ ObjectStoreToken* token2 = ObjectStoreToken::createToken("./testdir", "token2", label2, serial2);
+#else
+ ObjectStoreToken* token1 = ObjectStoreToken::createToken(".\\testdir", "token1", label1, serial1);
+ ObjectStoreToken* token2 = ObjectStoreToken::createToken(".\\testdir", "token2", label2, serial2);
+#endif
+
+ CPPUNIT_ASSERT((token1 != NULL) && (token2 != NULL));
+
+ delete token1;
+ delete token2;
+
+ // Now associate a store with the test directory
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* retrieveToken1 = store.getToken(0);
+ ObjectStoreToken* retrieveToken2 = store.getToken(1);
+
+ ByteString retrieveLabel1, retrieveLabel2, retrieveSerial1, retrieveSerial2;
+
+ CPPUNIT_ASSERT(retrieveToken1 != NULL);
+ CPPUNIT_ASSERT(retrieveToken2 != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label1) || (retrieveLabel1 == label2));
+ CPPUNIT_ASSERT((retrieveLabel2 == label1) || (retrieveLabel2 == label2));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+ CPPUNIT_ASSERT((retrieveSerial1 == serial1) || (retrieveSerial1 == serial2));
+ CPPUNIT_ASSERT((retrieveSerial2 == serial1) || (retrieveSerial2 == serial2));
+ CPPUNIT_ASSERT(retrieveSerial1 != retrieveSerial2);
+
+ // Now, delete token #1
+ CPPUNIT_ASSERT(store.destroyToken(retrieveToken1));
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 1);
+
+ ObjectStoreToken* retrieveToken_ = store.getToken(0);
+
+ ByteString retrieveLabel_,retrieveSerial_;
+
+ CPPUNIT_ASSERT(retrieveToken_->getTokenLabel(retrieveLabel_));
+ CPPUNIT_ASSERT(retrieveToken_->getTokenSerial(retrieveSerial_));
+
+ CPPUNIT_ASSERT(((retrieveLabel_ == label1) && (retrieveSerial_ == serial1)) ||
+ ((retrieveLabel_ == label2) && (retrieveSerial_ == serial2)));
+
+ // Now add a new token
+ ByteString label3 = "DEADC0FFEEBEEF";
+
+ // Create a new token
+ ObjectStoreToken* tokenNew = store.newToken(label3);
+
+ CPPUNIT_ASSERT(tokenNew != NULL);
+
+ CPPUNIT_ASSERT(store.getTokenCount() == 2);
+
+ // Retrieve both tokens and check that both are present
+ ObjectStoreToken* retrieveToken1_ = store.getToken(0);
+ ObjectStoreToken* retrieveToken2_ = store.getToken(1);
+
+ CPPUNIT_ASSERT(retrieveToken1_ != NULL);
+ CPPUNIT_ASSERT(retrieveToken2_ != NULL);
+
+ CPPUNIT_ASSERT(retrieveToken1_->getTokenLabel(retrieveLabel1));
+ CPPUNIT_ASSERT(retrieveToken2_->getTokenLabel(retrieveLabel2));
+ CPPUNIT_ASSERT(retrieveToken1_->getTokenSerial(retrieveSerial1));
+ CPPUNIT_ASSERT(retrieveToken2_->getTokenSerial(retrieveSerial2));
+
+ CPPUNIT_ASSERT((retrieveLabel1 == label3) || (retrieveLabel2 == label3));
+ CPPUNIT_ASSERT(((retrieveLabel1 == label1) && (retrieveLabel2 != label2)) ||
+ ((retrieveLabel1 == label2) && (retrieveLabel2 != label1)));
+ CPPUNIT_ASSERT(retrieveLabel1 != retrieveLabel2);
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.h b/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.h
new file mode 100644
index 0000000..3f03c5a
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/ObjectStoreTests.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectStoreTests.h
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTSTORETESTS_H
+#define _SOFTHSM_V2_OBJECTSTORETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ObjectStoreTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(ObjectStoreTests);
+ CPPUNIT_TEST(testEmptyStore);
+ CPPUNIT_TEST(testNewTokens);
+ CPPUNIT_TEST(testExistingTokens);
+ CPPUNIT_TEST(testDeleteToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testEmptyStore();
+ void testNewTokens();
+ void testExistingTokens();
+ void testDeleteToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_OBJECTSTORETESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.cpp b/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.cpp
new file mode 100644
index 0000000..2c41eb0
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStoreTests.cpp
+
+ Contains test cases to test the session object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <memory>
+#include "SessionObjectStoreTests.h"
+#include "SessionObjectStore.h"
+#include "SessionObject.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionObjectStoreTests);
+
+void SessionObjectStoreTests::setUp()
+{
+}
+
+void SessionObjectStoreTests::tearDown()
+{
+}
+
+void SessionObjectStoreTests::testCreateDeleteObjects()
+{
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+ ByteString label = "AABBCCDDEEFF";
+ ByteString serial = "1234567890";
+
+ // Get access to the session object store
+ SessionObjectStore* testStore = new SessionObjectStore();
+
+ // Create 3 objects in the store
+ SessionObject* obj1 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = testStore->createObject(1, 1);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the store contains 3 objects
+ CPPUNIT_ASSERT(testStore->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<SessionObject*> objects = testStore->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now delete the second object
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[1])
+ {
+ CPPUNIT_ASSERT(testStore->deleteObject(*i));
+ break;
+ }
+ }
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(testStore->getObjects().size() == 2);
+
+ objects = testStore->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+
+ delete testStore;
+}
+
+void SessionObjectStoreTests::testMultiSession()
+{
+ // Get access to the store
+ SessionObjectStore* store = new SessionObjectStore();
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+
+ // Test IDs
+ ByteString id[5] = { "112233445566", "AABBCCDDEEFF", "ABABABABABAB", "557788991122", "005500550055" };
+ OSAttribute idAtt[5] = { id[0], id[1], id[2], id[3], id[4] };
+
+ // Create 3 objects in the store for three different sessions
+ SessionObject* obj1 = store->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = store->createObject(1, 2);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = store->createObject(1, 3);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Now set the IDs of the 3 objects
+ obj1->setAttribute(CKA_ID, idAtt[0]);
+ obj2->setAttribute(CKA_ID, idAtt[1]);
+ obj3->setAttribute(CKA_ID, idAtt[2]);
+
+ // Check that the store contains 3 objects
+ CPPUNIT_ASSERT(store->getObjects().size() == 3);
+
+ // Check that all three objects are distinct and present
+ std::set<SessionObject*> objects = store->getObjects();
+ bool present1[3] = { false, false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ for (int j = 0; j < 3; j++)
+ {
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[j])
+ {
+ present1[j] = true;
+ }
+ }
+ }
+
+ for (int j = 0; j < 3; j++)
+ {
+ CPPUNIT_ASSERT(present1[j] == true);
+ }
+
+ // Now indicate that the second session has been closed
+ store->sessionClosed(2);
+
+ // Verify that it was indeed removed
+ CPPUNIT_ASSERT(store->getObjects().size() == 2);
+
+ objects = store->getObjects();
+ bool present3[2] = { false, false };
+
+ for (std::set<SessionObject*>::iterator i = objects.begin(); i != objects.end(); i++)
+ {
+ ByteString retrievedId;
+
+ CPPUNIT_ASSERT((*i)->isValid());
+ CPPUNIT_ASSERT((*i)->attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT((*i)->getAttribute(CKA_ID).isByteStringAttribute());
+
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[0])
+ {
+ present3[0] = true;
+ }
+ if ((*i)->getAttribute(CKA_ID).getByteStringValue() == id[2])
+ {
+ present3[1] = true;
+ }
+ }
+
+ for (int j = 0; j < 2; j++)
+ {
+ CPPUNIT_ASSERT(present3[j] == true);
+ }
+
+ // Create two more objects for session 7
+ SessionObject* obj4 = store->createObject(1, 7);
+ CPPUNIT_ASSERT(obj4 != NULL);
+ SessionObject* obj5 = store->createObject(1, 7);
+ CPPUNIT_ASSERT(obj5 != NULL);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 4);
+
+ // Close session 1
+ store->sessionClosed(1);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 3);
+
+ objects = store->getObjects();
+
+ CPPUNIT_ASSERT(objects.find(obj1) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj2) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj3) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj4) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj5) != objects.end());
+
+ CPPUNIT_ASSERT(!obj1->isValid());
+ CPPUNIT_ASSERT(!obj2->isValid());
+ CPPUNIT_ASSERT(obj3->isValid());
+ CPPUNIT_ASSERT(obj4->isValid());
+ CPPUNIT_ASSERT(obj5->isValid());
+
+ // Close session 7
+ store->sessionClosed(7);
+
+ CPPUNIT_ASSERT(store->getObjects().size() == 1);
+
+ objects = store->getObjects();
+
+ CPPUNIT_ASSERT(objects.find(obj1) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj2) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj3) != objects.end());
+ CPPUNIT_ASSERT(objects.find(obj4) == objects.end());
+ CPPUNIT_ASSERT(objects.find(obj5) == objects.end());
+
+ CPPUNIT_ASSERT(!obj1->isValid());
+ CPPUNIT_ASSERT(!obj2->isValid());
+ CPPUNIT_ASSERT(obj3->isValid());
+ CPPUNIT_ASSERT(!obj4->isValid());
+ CPPUNIT_ASSERT(!obj5->isValid());
+
+ delete store;
+}
+
+void SessionObjectStoreTests::testWipeStore()
+{
+ // Get access to the store
+ SessionObjectStore* store = new SessionObjectStore();
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+
+ // Create 3 objects in the store for three different sessions
+ SessionObject* obj1 = store->createObject(1, 1);
+ CPPUNIT_ASSERT(obj1 != NULL);
+ SessionObject* obj2 = store->createObject(1, 2);
+ CPPUNIT_ASSERT(obj2 != NULL);
+ SessionObject* obj3 = store->createObject(1, 3);
+ CPPUNIT_ASSERT(obj3 != NULL);
+
+ // Wipe the store
+ store->clearStore();
+
+ // Check that the store is empty
+ CPPUNIT_ASSERT(store->getObjects().size() == 0);
+
+ delete store;
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.h b/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.h
new file mode 100644
index 0000000..374eeaa
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/SessionObjectStoreTests.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectStoreTests.h
+
+ Contains test cases to test the session object store implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+#define _SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionObjectStoreTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionObjectStoreTests);
+ CPPUNIT_TEST(testCreateDeleteObjects);
+ CPPUNIT_TEST(testMultiSession);
+ CPPUNIT_TEST(testWipeStore);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testCreateDeleteObjects();
+ void testMultiSession();
+ void testWipeStore();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECTSTORETESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.cpp b/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.cpp
new file mode 100644
index 0000000..6183ec6
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.cpp
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectTests.cpp
+
+ Contains test cases to test the session object implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SessionObjectTests.h"
+#include "SessionObject.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionObjectTests);
+
+void SessionObjectTests::setUp()
+{
+}
+
+void SessionObjectTests::tearDown()
+{
+}
+
+void SessionObjectTests::testBoolAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ bool value2 = false;
+ bool value3 = true;
+ bool value4 = true;
+ bool value5 = false;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SENSITIVE, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_EXTRACTABLE, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_NEVER_EXTRACTABLE, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SIGN, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SENSITIVE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_NEVER_EXTRACTABLE));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SIGN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).isBooleanAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SENSITIVE).getBooleanValue() == false);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_EXTRACTABLE).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_NEVER_EXTRACTABLE).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SIGN).getBooleanValue() == false);
+
+ bool value6 = true;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VERIFY, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VERIFY).getBooleanValue() == value6);
+ CPPUNIT_ASSERT(testObject.getBooleanValue(CKA_VERIFY, false) == value6);
+}
+
+void SessionObjectTests::testULongAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ unsigned long value1 = 0x12345678;
+ unsigned long value2 = 0x87654321;
+ unsigned long value3 = 0x01010101;
+ unsigned long value4 = 0x10101010;
+ unsigned long value5 = 0xABCDEF;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS_BITS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_AUTH_PIN_FLAGS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBPRIME_BITS, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_KEY_TYPE, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_AUTH_PIN_FLAGS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBPRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_KEY_TYPE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).isUnsignedLongAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS_BITS).getUnsignedLongValue() == 0x12345678);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_AUTH_PIN_FLAGS).getUnsignedLongValue() == 0x01010101);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBPRIME_BITS).getUnsignedLongValue() == 0x10101010);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_KEY_TYPE).getUnsignedLongValue() == 0xABCDEF);
+
+ unsigned long value6 = 0x90909090;
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_CLASS, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_CLASS).getUnsignedLongValue() == value6);
+ CPPUNIT_ASSERT(testObject.getUnsignedLongValue(CKA_CLASS, 0x0) == value6);
+}
+
+void SessionObjectTests::testByteStrAttr()
+{
+ ByteString value1 = "010203040506070809";
+ ByteString value2 = "ABABABABABABABABABABABABABABABABAB";
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value4 = "98A7E5D798A7E5D798A7E5D798A7E5D798A7E5D798A7E5D7";
+ ByteString value5 = "ABCDABCDABCDABCDABCDABCDABCDABCD";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+ OSAttribute attr4(value4);
+ OSAttribute attr5(value5);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_MODULUS, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_COEFFICIENT, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PUBLIC_EXPONENT, attr4));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_SUBJECT, attr5));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_MODULUS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_COEFFICIENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PUBLIC_EXPONENT));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_SUBJECT));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_MODULUS).getByteStringValue() == value1);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_COEFFICIENT).getByteStringValue() == value2);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PUBLIC_EXPONENT).getByteStringValue() == value4);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_SUBJECT).getByteStringValue() == value5);
+
+ ByteString value6 = "909090908080808080807070707070FF";
+ OSAttribute attr6(value6);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ISSUER, attr6));
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ISSUER).isByteStringAttribute());
+ CPPUNIT_ASSERT(testObject.getByteStringValue(CKA_ISSUER) == value6);
+}
+
+void SessionObjectTests::testMechTypeSetAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ std::set<CK_MECHANISM_TYPE> set;
+ set.insert(CKM_SHA256);
+ set.insert(CKM_SHA512);
+
+ OSAttribute attr(set);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_ALLOWED_MECHANISMS, attr));
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_ALLOWED_MECHANISMS));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_ALLOWED_MECHANISMS).isMechanismTypeSetAttribute());
+
+ std::set<CK_MECHANISM_TYPE> retrieved =
+ testObject.getAttribute(CKA_ALLOWED_MECHANISMS).getMechanismTypeSetValue();
+
+ CPPUNIT_ASSERT(retrieved.size() == 2);
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA256) != retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA384) == retrieved.end());
+ CPPUNIT_ASSERT(retrieved.find(CKM_SHA512) != retrieved.end());
+}
+
+void SessionObjectTests::testAttrMapAttr()
+{
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattr;
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_TOKEN, attr1));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_PRIME_BITS, attr2));
+ mattr.insert(std::pair<CK_ATTRIBUTE_TYPE,OSAttribute> (CKA_VALUE_BITS, attr3));
+ OSAttribute attra(mattr);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_WRAP_TEMPLATE, attra));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_WRAP_TEMPLATE));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_UNWRAP_TEMPLATE));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_WRAP_TEMPLATE).isAttributeMapAttribute());
+
+ std::map<CK_ATTRIBUTE_TYPE,OSAttribute> mattrb =
+ testObject.getAttribute(CKA_WRAP_TEMPLATE).getAttributeMapValue();
+ CPPUNIT_ASSERT(mattrb.size() == 3);
+ CPPUNIT_ASSERT(mattrb.find(CKA_TOKEN) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(mattrb.find(CKA_PRIME_BITS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(mattrb.find(CKA_VALUE_BITS) != mattrb.end());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE_BITS).isByteStringAttribute());
+ CPPUNIT_ASSERT(mattrb.at(CKA_VALUE_BITS).getByteStringValue() == value3);
+
+}
+
+void SessionObjectTests::testMixedAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3);
+}
+
+void SessionObjectTests::testDoubleAttr()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+ ByteString value3a = "466487346943785684957634";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3);
+
+ bool value1a = false;
+ unsigned long value2a = 0x76767676;
+
+ OSAttribute attr1a(value1a);
+ OSAttribute attr2a(value2a);
+ OSAttribute attr3a(value3a);
+
+ // Change the attributes
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2a));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3a));
+
+ // Check the attributes
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == value1a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == value2a);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3a);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+}
+
+void SessionObjectTests::testCloseSession()
+{
+ ByteString value3 = "BDEBDBEDBBDBEBDEBE792759537328";
+
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ bool value1 = true;
+ unsigned long value2 = 0x87654321;
+
+ OSAttribute attr1(value1);
+ OSAttribute attr2(value2);
+ OSAttribute attr3(value3);
+
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_TOKEN, attr1));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_PRIME_BITS, attr2));
+ CPPUNIT_ASSERT(testObject.setAttribute(CKA_VALUE_BITS, attr3));
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(testObject.attributeExists(CKA_VALUE_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_ID));
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).isBooleanAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).isUnsignedLongAttribute());
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).isByteStringAttribute());
+
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_TOKEN).getBooleanValue() == true);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_PRIME_BITS).getUnsignedLongValue() == 0x87654321);
+ CPPUNIT_ASSERT(testObject.getAttribute(CKA_VALUE_BITS).getByteStringValue() == value3);
+
+ // Now close the session
+ testObject.removeOnSessionClose(1);
+
+ CPPUNIT_ASSERT(!testObject.isValid());
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_TOKEN));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_PRIME_BITS));
+ CPPUNIT_ASSERT(!testObject.attributeExists(CKA_VALUE_BITS));
+}
+
+void SessionObjectTests::testDestroyObjectFails()
+{
+ // Create test object instance
+ SessionObject testObject(NULL, 1, 1);
+
+ CPPUNIT_ASSERT(testObject.isValid());
+
+ OSObject* testIF = (OSObject*) &testObject;
+
+ CPPUNIT_ASSERT(!testIF->destroyObject());
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.h b/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.h
new file mode 100644
index 0000000..76fa02e
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/SessionObjectTests.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionObjectTests.h
+
+ Contains test cases to test the session object implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONOBJECTTESTS_H
+#define _SOFTHSM_V2_SESSIONOBJECTTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionObjectTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionObjectTests);
+ CPPUNIT_TEST(testBoolAttr);
+ CPPUNIT_TEST(testULongAttr);
+ CPPUNIT_TEST(testByteStrAttr);
+ CPPUNIT_TEST(testMechTypeSetAttr);
+ CPPUNIT_TEST(testAttrMapAttr);
+ CPPUNIT_TEST(testMixedAttr);
+ CPPUNIT_TEST(testDoubleAttr);
+ CPPUNIT_TEST(testCloseSession);
+ CPPUNIT_TEST(testDestroyObjectFails);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testBoolAttr();
+ void testULongAttr();
+ void testByteStrAttr();
+ void testMechTypeSetAttr();
+ void testAttrMapAttr();
+ void testMixedAttr();
+ void testDoubleAttr();
+ void testCloseSession();
+ void testDestroyObjectFails();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONOBJECTTESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/UUIDTests.cpp b/SoftHSMv2/src/lib/object_store/test/UUIDTests.cpp
new file mode 100644
index 0000000..84a49d2
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/UUIDTests.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUIDTests.cpp
+
+ Contains test cases to test the UUID implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "UUIDTests.h"
+#include "UUID.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(UUIDTests);
+
+void UUIDTests::setUp()
+{
+}
+
+void UUIDTests::tearDown()
+{
+}
+
+void UUIDTests::testUUID()
+{
+ std::string uuid1 = UUID::newUUID();
+ std::string uuid2 = UUID::newUUID();
+ std::string uuid3 = UUID::newUUID();
+
+ CPPUNIT_ASSERT((uuid1.size() == 36) && (uuid2.size() == 36) && (uuid3.size() == 36));
+
+ CPPUNIT_ASSERT(uuid1.compare(uuid2));
+ CPPUNIT_ASSERT(uuid1.compare(uuid3));
+ CPPUNIT_ASSERT(uuid2.compare(uuid3));
+}
+
diff --git a/SoftHSMv2/src/lib/object_store/test/UUIDTests.h b/SoftHSMv2/src/lib/object_store/test/UUIDTests.h
new file mode 100644
index 0000000..374d509
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/UUIDTests.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UUIDTests.h
+
+ Contains test cases to test the UUID implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_UUIDTESTS_H
+#define _SOFTHSM_V2_UUIDTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class UUIDTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(UUIDTests);
+ CPPUNIT_TEST(testUUID);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testUUID();
+
+ void setUp();
+ void tearDown();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_UUIDTESTS_H
+
diff --git a/SoftHSMv2/src/lib/object_store/test/objstoretest.cpp b/SoftHSMv2/src/lib/object_store/test/objstoretest.cpp
new file mode 100644
index 0000000..7e4b854
--- /dev/null
+++ b/SoftHSMv2/src/lib/object_store/test/objstoretest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ objstoretest.cpp
+
+ The main test executor for tests on the object store in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "SecureMemoryRegistry.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#endif
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ CryptoFactory::reset();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/SoftHSMv2/src/lib/pkcs11/cryptoki.h b/SoftHSMv2/src/lib/pkcs11/cryptoki.h
new file mode 100644
index 0000000..d278b42
--- /dev/null
+++ b/SoftHSMv2/src/lib/pkcs11/cryptoki.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ cryptoki.h
+
+ Set the PKCS#11 macros.
+ *****************************************************************************/
+
+#ifndef _CRYPTOKI_H
+#define _CRYPTOKI_H
+
+#ifdef _WIN32
+#pragma pack(push, cryptoki, 1)
+#endif
+
+// 1. CK_PTR: The indirection string for making a pointer to an
+// object.
+
+#define CK_PTR *
+
+// 2. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+// an importable Cryptoki library function declaration out of a
+// return type and a function name.
+
+#ifdef _WIN32
+#ifdef CRYPTOKI_EXPORTS
+#define CK_DECLARE_FUNCTION(returnType, name) \
+ returnType __declspec(dllexport) name
+#else
+#define CK_DECLARE_FUNCTION(returnType, name) \
+ returnType __declspec(dllimport) name
+#endif
+#else
+#define CK_DECLARE_FUNCTION(returnType, name) \
+ returnType name
+#endif
+
+// 3. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+// which makes a Cryptoki API function pointer declaration or
+// function pointer type declaration out of a return type and a
+// function name.
+
+#ifdef _WIN32
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ returnType __declspec(dllimport) (* name)
+#else
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ returnType (* name)
+#endif
+
+// 4. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+// a function pointer type for an application callback out of
+// a return type for the callback and a name for the callback.
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+ returnType (* name)
+
+// 5. NULL_PTR: This macro is the value of a NULL pointer.
+
+#ifndef NULL_PTR
+#define NULL_PTR 0
+#endif
+
+#include "pkcs11.h"
+
+#ifdef _WIN32
+#pragma pack(pop, cryptoki)
+#endif
+
+#endif // !_CRYPTOKI_H
diff --git a/SoftHSMv2/src/lib/pkcs11/pkcs11.h b/SoftHSMv2/src/lib/pkcs11/pkcs11.h
new file mode 100644
index 0000000..0d78dd7
--- /dev/null
+++ b/SoftHSMv2/src/lib/pkcs11/pkcs11.h
@@ -0,0 +1,265 @@
+/* Copyright (c) OASIS Open 2016. All Rights Reserved./
+ * /Distributed under the terms of the OASIS IPR Policy,
+ * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
+ * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
+ */
+
+/* Latest version of the specification:
+ * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
+ */
+
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 5 platform-specific macros must be defined. These
+ * macros are described below, and typical definitions for them
+ * are also given. Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a Cryptoki library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 5 macros, the packing convention
+ * for Cryptoki structures should be set. The Cryptoki
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, this might be done by using the following
+ * preprocessor directive before including pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, this might be done by using
+ * the following preprocessor directive before including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(1)
+ *
+ * In a UNIX environment, you're on your own for this. You might
+ * not need to do (or be able to do!) anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object. It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, it might be defined by:
+ *
+ * #define CK_PTR far *
+ *
+ * In a typical UNIX environment, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable Cryptoki library function declaration out of a
+ * return type and a function name. It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * );
+ *
+ * If you're using Microsoft Developer Studio 5.0 to declare a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllimport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to declare a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a Cryptoki API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name. It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a Cryptoki API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // Cryptoki API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to access
+ * functions in a Win32 Cryptoki .dll, in might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __declspec(dllimport) (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to access functions in a Win16 Cryptoki .dll, it might
+ * be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __export _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 4. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV. It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to do Win32
+ * Cryptoki development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to do Win16 development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 5. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should best be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+
+/* All the various Cryptoki types and #define'd values are in the
+ * file pkcs11t.h.
+ */
+#include "pkcs11t.h"
+
+#define __PASTE(x,y) x##y
+
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ extern CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes.
+ */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define the typedef form of all the entry points. That is, for
+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes.
+ */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define structed vector of entry points. A CK_FUNCTION_LIST
+ * contains a CK_VERSION indicating a library's Cryptoki version
+ * and then a whole slew of function pointers to the routines in
+ * the library. This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ __PASTE(CK_,name) name;
+
+struct CK_FUNCTION_LIST {
+
+ CK_VERSION version; /* Cryptoki version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes.
+ */
+#include "pkcs11f.h"
+
+};
+
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKCS11_H_ */
+
diff --git a/SoftHSMv2/src/lib/pkcs11/pkcs11f.h b/SoftHSMv2/src/lib/pkcs11/pkcs11f.h
new file mode 100644
index 0000000..ed90aff
--- /dev/null
+++ b/SoftHSMv2/src/lib/pkcs11/pkcs11f.h
@@ -0,0 +1,939 @@
+/* Copyright (c) OASIS Open 2016. All Rights Reserved./
+ * /Distributed under the terms of the OASIS IPR Policy,
+ * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
+ * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
+ */
+
+/* Latest version of the specification:
+ * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
+ */
+
+/* This header file contains pretty much everything about all the
+ * Cryptoki function prototypes. Because this information is
+ * used for more than just declaring function prototypes, the
+ * order of the functions appearing herein is important, and
+ * should not be altered.
+ */
+
+/* General-purpose */
+
+/* C_Initialize initializes the Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
+ * cast to CK_C_INITIALIZE_ARGS_PTR
+ * and dereferenced
+ */
+);
+#endif
+
+
+/* C_Finalize indicates that an application is done with the
+ * Cryptoki library.
+ */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
+
+/* C_GetInfo returns general information about Cryptoki. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_INFO_PTR pInfo /* location that receives information */
+);
+#endif
+
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
+ * function list
+ */
+);
+#endif
+
+
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_BBOOL tokenPresent, /* only slots with tokens */
+ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
+ CK_ULONG_PTR pulCount /* receives number of slots */
+);
+#endif
+
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the ID of the slot */
+ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
+);
+#endif
+
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
+);
+#endif
+
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of token's slot */
+ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
+ CK_ULONG_PTR pulCount /* gets # of mechs. */
+);
+#endif
+
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_MECHANISM_TYPE type, /* type of mechanism */
+ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
+);
+#endif
+
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
+ CK_ULONG ulPinLen, /* length in bytes of the PIN */
+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
+);
+#endif
+
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
+ CK_ULONG ulPinLen /* length in bytes of the PIN */
+);
+#endif
+
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
+ CK_ULONG ulOldLen, /* length of the old PIN */
+ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
+ CK_ULONG ulNewLen /* length of the new PIN */
+);
+#endif
+
+
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token.
+ */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the slot's ID */
+ CK_FLAGS flags, /* from CK_SESSION_INFO */
+ CK_VOID_PTR pApplication, /* passed to callback */
+ CK_NOTIFY Notify, /* callback function */
+ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
+);
+#endif
+
+
+/* C_CloseSession closes a session between an application and a
+ * token.
+ */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID /* the token's slot */
+);
+#endif
+
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_SESSION_INFO_PTR pInfo /* receives session info */
+);
+#endif
+
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* gets state */
+ CK_ULONG_PTR pulOperationStateLen /* gets state length */
+);
+#endif
+
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* holds state */
+ CK_ULONG ulOperationStateLen, /* holds state length */
+ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
+ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
+);
+#endif
+
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_USER_TYPE userType, /* the user type */
+ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
+ CK_ULONG ulPinLen /* the length of the PIN */
+);
+#endif
+
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
+);
+#endif
+
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy.
+ */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
+);
+#endif
+
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject /* the object's handle */
+);
+#endif
+
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ULONG_PTR pulSize /* receives size of object */
+);
+#endif
+
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template.
+ */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
+ CK_ULONG ulCount /* attrs in search template */
+);
+#endif
+
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles.
+ */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
+ CK_ULONG ulMaxObjectCount, /* max handles to get */
+ CK_ULONG_PTR pulObjectCount /* actual # returned */
+);
+#endif
+
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects.
+ */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of encryption key */
+);
+#endif
+
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pData, /* the plaintext data */
+ CK_ULONG ulDataLen, /* bytes of plaintext */
+ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext data len */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
+ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
+);
+#endif
+
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of decryption key */
+);
+#endif
+
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedData, /* ciphertext */
+ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
+ CK_BYTE_PTR pData, /* gets plaintext */
+ CK_ULONG_PTR pulDataLen /* gets p-text size */
+);
+#endif
+
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
+ CK_ULONG ulEncryptedPartLen, /* input length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* p-text size */
+);
+#endif
+
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pLastPart, /* gets plaintext */
+ CK_ULONG_PTR pulLastPartLen /* p-text size */
+);
+#endif
+
+
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
+);
+#endif
+
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* data to be digested */
+ CK_ULONG ulDataLen, /* bytes of data to digest */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets digest length */
+);
+#endif
+
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* data to be digested */
+ CK_ULONG ulPartLen /* bytes of data to be digested */
+);
+#endif
+
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hKey /* secret key to digest */
+);
+#endif
+
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
+);
+#endif
+
+
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ * signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of signature key */
+);
+#endif
+
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* the data to sign */
+ CK_ULONG ulPartLen /* count of bytes to sign */
+);
+#endif
+
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of the signature key */
+);
+#endif
+
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ * cannot be recovered from the signature (e.g. DSA).
+ */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* signed data */
+ CK_ULONG ulDataLen, /* length of signed data */
+ CK_BYTE_PTR pSignature, /* signature */
+ CK_ULONG ulSignatureLen /* signature length*/
+);
+#endif
+
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* signed data */
+ CK_ULONG ulPartLen /* length of signed data */
+);
+#endif
+
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen /* signature length */
+);
+#endif
+
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature.
+ */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen, /* signature length */
+ CK_BYTE_PTR pData, /* gets signed data */
+ CK_ULONG_PTR pulDataLen /* gets signed data len */
+);
+#endif
+
+
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets plaintext len */
+);
+#endif
+
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets p-text length */
+);
+#endif
+
+
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
+ CK_ULONG ulCount, /* # of attrs in template */
+ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
+);
+#endif
+
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_MECHANISM_PTR pMechanism, /* key-gen mech. */
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template for pub. key */
+ CK_ULONG ulPublicKeyAttributeCount, /* # pub. attrs. */
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template for priv. key */
+ CK_ULONG ulPrivateKeyAttributeCount, /* # priv. attrs. */
+ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. key handle */
+ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets priv. key handle */
+);
+#endif
+
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
+ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
+ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
+ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
+ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object.
+ */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
+ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
+ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
+ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object.
+ */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
+ CK_OBJECT_HANDLE hBaseKey, /* base key */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator.
+ */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSeed, /* the seed material */
+ CK_ULONG ulSeedLen /* length of seed material */
+);
+#endif
+
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR RandomData, /* receives the random data */
+ CK_ULONG ulRandomLen /* # of bytes to generate */
+);
+#endif
+
+
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application.
+ */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel.
+ */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur.
+ */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FLAGS flags, /* blocking/nonblocking flag */
+ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
+ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
diff --git a/SoftHSMv2/src/lib/pkcs11/pkcs11t.h b/SoftHSMv2/src/lib/pkcs11/pkcs11t.h
new file mode 100644
index 0000000..0cf3acc
--- /dev/null
+++ b/SoftHSMv2/src/lib/pkcs11/pkcs11t.h
@@ -0,0 +1,2003 @@
+/* Copyright (c) OASIS Open 2016. All Rights Reserved./
+ * /Distributed under the terms of the OASIS IPR Policy,
+ * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
+ * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
+ */
+
+/* Latest version of the specification:
+ * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
+ */
+
+/* See top of pkcs11.h for information about the macros that
+ * must be defined and the structure-packing conventions that
+ * must be set before including this file.
+ */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#define CRYPTOKI_VERSION_MAJOR 2
+#define CRYPTOKI_VERSION_MINOR 40
+#define CRYPTOKI_VERSION_AMENDMENT 0
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE CK_FALSE
+#endif
+#ifndef TRUE
+#define TRUE CK_TRUE
+#endif
+#endif
+
+/* an unsigned 8-bit value */
+typedef unsigned char CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+typedef long int CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG CK_FLAGS;
+
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE 0UL
+
+
+typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+typedef CK_CHAR CK_PTR CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
+typedef CK_ULONG CK_PTR CK_ULONG_PTR;
+typedef void CK_PTR CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+
+/* The following value is always invalid if used as a session
+ * handle or object handle
+ */
+#define CK_INVALID_HANDLE 0UL
+
+
+typedef struct CK_VERSION {
+ CK_BYTE major; /* integer portion of version number */
+ CK_BYTE minor; /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+
+typedef struct CK_INFO {
+ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags; /* must be zero */
+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
+ CK_VERSION libraryVersion; /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR CK_INFO_PTR;
+
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * Cryptoki provides to an application
+ */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER 0UL
+#define CKN_OTP_CHANGED 1UL
+
+typedef CK_ULONG CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+ CK_UTF8CHAR slotDescription[64]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags;
+
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_TOKEN_PRESENT 0x00000001UL /* a token is there */
+#define CKF_REMOVABLE_DEVICE 0x00000002UL /* removable devices*/
+#define CKF_HW_SLOT 0x00000004UL /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+ CK_UTF8CHAR label[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR model[16]; /* blank padded */
+ CK_CHAR serialNumber[16]; /* blank padded */
+ CK_FLAGS flags; /* see below */
+
+ CK_ULONG ulMaxSessionCount; /* max open sessions */
+ CK_ULONG ulSessionCount; /* sess. now open */
+ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
+ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
+ CK_ULONG ulMaxPinLen; /* in bytes */
+ CK_ULONG ulMinPinLen; /* in bytes */
+ CK_ULONG ulTotalPublicMemory; /* in bytes */
+ CK_ULONG ulFreePublicMemory; /* in bytes */
+ CK_ULONG ulTotalPrivateMemory; /* in bytes */
+ CK_ULONG ulFreePrivateMemory; /* in bytes */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+ CK_CHAR utcTime[16]; /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RNG 0x00000001UL /* has random # generator */
+#define CKF_WRITE_PROTECTED 0x00000002UL /* token is write-protected */
+#define CKF_LOGIN_REQUIRED 0x00000004UL /* user must login */
+#define CKF_USER_PIN_INITIALIZED 0x00000008UL /* normal user's PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED. If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state
+ */
+#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020UL
+
+/* CKF_CLOCK_ON_TOKEN. If it is set, that means
+ * that the token has some sort of clock. The time on that
+ * clock is returned in the token info structure
+ */
+#define CKF_CLOCK_ON_TOKEN 0x00000040UL
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH. If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the Cryptoki library itself
+ */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100UL
+
+/* CKF_DUAL_CRYPTO_OPERATIONS. If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign)
+ */
+#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200UL
+
+/* CKF_TOKEN_INITIALIZED. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized.
+ */
+#define CKF_TOKEN_INITIALIZED 0x00000400UL
+
+/* CKF_SECONDARY_AUTHENTICATION. If it is
+ * true, the token supports secondary authentication for
+ * private key objects.
+ */
+#define CKF_SECONDARY_AUTHENTICATION 0x00000800UL
+
+/* CKF_USER_PIN_COUNT_LOW. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication.
+ */
+#define CKF_USER_PIN_COUNT_LOW 0x00010000UL
+
+/* CKF_USER_PIN_FINAL_TRY. If it is true,
+ * supplying an incorrect user PIN will it to become locked.
+ */
+#define CKF_USER_PIN_FINAL_TRY 0x00020000UL
+
+/* CKF_USER_PIN_LOCKED. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible.
+ */
+#define CKF_USER_PIN_LOCKED 0x00040000UL
+
+/* CKF_USER_PIN_TO_BE_CHANGED. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card.
+ */
+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000UL
+
+/* CKF_SO_PIN_COUNT_LOW. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication.
+ */
+#define CKF_SO_PIN_COUNT_LOW 0x00100000UL
+
+/* CKF_SO_PIN_FINAL_TRY. If it is true,
+ * supplying an incorrect SO PIN will it to become locked.
+ */
+#define CKF_SO_PIN_FINAL_TRY 0x00200000UL
+
+/* CKF_SO_PIN_LOCKED. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED 0x00400000UL
+
+/* CKF_SO_PIN_TO_BE_CHANGED. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card.
+ */
+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000UL
+
+#define CKF_ERROR_STATE 0x01000000UL
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+
+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
+ * identifies a session
+ */
+typedef CK_ULONG CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+
+/* CK_USER_TYPE enumerates the types of Cryptoki users */
+typedef CK_ULONG CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO 0UL
+/* Normal user */
+#define CKU_USER 1UL
+/* Context specific */
+#define CKU_CONTEXT_SPECIFIC 2UL
+
+/* CK_STATE enumerates the session states */
+typedef CK_ULONG CK_STATE;
+#define CKS_RO_PUBLIC_SESSION 0UL
+#define CKS_RO_USER_FUNCTIONS 1UL
+#define CKS_RW_PUBLIC_SESSION 2UL
+#define CKS_RW_USER_FUNCTIONS 3UL
+#define CKS_RW_SO_FUNCTIONS 4UL
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+ CK_SLOT_ID slotID;
+ CK_STATE state;
+ CK_FLAGS flags; /* see below */
+ CK_ULONG ulDeviceError; /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RW_SESSION 0x00000002UL /* session is r/w */
+#define CKF_SERIAL_SESSION 0x00000004UL /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object
+ */
+typedef CK_ULONG CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that Cryptoki recognizes. It is defined
+ * as follows:
+ */
+typedef CK_ULONG CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+#define CKO_DATA 0x00000000UL
+#define CKO_CERTIFICATE 0x00000001UL
+#define CKO_PUBLIC_KEY 0x00000002UL
+#define CKO_PRIVATE_KEY 0x00000003UL
+#define CKO_SECRET_KEY 0x00000004UL
+#define CKO_HW_FEATURE 0x00000005UL
+#define CKO_DOMAIN_PARAMETERS 0x00000006UL
+#define CKO_MECHANISM 0x00000007UL
+#define CKO_OTP_KEY 0x00000008UL
+
+#define CKO_VENDOR_DEFINED 0x80000000UL
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_HW_FEATURE_TYPE is a value that identifies the hardware feature type
+ * of an object with CK_OBJECT_CLASS equal to CKO_HW_FEATURE.
+ */
+typedef CK_ULONG CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+#define CKH_MONOTONIC_COUNTER 0x00000001UL
+#define CKH_CLOCK 0x00000002UL
+#define CKH_USER_INTERFACE 0x00000003UL
+#define CKH_VENDOR_DEFINED 0x80000000UL
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+typedef CK_ULONG CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA 0x00000000UL
+#define CKK_DSA 0x00000001UL
+#define CKK_DH 0x00000002UL
+#define CKK_ECDSA 0x00000003UL /* Deprecated */
+#define CKK_EC 0x00000003UL
+#define CKK_X9_42_DH 0x00000004UL
+#define CKK_KEA 0x00000005UL
+#define CKK_GENERIC_SECRET 0x00000010UL
+#define CKK_RC2 0x00000011UL
+#define CKK_RC4 0x00000012UL
+#define CKK_DES 0x00000013UL
+#define CKK_DES2 0x00000014UL
+#define CKK_DES3 0x00000015UL
+#define CKK_CAST 0x00000016UL
+#define CKK_CAST3 0x00000017UL
+#define CKK_CAST5 0x00000018UL /* Deprecated */
+#define CKK_CAST128 0x00000018UL
+#define CKK_RC5 0x00000019UL
+#define CKK_IDEA 0x0000001AUL
+#define CKK_SKIPJACK 0x0000001BUL
+#define CKK_BATON 0x0000001CUL
+#define CKK_JUNIPER 0x0000001DUL
+#define CKK_CDMF 0x0000001EUL
+#define CKK_AES 0x0000001FUL
+#define CKK_BLOWFISH 0x00000020UL
+#define CKK_TWOFISH 0x00000021UL
+#define CKK_SECURID 0x00000022UL
+#define CKK_HOTP 0x00000023UL
+#define CKK_ACTI 0x00000024UL
+#define CKK_CAMELLIA 0x00000025UL
+#define CKK_ARIA 0x00000026UL
+
+#define CKK_MD5_HMAC 0x00000027UL
+#define CKK_SHA_1_HMAC 0x00000028UL
+#define CKK_RIPEMD128_HMAC 0x00000029UL
+#define CKK_RIPEMD160_HMAC 0x0000002AUL
+#define CKK_SHA256_HMAC 0x0000002BUL
+#define CKK_SHA384_HMAC 0x0000002CUL
+#define CKK_SHA512_HMAC 0x0000002DUL
+#define CKK_SHA224_HMAC 0x0000002EUL
+
+#define CKK_SEED 0x0000002FUL
+#define CKK_GOSTR3410 0x00000030UL
+#define CKK_GOSTR3411 0x00000031UL
+#define CKK_GOST28147 0x00000032UL
+
+
+
+#define CKK_VENDOR_DEFINED 0x80000000UL
+
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type
+ */
+typedef CK_ULONG CK_CERTIFICATE_TYPE;
+
+#define CK_CERTIFICATE_CATEGORY_UNSPECIFIED 0UL
+#define CK_CERTIFICATE_CATEGORY_TOKEN_USER 1UL
+#define CK_CERTIFICATE_CATEGORY_AUTHORITY 2UL
+#define CK_CERTIFICATE_CATEGORY_OTHER_ENTITY 3UL
+
+#define CK_SECURITY_DOMAIN_UNSPECIFIED 0UL
+#define CK_SECURITY_DOMAIN_MANUFACTURER 1UL
+#define CK_SECURITY_DOMAIN_OPERATOR 2UL
+#define CK_SECURITY_DOMAIN_THIRD_PARTY 3UL
+
+
+/* The following certificate types are defined: */
+#define CKC_X_509 0x00000000UL
+#define CKC_X_509_ATTR_CERT 0x00000001UL
+#define CKC_WTLS 0x00000002UL
+#define CKC_VENDOR_DEFINED 0x80000000UL
+#define CKC_OPENPGP (CKC_VENDOR_DEFINED|0x00504750)
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type
+ */
+typedef CK_ULONG CK_ATTRIBUTE_TYPE;
+
+/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
+ * consists of an array of values.
+ */
+#define CKF_ARRAY_ATTRIBUTE 0x40000000UL
+
+/* The following OTP-related defines relate to the CKA_OTP_FORMAT attribute */
+#define CK_OTP_FORMAT_DECIMAL 0UL
+#define CK_OTP_FORMAT_HEXADECIMAL 1UL
+#define CK_OTP_FORMAT_ALPHANUMERIC 2UL
+#define CK_OTP_FORMAT_BINARY 3UL
+
+/* The following OTP-related defines relate to the CKA_OTP_..._REQUIREMENT
+ * attributes
+ */
+#define CK_OTP_PARAM_IGNORED 0UL
+#define CK_OTP_PARAM_OPTIONAL 1UL
+#define CK_OTP_PARAM_MANDATORY 2UL
+
+/* The following attribute types are defined: */
+#define CKA_CLASS 0x00000000UL
+#define CKA_TOKEN 0x00000001UL
+#define CKA_PRIVATE 0x00000002UL
+#define CKA_LABEL 0x00000003UL
+#define CKA_APPLICATION 0x00000010UL
+#define CKA_VALUE 0x00000011UL
+#define CKA_OBJECT_ID 0x00000012UL
+#define CKA_CERTIFICATE_TYPE 0x00000080UL
+#define CKA_ISSUER 0x00000081UL
+#define CKA_SERIAL_NUMBER 0x00000082UL
+#define CKA_AC_ISSUER 0x00000083UL
+#define CKA_OWNER 0x00000084UL
+#define CKA_ATTR_TYPES 0x00000085UL
+#define CKA_TRUSTED 0x00000086UL
+#define CKA_CERTIFICATE_CATEGORY 0x00000087UL
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088UL
+#define CKA_URL 0x00000089UL
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008AUL
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008BUL
+#define CKA_NAME_HASH_ALGORITHM 0x0000008CUL
+#define CKA_CHECK_VALUE 0x00000090UL
+
+#define CKA_KEY_TYPE 0x00000100UL
+#define CKA_SUBJECT 0x00000101UL
+#define CKA_ID 0x00000102UL
+#define CKA_SENSITIVE 0x00000103UL
+#define CKA_ENCRYPT 0x00000104UL
+#define CKA_DECRYPT 0x00000105UL
+#define CKA_WRAP 0x00000106UL
+#define CKA_UNWRAP 0x00000107UL
+#define CKA_SIGN 0x00000108UL
+#define CKA_SIGN_RECOVER 0x00000109UL
+#define CKA_VERIFY 0x0000010AUL
+#define CKA_VERIFY_RECOVER 0x0000010BUL
+#define CKA_DERIVE 0x0000010CUL
+#define CKA_START_DATE 0x00000110UL
+#define CKA_END_DATE 0x00000111UL
+#define CKA_MODULUS 0x00000120UL
+#define CKA_MODULUS_BITS 0x00000121UL
+#define CKA_PUBLIC_EXPONENT 0x00000122UL
+#define CKA_PRIVATE_EXPONENT 0x00000123UL
+#define CKA_PRIME_1 0x00000124UL
+#define CKA_PRIME_2 0x00000125UL
+#define CKA_EXPONENT_1 0x00000126UL
+#define CKA_EXPONENT_2 0x00000127UL
+#define CKA_COEFFICIENT 0x00000128UL
+#define CKA_PUBLIC_KEY_INFO 0x00000129UL
+#define CKA_PRIME 0x00000130UL
+#define CKA_SUBPRIME 0x00000131UL
+#define CKA_BASE 0x00000132UL
+
+#define CKA_PRIME_BITS 0x00000133UL
+#define CKA_SUBPRIME_BITS 0x00000134UL
+#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
+
+#define CKA_VALUE_BITS 0x00000160UL
+#define CKA_VALUE_LEN 0x00000161UL
+#define CKA_EXTRACTABLE 0x00000162UL
+#define CKA_LOCAL 0x00000163UL
+#define CKA_NEVER_EXTRACTABLE 0x00000164UL
+#define CKA_ALWAYS_SENSITIVE 0x00000165UL
+#define CKA_KEY_GEN_MECHANISM 0x00000166UL
+
+#define CKA_MODIFIABLE 0x00000170UL
+#define CKA_COPYABLE 0x00000171UL
+
+#define CKA_DESTROYABLE 0x00000172UL
+
+#define CKA_ECDSA_PARAMS 0x00000180UL /* Deprecated */
+#define CKA_EC_PARAMS 0x00000180UL
+
+#define CKA_EC_POINT 0x00000181UL
+
+#define CKA_SECONDARY_AUTH 0x00000200UL /* Deprecated */
+#define CKA_AUTH_PIN_FLAGS 0x00000201UL /* Deprecated */
+
+#define CKA_ALWAYS_AUTHENTICATE 0x00000202UL
+
+#define CKA_WRAP_WITH_TRUSTED 0x00000210UL
+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211UL)
+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212UL)
+#define CKA_DERIVE_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000213UL)
+
+#define CKA_OTP_FORMAT 0x00000220UL
+#define CKA_OTP_LENGTH 0x00000221UL
+#define CKA_OTP_TIME_INTERVAL 0x00000222UL
+#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223UL
+#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224UL
+#define CKA_OTP_TIME_REQUIREMENT 0x00000225UL
+#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226UL
+#define CKA_OTP_PIN_REQUIREMENT 0x00000227UL
+#define CKA_OTP_COUNTER 0x0000022EUL
+#define CKA_OTP_TIME 0x0000022FUL
+#define CKA_OTP_USER_IDENTIFIER 0x0000022AUL
+#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022BUL
+#define CKA_OTP_SERVICE_LOGO 0x0000022CUL
+#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022DUL
+
+#define CKA_GOSTR3410_PARAMS 0x00000250UL
+#define CKA_GOSTR3411_PARAMS 0x00000251UL
+#define CKA_GOST28147_PARAMS 0x00000252UL
+
+#define CKA_HW_FEATURE_TYPE 0x00000300UL
+#define CKA_RESET_ON_INIT 0x00000301UL
+#define CKA_HAS_RESET 0x00000302UL
+
+#define CKA_PIXEL_X 0x00000400UL
+#define CKA_PIXEL_Y 0x00000401UL
+#define CKA_RESOLUTION 0x00000402UL
+#define CKA_CHAR_ROWS 0x00000403UL
+#define CKA_CHAR_COLUMNS 0x00000404UL
+#define CKA_COLOR 0x00000405UL
+#define CKA_BITS_PER_PIXEL 0x00000406UL
+#define CKA_CHAR_SETS 0x00000480UL
+#define CKA_ENCODING_METHODS 0x00000481UL
+#define CKA_MIME_TYPES 0x00000482UL
+#define CKA_MECHANISM_TYPE 0x00000500UL
+#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501UL
+#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502UL
+#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503UL
+#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600UL)
+
+#define CKA_VENDOR_DEFINED 0x80000000UL
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute
+ */
+typedef struct CK_ATTRIBUTE {
+ CK_ATTRIBUTE_TYPE type;
+ CK_VOID_PTR pValue;
+ CK_ULONG ulValueLen; /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE{
+ CK_CHAR year[4]; /* the year ("1900" - "9999") */
+ CK_CHAR month[2]; /* the month ("01" - "12") */
+ CK_CHAR day[2]; /* the day ("01" - "31") */
+} CK_DATE;
+
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type
+ */
+typedef CK_ULONG CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000UL
+#define CKM_RSA_PKCS 0x00000001UL
+#define CKM_RSA_9796 0x00000002UL
+#define CKM_RSA_X_509 0x00000003UL
+
+#define CKM_MD2_RSA_PKCS 0x00000004UL
+#define CKM_MD5_RSA_PKCS 0x00000005UL
+#define CKM_SHA1_RSA_PKCS 0x00000006UL
+
+#define CKM_RIPEMD128_RSA_PKCS 0x00000007UL
+#define CKM_RIPEMD160_RSA_PKCS 0x00000008UL
+#define CKM_RSA_PKCS_OAEP 0x00000009UL
+
+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000AUL
+#define CKM_RSA_X9_31 0x0000000BUL
+#define CKM_SHA1_RSA_X9_31 0x0000000CUL
+#define CKM_RSA_PKCS_PSS 0x0000000DUL
+#define CKM_SHA1_RSA_PKCS_PSS 0x0000000EUL
+
+#define CKM_DSA_KEY_PAIR_GEN 0x00000010UL
+#define CKM_DSA 0x00000011UL
+#define CKM_DSA_SHA1 0x00000012UL
+#define CKM_DSA_SHA224 0x00000013UL
+#define CKM_DSA_SHA256 0x00000014UL
+#define CKM_DSA_SHA384 0x00000015UL
+#define CKM_DSA_SHA512 0x00000016UL
+
+#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020UL
+#define CKM_DH_PKCS_DERIVE 0x00000021UL
+
+#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030UL
+#define CKM_X9_42_DH_DERIVE 0x00000031UL
+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032UL
+#define CKM_X9_42_MQV_DERIVE 0x00000033UL
+
+#define CKM_SHA256_RSA_PKCS 0x00000040UL
+#define CKM_SHA384_RSA_PKCS 0x00000041UL
+#define CKM_SHA512_RSA_PKCS 0x00000042UL
+#define CKM_SHA256_RSA_PKCS_PSS 0x00000043UL
+#define CKM_SHA384_RSA_PKCS_PSS 0x00000044UL
+#define CKM_SHA512_RSA_PKCS_PSS 0x00000045UL
+
+#define CKM_SHA224_RSA_PKCS 0x00000046UL
+#define CKM_SHA224_RSA_PKCS_PSS 0x00000047UL
+
+#define CKM_SHA512_224 0x00000048UL
+#define CKM_SHA512_224_HMAC 0x00000049UL
+#define CKM_SHA512_224_HMAC_GENERAL 0x0000004AUL
+#define CKM_SHA512_224_KEY_DERIVATION 0x0000004BUL
+#define CKM_SHA512_256 0x0000004CUL
+#define CKM_SHA512_256_HMAC 0x0000004DUL
+#define CKM_SHA512_256_HMAC_GENERAL 0x0000004EUL
+#define CKM_SHA512_256_KEY_DERIVATION 0x0000004FUL
+
+#define CKM_SHA512_T 0x00000050UL
+#define CKM_SHA512_T_HMAC 0x00000051UL
+#define CKM_SHA512_T_HMAC_GENERAL 0x00000052UL
+#define CKM_SHA512_T_KEY_DERIVATION 0x00000053UL
+
+#define CKM_RC2_KEY_GEN 0x00000100UL
+#define CKM_RC2_ECB 0x00000101UL
+#define CKM_RC2_CBC 0x00000102UL
+#define CKM_RC2_MAC 0x00000103UL
+
+#define CKM_RC2_MAC_GENERAL 0x00000104UL
+#define CKM_RC2_CBC_PAD 0x00000105UL
+
+#define CKM_RC4_KEY_GEN 0x00000110UL
+#define CKM_RC4 0x00000111UL
+#define CKM_DES_KEY_GEN 0x00000120UL
+#define CKM_DES_ECB 0x00000121UL
+#define CKM_DES_CBC 0x00000122UL
+#define CKM_DES_MAC 0x00000123UL
+
+#define CKM_DES_MAC_GENERAL 0x00000124UL
+#define CKM_DES_CBC_PAD 0x00000125UL
+
+#define CKM_DES2_KEY_GEN 0x00000130UL
+#define CKM_DES3_KEY_GEN 0x00000131UL
+#define CKM_DES3_ECB 0x00000132UL
+#define CKM_DES3_CBC 0x00000133UL
+#define CKM_DES3_MAC 0x00000134UL
+
+#define CKM_DES3_MAC_GENERAL 0x00000135UL
+#define CKM_DES3_CBC_PAD 0x00000136UL
+#define CKM_DES3_CMAC_GENERAL 0x00000137UL
+#define CKM_DES3_CMAC 0x00000138UL
+#define CKM_CDMF_KEY_GEN 0x00000140UL
+#define CKM_CDMF_ECB 0x00000141UL
+#define CKM_CDMF_CBC 0x00000142UL
+#define CKM_CDMF_MAC 0x00000143UL
+#define CKM_CDMF_MAC_GENERAL 0x00000144UL
+#define CKM_CDMF_CBC_PAD 0x00000145UL
+
+#define CKM_DES_OFB64 0x00000150UL
+#define CKM_DES_OFB8 0x00000151UL
+#define CKM_DES_CFB64 0x00000152UL
+#define CKM_DES_CFB8 0x00000153UL
+
+#define CKM_MD2 0x00000200UL
+
+#define CKM_MD2_HMAC 0x00000201UL
+#define CKM_MD2_HMAC_GENERAL 0x00000202UL
+
+#define CKM_MD5 0x00000210UL
+
+#define CKM_MD5_HMAC 0x00000211UL
+#define CKM_MD5_HMAC_GENERAL 0x00000212UL
+
+#define CKM_SHA_1 0x00000220UL
+
+#define CKM_SHA_1_HMAC 0x00000221UL
+#define CKM_SHA_1_HMAC_GENERAL 0x00000222UL
+
+#define CKM_RIPEMD128 0x00000230UL
+#define CKM_RIPEMD128_HMAC 0x00000231UL
+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232UL
+#define CKM_RIPEMD160 0x00000240UL
+#define CKM_RIPEMD160_HMAC 0x00000241UL
+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242UL
+
+#define CKM_SHA256 0x00000250UL
+#define CKM_SHA256_HMAC 0x00000251UL
+#define CKM_SHA256_HMAC_GENERAL 0x00000252UL
+#define CKM_SHA224 0x00000255UL
+#define CKM_SHA224_HMAC 0x00000256UL
+#define CKM_SHA224_HMAC_GENERAL 0x00000257UL
+#define CKM_SHA384 0x00000260UL
+#define CKM_SHA384_HMAC 0x00000261UL
+#define CKM_SHA384_HMAC_GENERAL 0x00000262UL
+#define CKM_SHA512 0x00000270UL
+#define CKM_SHA512_HMAC 0x00000271UL
+#define CKM_SHA512_HMAC_GENERAL 0x00000272UL
+#define CKM_SECURID_KEY_GEN 0x00000280UL
+#define CKM_SECURID 0x00000282UL
+#define CKM_HOTP_KEY_GEN 0x00000290UL
+#define CKM_HOTP 0x00000291UL
+#define CKM_ACTI 0x000002A0UL
+#define CKM_ACTI_KEY_GEN 0x000002A1UL
+
+#define CKM_CAST_KEY_GEN 0x00000300UL
+#define CKM_CAST_ECB 0x00000301UL
+#define CKM_CAST_CBC 0x00000302UL
+#define CKM_CAST_MAC 0x00000303UL
+#define CKM_CAST_MAC_GENERAL 0x00000304UL
+#define CKM_CAST_CBC_PAD 0x00000305UL
+#define CKM_CAST3_KEY_GEN 0x00000310UL
+#define CKM_CAST3_ECB 0x00000311UL
+#define CKM_CAST3_CBC 0x00000312UL
+#define CKM_CAST3_MAC 0x00000313UL
+#define CKM_CAST3_MAC_GENERAL 0x00000314UL
+#define CKM_CAST3_CBC_PAD 0x00000315UL
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST5_KEY_GEN 0x00000320UL
+#define CKM_CAST128_KEY_GEN 0x00000320UL
+#define CKM_CAST5_ECB 0x00000321UL
+#define CKM_CAST128_ECB 0x00000321UL
+#define CKM_CAST5_CBC 0x00000322UL /* Deprecated */
+#define CKM_CAST128_CBC 0x00000322UL
+#define CKM_CAST5_MAC 0x00000323UL /* Deprecated */
+#define CKM_CAST128_MAC 0x00000323UL
+#define CKM_CAST5_MAC_GENERAL 0x00000324UL /* Deprecated */
+#define CKM_CAST128_MAC_GENERAL 0x00000324UL
+#define CKM_CAST5_CBC_PAD 0x00000325UL /* Deprecated */
+#define CKM_CAST128_CBC_PAD 0x00000325UL
+#define CKM_RC5_KEY_GEN 0x00000330UL
+#define CKM_RC5_ECB 0x00000331UL
+#define CKM_RC5_CBC 0x00000332UL
+#define CKM_RC5_MAC 0x00000333UL
+#define CKM_RC5_MAC_GENERAL 0x00000334UL
+#define CKM_RC5_CBC_PAD 0x00000335UL
+#define CKM_IDEA_KEY_GEN 0x00000340UL
+#define CKM_IDEA_ECB 0x00000341UL
+#define CKM_IDEA_CBC 0x00000342UL
+#define CKM_IDEA_MAC 0x00000343UL
+#define CKM_IDEA_MAC_GENERAL 0x00000344UL
+#define CKM_IDEA_CBC_PAD 0x00000345UL
+#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350UL
+#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360UL
+#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362UL
+#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363UL
+#define CKM_XOR_BASE_AND_DATA 0x00000364UL
+#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365UL
+#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370UL
+#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371UL
+#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372UL
+
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373UL
+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374UL
+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375UL
+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376UL
+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377UL
+
+#define CKM_TLS_PRF 0x00000378UL
+
+#define CKM_SSL3_MD5_MAC 0x00000380UL
+#define CKM_SSL3_SHA1_MAC 0x00000381UL
+#define CKM_MD5_KEY_DERIVATION 0x00000390UL
+#define CKM_MD2_KEY_DERIVATION 0x00000391UL
+#define CKM_SHA1_KEY_DERIVATION 0x00000392UL
+
+#define CKM_SHA256_KEY_DERIVATION 0x00000393UL
+#define CKM_SHA384_KEY_DERIVATION 0x00000394UL
+#define CKM_SHA512_KEY_DERIVATION 0x00000395UL
+#define CKM_SHA224_KEY_DERIVATION 0x00000396UL
+
+#define CKM_PBE_MD2_DES_CBC 0x000003A0UL
+#define CKM_PBE_MD5_DES_CBC 0x000003A1UL
+#define CKM_PBE_MD5_CAST_CBC 0x000003A2UL
+#define CKM_PBE_MD5_CAST3_CBC 0x000003A3UL
+#define CKM_PBE_MD5_CAST5_CBC 0x000003A4UL /* Deprecated */
+#define CKM_PBE_MD5_CAST128_CBC 0x000003A4UL
+#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5UL /* Deprecated */
+#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5UL
+#define CKM_PBE_SHA1_RC4_128 0x000003A6UL
+#define CKM_PBE_SHA1_RC4_40 0x000003A7UL
+#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8UL
+#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9UL
+#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AAUL
+#define CKM_PBE_SHA1_RC2_40_CBC 0x000003ABUL
+
+#define CKM_PKCS5_PBKD2 0x000003B0UL
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0UL
+
+#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0UL
+#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1UL
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2UL
+#define CKM_WTLS_PRF 0x000003D3UL
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4UL
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5UL
+
+#define CKM_TLS10_MAC_SERVER 0x000003D6UL
+#define CKM_TLS10_MAC_CLIENT 0x000003D7UL
+#define CKM_TLS12_MAC 0x000003D8UL
+#define CKM_TLS12_KDF 0x000003D9UL
+#define CKM_TLS12_MASTER_KEY_DERIVE 0x000003E0UL
+#define CKM_TLS12_KEY_AND_MAC_DERIVE 0x000003E1UL
+#define CKM_TLS12_MASTER_KEY_DERIVE_DH 0x000003E2UL
+#define CKM_TLS12_KEY_SAFE_DERIVE 0x000003E3UL
+#define CKM_TLS_MAC 0x000003E4UL
+#define CKM_TLS_KDF 0x000003E5UL
+
+#define CKM_KEY_WRAP_LYNKS 0x00000400UL
+#define CKM_KEY_WRAP_SET_OAEP 0x00000401UL
+
+#define CKM_CMS_SIG 0x00000500UL
+#define CKM_KIP_DERIVE 0x00000510UL
+#define CKM_KIP_WRAP 0x00000511UL
+#define CKM_KIP_MAC 0x00000512UL
+
+#define CKM_CAMELLIA_KEY_GEN 0x00000550UL
+#define CKM_CAMELLIA_ECB 0x00000551UL
+#define CKM_CAMELLIA_CBC 0x00000552UL
+#define CKM_CAMELLIA_MAC 0x00000553UL
+#define CKM_CAMELLIA_MAC_GENERAL 0x00000554UL
+#define CKM_CAMELLIA_CBC_PAD 0x00000555UL
+#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556UL
+#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557UL
+#define CKM_CAMELLIA_CTR 0x00000558UL
+
+#define CKM_ARIA_KEY_GEN 0x00000560UL
+#define CKM_ARIA_ECB 0x00000561UL
+#define CKM_ARIA_CBC 0x00000562UL
+#define CKM_ARIA_MAC 0x00000563UL
+#define CKM_ARIA_MAC_GENERAL 0x00000564UL
+#define CKM_ARIA_CBC_PAD 0x00000565UL
+#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566UL
+#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567UL
+
+#define CKM_SEED_KEY_GEN 0x00000650UL
+#define CKM_SEED_ECB 0x00000651UL
+#define CKM_SEED_CBC 0x00000652UL
+#define CKM_SEED_MAC 0x00000653UL
+#define CKM_SEED_MAC_GENERAL 0x00000654UL
+#define CKM_SEED_CBC_PAD 0x00000655UL
+#define CKM_SEED_ECB_ENCRYPT_DATA 0x00000656UL
+#define CKM_SEED_CBC_ENCRYPT_DATA 0x00000657UL
+
+#define CKM_SKIPJACK_KEY_GEN 0x00001000UL
+#define CKM_SKIPJACK_ECB64 0x00001001UL
+#define CKM_SKIPJACK_CBC64 0x00001002UL
+#define CKM_SKIPJACK_OFB64 0x00001003UL
+#define CKM_SKIPJACK_CFB64 0x00001004UL
+#define CKM_SKIPJACK_CFB32 0x00001005UL
+#define CKM_SKIPJACK_CFB16 0x00001006UL
+#define CKM_SKIPJACK_CFB8 0x00001007UL
+#define CKM_SKIPJACK_WRAP 0x00001008UL
+#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009UL
+#define CKM_SKIPJACK_RELAYX 0x0000100aUL
+#define CKM_KEA_KEY_PAIR_GEN 0x00001010UL
+#define CKM_KEA_KEY_DERIVE 0x00001011UL
+#define CKM_KEA_DERIVE 0x00001012UL
+#define CKM_FORTEZZA_TIMESTAMP 0x00001020UL
+#define CKM_BATON_KEY_GEN 0x00001030UL
+#define CKM_BATON_ECB128 0x00001031UL
+#define CKM_BATON_ECB96 0x00001032UL
+#define CKM_BATON_CBC128 0x00001033UL
+#define CKM_BATON_COUNTER 0x00001034UL
+#define CKM_BATON_SHUFFLE 0x00001035UL
+#define CKM_BATON_WRAP 0x00001036UL
+
+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040UL /* Deprecated */
+#define CKM_EC_KEY_PAIR_GEN 0x00001040UL
+
+#define CKM_ECDSA 0x00001041UL
+#define CKM_ECDSA_SHA1 0x00001042UL
+#define CKM_ECDSA_SHA224 0x00001043UL
+#define CKM_ECDSA_SHA256 0x00001044UL
+#define CKM_ECDSA_SHA384 0x00001045UL
+#define CKM_ECDSA_SHA512 0x00001046UL
+
+#define CKM_ECDH1_DERIVE 0x00001050UL
+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051UL
+#define CKM_ECMQV_DERIVE 0x00001052UL
+
+#define CKM_ECDH_AES_KEY_WRAP 0x00001053UL
+#define CKM_RSA_AES_KEY_WRAP 0x00001054UL
+
+#define CKM_JUNIPER_KEY_GEN 0x00001060UL
+#define CKM_JUNIPER_ECB128 0x00001061UL
+#define CKM_JUNIPER_CBC128 0x00001062UL
+#define CKM_JUNIPER_COUNTER 0x00001063UL
+#define CKM_JUNIPER_SHUFFLE 0x00001064UL
+#define CKM_JUNIPER_WRAP 0x00001065UL
+#define CKM_FASTHASH 0x00001070UL
+
+#define CKM_AES_KEY_GEN 0x00001080UL
+#define CKM_AES_ECB 0x00001081UL
+#define CKM_AES_CBC 0x00001082UL
+#define CKM_AES_MAC 0x00001083UL
+#define CKM_AES_MAC_GENERAL 0x00001084UL
+#define CKM_AES_CBC_PAD 0x00001085UL
+#define CKM_AES_CTR 0x00001086UL
+#define CKM_AES_GCM 0x00001087UL
+#define CKM_AES_CCM 0x00001088UL
+#define CKM_AES_CTS 0x00001089UL
+#define CKM_AES_CMAC 0x0000108AUL
+#define CKM_AES_CMAC_GENERAL 0x0000108BUL
+
+#define CKM_AES_XCBC_MAC 0x0000108CUL
+#define CKM_AES_XCBC_MAC_96 0x0000108DUL
+#define CKM_AES_GMAC 0x0000108EUL
+
+#define CKM_BLOWFISH_KEY_GEN 0x00001090UL
+#define CKM_BLOWFISH_CBC 0x00001091UL
+#define CKM_TWOFISH_KEY_GEN 0x00001092UL
+#define CKM_TWOFISH_CBC 0x00001093UL
+#define CKM_BLOWFISH_CBC_PAD 0x00001094UL
+#define CKM_TWOFISH_CBC_PAD 0x00001095UL
+
+#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100UL
+#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101UL
+#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102UL
+#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103UL
+#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104UL
+#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105UL
+
+#define CKM_GOSTR3410_KEY_PAIR_GEN 0x00001200UL
+#define CKM_GOSTR3410 0x00001201UL
+#define CKM_GOSTR3410_WITH_GOSTR3411 0x00001202UL
+#define CKM_GOSTR3410_KEY_WRAP 0x00001203UL
+#define CKM_GOSTR3410_DERIVE 0x00001204UL
+#define CKM_GOSTR3411 0x00001210UL
+#define CKM_GOSTR3411_HMAC 0x00001211UL
+#define CKM_GOST28147_KEY_GEN 0x00001220UL
+#define CKM_GOST28147_ECB 0x00001221UL
+#define CKM_GOST28147 0x00001222UL
+#define CKM_GOST28147_MAC 0x00001223UL
+#define CKM_GOST28147_KEY_WRAP 0x00001224UL
+
+#define CKM_DSA_PARAMETER_GEN 0x00002000UL
+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001UL
+#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002UL
+#define CKM_DSA_PROBABLISTIC_PARAMETER_GEN 0x00002003UL
+#define CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN 0x00002004UL
+
+#define CKM_AES_OFB 0x00002104UL
+#define CKM_AES_CFB64 0x00002105UL
+#define CKM_AES_CFB8 0x00002106UL
+#define CKM_AES_CFB128 0x00002107UL
+
+#define CKM_AES_CFB1 0x00002108UL
+#define CKM_AES_KEY_WRAP 0x00002109UL /* WAS: 0x00001090 */
+#define CKM_AES_KEY_WRAP_PAD 0x0000210AUL /* WAS: 0x00001091 */
+
+#define CKM_RSA_PKCS_TPM_1_1 0x00004001UL
+#define CKM_RSA_PKCS_OAEP_TPM_1_1 0x00004002UL
+
+#define CKM_VENDOR_DEFINED 0x80000000UL
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism
+ */
+typedef struct CK_MECHANISM {
+ CK_MECHANISM_TYPE mechanism;
+ CK_VOID_PTR pParameter;
+ CK_ULONG ulParameterLen; /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism
+ */
+typedef struct CK_MECHANISM_INFO {
+ CK_ULONG ulMinKeySize;
+ CK_ULONG ulMaxKeySize;
+ CK_FLAGS flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ * Bit Flag Mask Meaning */
+#define CKF_HW 0x00000001UL /* performed by HW */
+
+/* Specify whether or not a mechanism can be used for a particular task */
+#define CKF_ENCRYPT 0x00000100UL
+#define CKF_DECRYPT 0x00000200UL
+#define CKF_DIGEST 0x00000400UL
+#define CKF_SIGN 0x00000800UL
+#define CKF_SIGN_RECOVER 0x00001000UL
+#define CKF_VERIFY 0x00002000UL
+#define CKF_VERIFY_RECOVER 0x00004000UL
+#define CKF_GENERATE 0x00008000UL
+#define CKF_GENERATE_KEY_PAIR 0x00010000UL
+#define CKF_WRAP 0x00020000UL
+#define CKF_UNWRAP 0x00040000UL
+#define CKF_DERIVE 0x00080000UL
+
+/* Describe a token's EC capabilities not available in mechanism
+ * information.
+ */
+#define CKF_EC_F_P 0x00100000UL
+#define CKF_EC_F_2M 0x00200000UL
+#define CKF_EC_ECPARAMETERS 0x00400000UL
+#define CKF_EC_NAMEDCURVE 0x00800000UL
+#define CKF_EC_UNCOMPRESS 0x01000000UL
+#define CKF_EC_COMPRESS 0x02000000UL
+
+#define CKF_EXTENSION 0x80000000UL
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+/* CK_RV is a value that identifies the return value of a
+ * Cryptoki function
+ */
+typedef CK_ULONG CK_RV;
+
+#define CKR_OK 0x00000000UL
+#define CKR_CANCEL 0x00000001UL
+#define CKR_HOST_MEMORY 0x00000002UL
+#define CKR_SLOT_ID_INVALID 0x00000003UL
+
+#define CKR_GENERAL_ERROR 0x00000005UL
+#define CKR_FUNCTION_FAILED 0x00000006UL
+
+#define CKR_ARGUMENTS_BAD 0x00000007UL
+#define CKR_NO_EVENT 0x00000008UL
+#define CKR_NEED_TO_CREATE_THREADS 0x00000009UL
+#define CKR_CANT_LOCK 0x0000000AUL
+
+#define CKR_ATTRIBUTE_READ_ONLY 0x00000010UL
+#define CKR_ATTRIBUTE_SENSITIVE 0x00000011UL
+#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012UL
+#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013UL
+
+#define CKR_ACTION_PROHIBITED 0x0000001BUL
+
+#define CKR_DATA_INVALID 0x00000020UL
+#define CKR_DATA_LEN_RANGE 0x00000021UL
+#define CKR_DEVICE_ERROR 0x00000030UL
+#define CKR_DEVICE_MEMORY 0x00000031UL
+#define CKR_DEVICE_REMOVED 0x00000032UL
+#define CKR_ENCRYPTED_DATA_INVALID 0x00000040UL
+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041UL
+#define CKR_FUNCTION_CANCELED 0x00000050UL
+#define CKR_FUNCTION_NOT_PARALLEL 0x00000051UL
+
+#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054UL
+
+#define CKR_KEY_HANDLE_INVALID 0x00000060UL
+
+#define CKR_KEY_SIZE_RANGE 0x00000062UL
+#define CKR_KEY_TYPE_INCONSISTENT 0x00000063UL
+
+#define CKR_KEY_NOT_NEEDED 0x00000064UL
+#define CKR_KEY_CHANGED 0x00000065UL
+#define CKR_KEY_NEEDED 0x00000066UL
+#define CKR_KEY_INDIGESTIBLE 0x00000067UL
+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068UL
+#define CKR_KEY_NOT_WRAPPABLE 0x00000069UL
+#define CKR_KEY_UNEXTRACTABLE 0x0000006AUL
+
+#define CKR_MECHANISM_INVALID 0x00000070UL
+#define CKR_MECHANISM_PARAM_INVALID 0x00000071UL
+
+#define CKR_OBJECT_HANDLE_INVALID 0x00000082UL
+#define CKR_OPERATION_ACTIVE 0x00000090UL
+#define CKR_OPERATION_NOT_INITIALIZED 0x00000091UL
+#define CKR_PIN_INCORRECT 0x000000A0UL
+#define CKR_PIN_INVALID 0x000000A1UL
+#define CKR_PIN_LEN_RANGE 0x000000A2UL
+
+#define CKR_PIN_EXPIRED 0x000000A3UL
+#define CKR_PIN_LOCKED 0x000000A4UL
+
+#define CKR_SESSION_CLOSED 0x000000B0UL
+#define CKR_SESSION_COUNT 0x000000B1UL
+#define CKR_SESSION_HANDLE_INVALID 0x000000B3UL
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4UL
+#define CKR_SESSION_READ_ONLY 0x000000B5UL
+#define CKR_SESSION_EXISTS 0x000000B6UL
+
+#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7UL
+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8UL
+
+#define CKR_SIGNATURE_INVALID 0x000000C0UL
+#define CKR_SIGNATURE_LEN_RANGE 0x000000C1UL
+#define CKR_TEMPLATE_INCOMPLETE 0x000000D0UL
+#define CKR_TEMPLATE_INCONSISTENT 0x000000D1UL
+#define CKR_TOKEN_NOT_PRESENT 0x000000E0UL
+#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1UL
+#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2UL
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0UL
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1UL
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2UL
+#define CKR_USER_ALREADY_LOGGED_IN 0x00000100UL
+#define CKR_USER_NOT_LOGGED_IN 0x00000101UL
+#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102UL
+#define CKR_USER_TYPE_INVALID 0x00000103UL
+
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104UL
+#define CKR_USER_TOO_MANY_TYPES 0x00000105UL
+
+#define CKR_WRAPPED_KEY_INVALID 0x00000110UL
+#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112UL
+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113UL
+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114UL
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115UL
+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120UL
+
+#define CKR_RANDOM_NO_RNG 0x00000121UL
+
+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130UL
+
+#define CKR_CURVE_NOT_SUPPORTED 0x00000140UL
+
+#define CKR_BUFFER_TOO_SMALL 0x00000150UL
+#define CKR_SAVED_STATE_INVALID 0x00000160UL
+#define CKR_INFORMATION_SENSITIVE 0x00000170UL
+#define CKR_STATE_UNSAVEABLE 0x00000180UL
+
+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190UL
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191UL
+#define CKR_MUTEX_BAD 0x000001A0UL
+#define CKR_MUTEX_NOT_LOCKED 0x000001A1UL
+
+#define CKR_NEW_PIN_MODE 0x000001B0UL
+#define CKR_NEXT_OTP 0x000001B1UL
+
+#define CKR_EXCEEDED_MAX_ITERATIONS 0x000001B5UL
+#define CKR_FIPS_SELF_TEST_FAILED 0x000001B6UL
+#define CKR_LIBRARY_LOAD_FAILED 0x000001B7UL
+#define CKR_PIN_TOO_WEAK 0x000001B8UL
+#define CKR_PUBLIC_KEY_INVALID 0x000001B9UL
+
+#define CKR_FUNCTION_REJECTED 0x00000200UL
+
+#define CKR_VENDOR_DEFINED 0x80000000UL
+
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication /* passed to C_OpenSession */
+);
+
+
+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
+ * version and pointers of appropriate types to all the
+ * Cryptoki functions
+ */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object
+ */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
+);
+
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object
+ */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex
+ */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize
+ */
+typedef struct CK_C_INITIALIZE_ARGS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001UL
+#define CKF_OS_LOCKING_OK 0x00000002UL
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK 1
+
+/* CK_RSA_PKCS_MGF_TYPE is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme.
+ */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+#define CKG_MGF1_SHA1 0x00000001UL
+#define CKG_MGF1_SHA256 0x00000002UL
+#define CKG_MGF1_SHA384 0x00000003UL
+#define CKG_MGF1_SHA512 0x00000004UL
+#define CKG_MGF1_SHA224 0x00000005UL
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme.
+ */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED 0x00000001UL
+
+/* CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism.
+ */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s).
+ */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_ULONG sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL 0x00000001UL
+#define CKD_SHA1_KDF 0x00000002UL
+
+/* The following X9.42 DH key derivation functions are defined */
+#define CKD_SHA1_KDF_ASN1 0x00000003UL
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004UL
+#define CKD_SHA224_KDF 0x00000005UL
+#define CKD_SHA256_KDF 0x00000006UL
+#define CKD_SHA384_KDF 0x00000007UL
+#define CKD_SHA512_KDF 0x00000008UL
+#define CKD_CPDIVERSIFY_KDF 0x00000009UL
+
+
+/* CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
+ * where each party contributes one key pair.
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
+
+/*
+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs.
+ */
+typedef struct CK_ECDH2_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_ECDH2_DERIVE_PARAMS;
+
+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_ECMQV_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+ CK_OBJECT_HANDLE publicKey;
+} CK_ECMQV_DERIVE_PARAMS;
+
+typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
+
+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms
+ */
+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
+
+/* CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
+ * contributes one key pair
+ */
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_X9_42_DH1_DERIVE_PARAMS;
+
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
+
+/* CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
+ * mechanisms, where each party contributes two key pairs
+ */
+typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_X9_42_DH2_DERIVE_PARAMS;
+
+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+ CK_OBJECT_HANDLE publicKey;
+} CK_X9_42_MQV_DERIVE_PARAMS;
+
+typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism
+ */
+typedef struct CK_KEA_DERIVE_PARAMS {
+ CK_BBOOL isSender;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pRandomB;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
+ * holds the effective keysize
+ */
+typedef CK_ULONG CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism
+ */
+typedef struct CK_RC2_CBC_PARAMS {
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+ CK_BYTE iv[8]; /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism
+ */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms
+ */
+typedef struct CK_RC5_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism
+ */
+typedef struct CK_RC5_CBC_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_BYTE_PTR pIv; /* pointer to IV */
+ CK_ULONG ulIvLen; /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism
+ */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
+ * the MAC
+ */
+typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[8];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism
+ */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pPassword;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPAndGLen;
+ CK_ULONG ulQLen;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pPrimeP;
+ CK_BYTE_PTR pBaseG;
+ CK_BYTE_PTR pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
+ CK_SKIPJACK_PRIVATE_WRAP_PARAMS_PTR;
+
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism
+ */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+ CK_ULONG ulOldWrappedXLen;
+ CK_BYTE_PTR pOldWrappedX;
+ CK_ULONG ulOldPasswordLen;
+ CK_BYTE_PTR pOldPassword;
+ CK_ULONG ulOldPublicDataLen;
+ CK_BYTE_PTR pOldPublicData;
+ CK_ULONG ulOldRandomLen;
+ CK_BYTE_PTR pOldRandomA;
+ CK_ULONG ulNewPasswordLen;
+ CK_BYTE_PTR pNewPassword;
+ CK_ULONG ulNewPublicDataLen;
+ CK_BYTE_PTR pNewPublicData;
+ CK_ULONG ulNewRandomLen;
+ CK_BYTE_PTR pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
+ CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+
+typedef struct CK_PBE_PARAMS {
+ CK_BYTE_PTR pInitVector;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_ULONG ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism
+ */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+ CK_BYTE bBC; /* block contents byte */
+ CK_BYTE_PTR pX; /* extra data */
+ CK_ULONG ulXLen; /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+typedef struct CK_SSL3_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hClientMacSecret;
+ CK_OBJECT_HANDLE hServerMacSecret;
+ CK_OBJECT_HANDLE hClientKey;
+ CK_OBJECT_HANDLE hServerKey;
+ CK_BYTE_PTR pIVClient;
+ CK_BYTE_PTR pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+typedef struct CK_TLS_PRF_PARAMS {
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLen;
+ CK_BYTE_PTR pOutput;
+ CK_ULONG_PTR pulOutputLen;
+} CK_TLS_PRF_PARAMS;
+
+typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
+
+typedef struct CK_WTLS_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_WTLS_RANDOM_DATA;
+
+typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
+
+typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_WTLS_RANDOM_DATA RandomInfo;
+ CK_BYTE_PTR pVersion;
+} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
+
+typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_WTLS_PRF_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLen;
+ CK_BYTE_PTR pOutput;
+ CK_ULONG_PTR pulOutputLen;
+} CK_WTLS_PRF_PARAMS;
+
+typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hMacSecret;
+ CK_OBJECT_HANDLE hKey;
+ CK_BYTE_PTR pIV;
+} CK_WTLS_KEY_MAT_OUT;
+
+typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_ULONG ulSequenceNumber;
+ CK_BBOOL bIsExport;
+ CK_WTLS_RANDOM_DATA RandomInfo;
+ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_WTLS_KEY_MAT_PARAMS;
+
+typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
+
+typedef struct CK_CMS_SIG_PARAMS {
+ CK_OBJECT_HANDLE certificateHandle;
+ CK_MECHANISM_PTR pSigningMechanism;
+ CK_MECHANISM_PTR pDigestMechanism;
+ CK_UTF8CHAR_PTR pContentType;
+ CK_BYTE_PTR pRequestedAttributes;
+ CK_ULONG ulRequestedAttributesLen;
+ CK_BYTE_PTR pRequiredAttributes;
+ CK_ULONG ulRequiredAttributesLen;
+} CK_CMS_SIG_PARAMS;
+
+typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+ CK_BYTE_PTR pData;
+ CK_ULONG ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
+ CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key
+ */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2.
+ */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR \
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001UL
+#define CKP_PKCS5_PBKD2_HMAC_GOSTR3411 0x00000002UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA224 0x00000003UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA256 0x00000004UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA384 0x00000005UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA512 0x00000006UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA512_224 0x00000007UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA512_256 0x00000008UL
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2.
+ */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR \
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED 0x00000001UL
+
+/* CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism.
+ */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG_PTR ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PARAMS2 is a corrected version of the CK_PKCS5_PBKD2_PARAMS
+ * structure that provides the parameters to the CKM_PKCS5_PBKD2 mechanism
+ * noting that the ulPasswordLen field is a CK_ULONG and not a CK_ULONG_PTR.
+ */
+typedef struct CK_PKCS5_PBKD2_PARAMS2 {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS2;
+
+typedef CK_PKCS5_PBKD2_PARAMS2 CK_PTR CK_PKCS5_PBKD2_PARAMS2_PTR;
+
+typedef CK_ULONG CK_OTP_PARAM_TYPE;
+typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* backward compatibility */
+
+typedef struct CK_OTP_PARAM {
+ CK_OTP_PARAM_TYPE type;
+ CK_VOID_PTR pValue;
+ CK_ULONG ulValueLen;
+} CK_OTP_PARAM;
+
+typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;
+
+typedef struct CK_OTP_PARAMS {
+ CK_OTP_PARAM_PTR pParams;
+ CK_ULONG ulCount;
+} CK_OTP_PARAMS;
+
+typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;
+
+typedef struct CK_OTP_SIGNATURE_INFO {
+ CK_OTP_PARAM_PTR pParams;
+ CK_ULONG ulCount;
+} CK_OTP_SIGNATURE_INFO;
+
+typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;
+
+#define CK_OTP_VALUE 0UL
+#define CK_OTP_PIN 1UL
+#define CK_OTP_CHALLENGE 2UL
+#define CK_OTP_TIME 3UL
+#define CK_OTP_COUNTER 4UL
+#define CK_OTP_FLAGS 5UL
+#define CK_OTP_OUTPUT_LENGTH 6UL
+#define CK_OTP_OUTPUT_FORMAT 7UL
+
+#define CKF_NEXT_OTP 0x00000001UL
+#define CKF_EXCLUDE_TIME 0x00000002UL
+#define CKF_EXCLUDE_COUNTER 0x00000004UL
+#define CKF_EXCLUDE_CHALLENGE 0x00000008UL
+#define CKF_EXCLUDE_PIN 0x00000010UL
+#define CKF_USER_FRIENDLY_OTP 0x00000020UL
+
+typedef struct CK_KIP_PARAMS {
+ CK_MECHANISM_PTR pMechanism;
+ CK_OBJECT_HANDLE hKey;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+} CK_KIP_PARAMS;
+
+typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;
+
+typedef struct CK_AES_CTR_PARAMS {
+ CK_ULONG ulCounterBits;
+ CK_BYTE cb[16];
+} CK_AES_CTR_PARAMS;
+
+typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;
+
+typedef struct CK_GCM_PARAMS {
+ CK_BYTE_PTR pIv;
+ CK_ULONG ulIvLen;
+ CK_ULONG ulIvBits;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulTagBits;
+} CK_GCM_PARAMS;
+
+typedef CK_GCM_PARAMS CK_PTR CK_GCM_PARAMS_PTR;
+
+typedef struct CK_CCM_PARAMS {
+ CK_ULONG ulDataLen;
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceLen;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulMACLen;
+} CK_CCM_PARAMS;
+
+typedef CK_CCM_PARAMS CK_PTR CK_CCM_PARAMS_PTR;
+
+/* Deprecated. Use CK_GCM_PARAMS */
+typedef struct CK_AES_GCM_PARAMS {
+ CK_BYTE_PTR pIv;
+ CK_ULONG ulIvLen;
+ CK_ULONG ulIvBits;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulTagBits;
+} CK_AES_GCM_PARAMS;
+
+typedef CK_AES_GCM_PARAMS CK_PTR CK_AES_GCM_PARAMS_PTR;
+
+/* Deprecated. Use CK_CCM_PARAMS */
+typedef struct CK_AES_CCM_PARAMS {
+ CK_ULONG ulDataLen;
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceLen;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulMACLen;
+} CK_AES_CCM_PARAMS;
+
+typedef CK_AES_CCM_PARAMS CK_PTR CK_AES_CCM_PARAMS_PTR;
+
+typedef struct CK_CAMELLIA_CTR_PARAMS {
+ CK_ULONG ulCounterBits;
+ CK_BYTE cb[16];
+} CK_CAMELLIA_CTR_PARAMS;
+
+typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;
+
+typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR \
+ CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR \
+ CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_DSA_PARAMETER_GEN_PARAM {
+ CK_MECHANISM_TYPE hash;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_ULONG ulIndex;
+} CK_DSA_PARAMETER_GEN_PARAM;
+
+typedef CK_DSA_PARAMETER_GEN_PARAM CK_PTR CK_DSA_PARAMETER_GEN_PARAM_PTR;
+
+typedef struct CK_ECDH_AES_KEY_WRAP_PARAMS {
+ CK_ULONG ulAESKeyBits;
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+} CK_ECDH_AES_KEY_WRAP_PARAMS;
+
+typedef CK_ECDH_AES_KEY_WRAP_PARAMS CK_PTR CK_ECDH_AES_KEY_WRAP_PARAMS_PTR;
+
+typedef CK_ULONG CK_JAVA_MIDP_SECURITY_DOMAIN;
+
+typedef CK_ULONG CK_CERTIFICATE_CATEGORY;
+
+typedef struct CK_RSA_AES_KEY_WRAP_PARAMS {
+ CK_ULONG ulAESKeyBits;
+ CK_RSA_PKCS_OAEP_PARAMS_PTR pOAEPParams;
+} CK_RSA_AES_KEY_WRAP_PARAMS;
+
+typedef CK_RSA_AES_KEY_WRAP_PARAMS CK_PTR CK_RSA_AES_KEY_WRAP_PARAMS_PTR;
+
+typedef struct CK_TLS12_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+ CK_MECHANISM_TYPE prfHashMechanism;
+} CK_TLS12_MASTER_KEY_DERIVE_PARAMS;
+
+typedef CK_TLS12_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_TLS12_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+ CK_MECHANISM_TYPE prfHashMechanism;
+} CK_TLS12_KEY_MAT_PARAMS;
+
+typedef CK_TLS12_KEY_MAT_PARAMS CK_PTR CK_TLS12_KEY_MAT_PARAMS_PTR;
+
+typedef struct CK_TLS_KDF_PARAMS {
+ CK_MECHANISM_TYPE prfMechanism;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLength;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_BYTE_PTR pContextData;
+ CK_ULONG ulContextDataLength;
+} CK_TLS_KDF_PARAMS;
+
+typedef CK_TLS_KDF_PARAMS CK_PTR CK_TLS_KDF_PARAMS_PTR;
+
+typedef struct CK_TLS_MAC_PARAMS {
+ CK_MECHANISM_TYPE prfHashMechanism;
+ CK_ULONG ulMacLength;
+ CK_ULONG ulServerOrClient;
+} CK_TLS_MAC_PARAMS;
+
+typedef CK_TLS_MAC_PARAMS CK_PTR CK_TLS_MAC_PARAMS_PTR;
+
+typedef struct CK_GOSTR3410_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pUKM;
+ CK_ULONG ulUKMLen;
+} CK_GOSTR3410_DERIVE_PARAMS;
+
+typedef CK_GOSTR3410_DERIVE_PARAMS CK_PTR CK_GOSTR3410_DERIVE_PARAMS_PTR;
+
+typedef struct CK_GOSTR3410_KEY_WRAP_PARAMS {
+ CK_BYTE_PTR pWrapOID;
+ CK_ULONG ulWrapOIDLen;
+ CK_BYTE_PTR pUKM;
+ CK_ULONG ulUKMLen;
+ CK_OBJECT_HANDLE hKey;
+} CK_GOSTR3410_KEY_WRAP_PARAMS;
+
+typedef CK_GOSTR3410_KEY_WRAP_PARAMS CK_PTR CK_GOSTR3410_KEY_WRAP_PARAMS_PTR;
+
+typedef struct CK_SEED_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_SEED_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_SEED_CBC_ENCRYPT_DATA_PARAMS CK_PTR \
+ CK_SEED_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+#endif /* _PKCS11T_H_ */
+
diff --git a/SoftHSMv2/src/lib/session_mgr/Makefile.am b/SoftHSMv2/src/lib/session_mgr/Makefile.am
new file mode 100644
index 0000000..5186d33
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/Makefile.am
@@ -0,0 +1,17 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../object_store \
+ -I$(srcdir)/../pkcs11 \
+ -I$(srcdir)/../slot_mgr
+
+noinst_LTLIBRARIES = libsofthsm_sessionmgr.la
+libsofthsm_sessionmgr_la_SOURCES = SessionManager.cpp \
+ Session.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/session_mgr/Session.cpp b/SoftHSMv2/src/lib/session_mgr/Session.cpp
new file mode 100644
index 0000000..5db36fd
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/Session.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Session.h
+
+ This class represents a single session
+ *****************************************************************************/
+
+#include "CryptoFactory.h"
+#include "Session.h"
+
+// Constructor
+Session::Session(Slot* inSlot, bool inIsReadWrite, CK_VOID_PTR inPApplication, CK_NOTIFY inNotify)
+{
+ slot = inSlot;
+ token = slot->getToken();
+ isReadWrite = inIsReadWrite;
+ hSession = CK_INVALID_HANDLE;
+ pApplication = inPApplication;
+ notify = inNotify;
+ operation = SESSION_OP_NONE;
+ findOp = NULL;
+ digestOp = NULL;
+ hashAlgo = HashAlgo::Unknown;
+ macOp = NULL;
+ asymmetricCryptoOp = NULL;
+ symmetricCryptoOp = NULL;
+ mechanism = AsymMech::Unknown;
+ reAuthentication = false;
+ allowSinglePartOp = false;
+ allowMultiPartOp = false;
+ publicKey = NULL;
+ privateKey = NULL;
+ symmetricKey = NULL;
+ param = NULL;
+ paramLen = 0;
+}
+
+// Constructor
+Session::Session()
+{
+ slot = NULL;
+ token = NULL;
+ isReadWrite = false;
+ hSession = CK_INVALID_HANDLE;
+ pApplication = NULL;
+ notify = NULL;
+ operation = SESSION_OP_NONE;
+ findOp = NULL;
+ digestOp = NULL;
+ hashAlgo = HashAlgo::Unknown;
+ macOp = NULL;
+ asymmetricCryptoOp = NULL;
+ symmetricCryptoOp = NULL;
+ mechanism = AsymMech::Unknown;
+ reAuthentication = false;
+ allowSinglePartOp = false;
+ allowMultiPartOp = false;
+ publicKey = NULL;
+ privateKey = NULL;
+ symmetricKey = NULL;
+ param = NULL;
+ paramLen = 0;
+}
+
+// Destructor
+Session::~Session()
+{
+ resetOp();
+}
+
+// Get session info
+CK_RV Session::getInfo(CK_SESSION_INFO_PTR pInfo)
+{
+ if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ pInfo->slotID = slot->getSlotID();
+
+ pInfo->state = getState();
+ pInfo->flags = CKF_SERIAL_SESSION;
+ if (isRW())
+ {
+ pInfo->flags |= CKF_RW_SESSION;
+ }
+ pInfo->ulDeviceError = 0;
+
+ return CKR_OK;
+}
+
+// Is a read and write session
+bool Session::isRW()
+{
+ return isReadWrite;
+}
+
+// Get session state
+CK_STATE Session::getState()
+{
+ if (token->isSOLoggedIn())
+ {
+ return CKS_RW_SO_FUNCTIONS;
+ }
+
+ if (token->isUserLoggedIn())
+ {
+ if (isRW())
+ {
+ return CKS_RW_USER_FUNCTIONS;
+ }
+ else
+ {
+ return CKS_RO_USER_FUNCTIONS;
+ }
+ }
+
+ if (isRW())
+ {
+ return CKS_RW_PUBLIC_SESSION;
+ }
+ else
+ {
+ return CKS_RO_PUBLIC_SESSION;
+ }
+}
+
+void Session::setHandle(CK_SESSION_HANDLE inHSession)
+{
+ hSession = inHSession;
+}
+
+CK_SESSION_HANDLE Session::getHandle()
+{
+ return hSession;
+}
+
+// Return the slot that the session is connected to
+Slot* Session::getSlot()
+{
+ return slot;
+}
+
+// Return the token that the session is connected to
+Token* Session::getToken()
+{
+ return token;
+}
+
+// Set the operation type
+void Session::setOpType(int inOperation)
+{
+ operation = inOperation;
+}
+
+// Get the operation type
+int Session::getOpType()
+{
+ return operation;
+}
+
+// Reset the operations
+void Session::resetOp()
+{
+ if (param != NULL)
+ {
+ free(param);
+ param = NULL;
+ paramLen = 0;
+ }
+
+ if (digestOp != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(digestOp);
+ digestOp = NULL;
+ }
+ else if (findOp != NULL)
+ {
+ findOp->recycle();
+ findOp = NULL;
+ }
+ else if (asymmetricCryptoOp != NULL)
+ {
+ if (publicKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePublicKey(publicKey);
+ publicKey = NULL;
+ }
+ if (privateKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePrivateKey(privateKey);
+ privateKey = NULL;
+ }
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymmetricCryptoOp);
+ asymmetricCryptoOp = NULL;
+ }
+ else if (symmetricCryptoOp != NULL)
+ {
+ if (symmetricKey != NULL)
+ {
+ symmetricCryptoOp->recycleKey(symmetricKey);
+ symmetricKey = NULL;
+ }
+ CryptoFactory::i()->recycleSymmetricAlgorithm(symmetricCryptoOp);
+ symmetricCryptoOp = NULL;
+ }
+ else if (macOp != NULL)
+ {
+ if (symmetricKey != NULL)
+ {
+ macOp->recycleKey(symmetricKey);
+ symmetricKey = NULL;
+ }
+ CryptoFactory::i()->recycleMacAlgorithm(macOp);
+ macOp = NULL;
+ }
+
+ operation = SESSION_OP_NONE;
+ reAuthentication = false;
+}
+
+void Session::setFindOp(FindOperation *inFindOp)
+{
+ if (findOp != NULL) {
+ delete findOp;
+ }
+ findOp = inFindOp;
+}
+
+FindOperation *Session::getFindOp()
+{
+ return findOp;
+}
+
+// Set the digesting operator
+void Session::setDigestOp(HashAlgorithm* inDigestOp)
+{
+ if (digestOp != NULL)
+ {
+ CryptoFactory::i()->recycleHashAlgorithm(digestOp);
+ }
+
+ digestOp = inDigestOp;
+}
+
+// Get the digesting operator
+HashAlgorithm* Session::getDigestOp()
+{
+ return digestOp;
+}
+
+void Session::setHashAlgo(HashAlgo::Type inHashAlgo)
+{
+ hashAlgo = inHashAlgo;
+}
+
+HashAlgo::Type Session::getHashAlgo()
+{
+ return hashAlgo;
+}
+
+// Set the MACing operator
+void Session::setMacOp(MacAlgorithm *inMacOp)
+{
+ if (macOp != NULL)
+ {
+ setSymmetricKey(NULL);
+ CryptoFactory::i()->recycleMacAlgorithm(macOp);
+ }
+
+ macOp = inMacOp;
+}
+
+// Get the MACing operator
+MacAlgorithm *Session::getMacOp()
+{
+ return macOp;
+}
+
+void Session::setAsymmetricCryptoOp(AsymmetricAlgorithm *inAsymmetricCryptoOp)
+{
+ if (asymmetricCryptoOp != NULL)
+ {
+ setPublicKey(NULL);
+ setPrivateKey(NULL);
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(asymmetricCryptoOp);
+ }
+
+ asymmetricCryptoOp = inAsymmetricCryptoOp;
+}
+
+AsymmetricAlgorithm *Session::getAsymmetricCryptoOp()
+{
+ return asymmetricCryptoOp;
+}
+
+void Session::setSymmetricCryptoOp(SymmetricAlgorithm *inSymmetricCryptoOp)
+{
+ if (symmetricCryptoOp != NULL)
+ {
+ setSymmetricKey(NULL);
+ CryptoFactory::i()->recycleSymmetricAlgorithm(symmetricCryptoOp);
+ }
+
+ symmetricCryptoOp = inSymmetricCryptoOp;
+}
+
+SymmetricAlgorithm *Session::getSymmetricCryptoOp()
+{
+ return symmetricCryptoOp;
+}
+
+void Session::setMechanism(AsymMech::Type inMechanism)
+{
+ mechanism = inMechanism;
+}
+
+AsymMech::Type Session::getMechanism()
+{
+ return mechanism;
+}
+
+void Session::setParameters(void* inParam, size_t inParamLen)
+{
+ if (inParam == NULL || inParamLen == 0) return;
+
+ if (param != NULL)
+ {
+ free(param);
+ paramLen = 0;
+ }
+
+ param = malloc(inParamLen);
+ if (param != NULL)
+ {
+ memcpy(param, inParam, inParamLen);
+ paramLen = inParamLen;
+ }
+}
+
+void* Session::getParameters(size_t& inParamLen)
+{
+ inParamLen = paramLen;
+ return param;
+}
+
+void Session::setReAuthentication(bool inReAuthentication)
+{
+ reAuthentication = inReAuthentication;
+}
+
+bool Session::getReAuthentication()
+{
+ return reAuthentication;
+}
+
+void Session::setAllowMultiPartOp(bool inAllowMultiPartOp)
+{
+ allowMultiPartOp = inAllowMultiPartOp;
+}
+
+bool Session::getAllowMultiPartOp()
+{
+ return allowMultiPartOp;
+}
+
+void Session::setAllowSinglePartOp(bool inAllowSinglePartOp)
+{
+ allowSinglePartOp = inAllowSinglePartOp;
+}
+
+bool Session::getAllowSinglePartOp()
+{
+ return allowSinglePartOp;
+}
+
+void Session::setPublicKey(PublicKey* inPublicKey)
+{
+ if (asymmetricCryptoOp == NULL)
+ return;
+
+ if (publicKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePublicKey(publicKey);
+ }
+
+ publicKey = inPublicKey;
+}
+
+PublicKey* Session::getPublicKey()
+{
+ return publicKey;
+}
+
+void Session::setPrivateKey(PrivateKey* inPrivateKey)
+{
+ if (asymmetricCryptoOp == NULL)
+ return;
+
+ if (privateKey != NULL)
+ {
+ asymmetricCryptoOp->recyclePrivateKey(privateKey);
+ }
+
+ privateKey = inPrivateKey;
+}
+
+PrivateKey* Session::getPrivateKey()
+{
+ return privateKey;
+}
+
+void Session::setSymmetricKey(SymmetricKey* inSymmetricKey)
+{
+ if (symmetricKey != NULL)
+ {
+ if (macOp) {
+ macOp->recycleKey(symmetricKey);
+ } else if (symmetricCryptoOp) {
+ symmetricCryptoOp->recycleKey(symmetricKey);
+ } else {
+ return;
+ }
+ }
+
+ symmetricKey = inSymmetricKey;
+}
+
+SymmetricKey* Session::getSymmetricKey()
+{
+ return symmetricKey;
+}
diff --git a/SoftHSMv2/src/lib/session_mgr/Session.h b/SoftHSMv2/src/lib/session_mgr/Session.h
new file mode 100644
index 0000000..142aaa5
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/Session.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Session.h
+
+ This class represents a single session
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSION_H
+#define _SOFTHSM_V2_SESSION_H
+
+#include "Slot.h"
+#include "FindOperation.h"
+#include "HashAlgorithm.h"
+#include "MacAlgorithm.h"
+#include "AsymmetricAlgorithm.h"
+#include "SymmetricAlgorithm.h"
+#include "Token.h"
+#include "cryptoki.h"
+
+#define SESSION_OP_NONE 0x0
+#define SESSION_OP_FIND 0x1
+#define SESSION_OP_ENCRYPT 0x2
+#define SESSION_OP_DECRYPT 0x3
+#define SESSION_OP_DIGEST 0x4
+#define SESSION_OP_SIGN 0x5
+#define SESSION_OP_VERIFY 0x6
+#define SESSION_OP_DIGEST_ENCRYPT 0x7
+#define SESSION_OP_DECRYPT_DIGEST 0x8
+#define SESSION_OP_SIGN_ENCRYPT 0x9
+#define SESSION_OP_DECRYPT_VERIFY 0x10
+
+class Session
+{
+public:
+ Session(Slot* inSlot, bool inIsReadWrite, CK_VOID_PTR inPApplication, CK_NOTIFY inNotify);
+
+ // Destructor
+ virtual ~Session();
+
+ // Slot and token
+ Slot* getSlot();
+ Token* getToken();
+
+ // Session properties
+ CK_RV getInfo(CK_SESSION_INFO_PTR pInfo);
+ bool isRW();
+ CK_STATE getState();
+ void setHandle(CK_SESSION_HANDLE inHSession);
+ CK_SESSION_HANDLE getHandle();
+
+ // Operations
+ int getOpType();
+ void setOpType(int inOperation);
+ void resetOp();
+
+ // Find
+ void setFindOp(FindOperation *inFindOp);
+ FindOperation *getFindOp();
+
+ // Digest
+ void setDigestOp(HashAlgorithm* inDigestOp);
+ HashAlgorithm* getDigestOp();
+ void setHashAlgo(HashAlgo::Type inHashAlgo);
+ HashAlgo::Type getHashAlgo();
+
+ // Mac
+ void setMacOp(MacAlgorithm* inMacOp);
+ MacAlgorithm* getMacOp();
+
+ // Asymmetric Crypto
+ void setAsymmetricCryptoOp(AsymmetricAlgorithm* inAsymmetricCryptoOp);
+ AsymmetricAlgorithm* getAsymmetricCryptoOp();
+
+ // Symmetric Crypto
+ void setSymmetricCryptoOp(SymmetricAlgorithm* inSymmetricCryptoOp);
+ SymmetricAlgorithm* getSymmetricCryptoOp();
+
+ void setMechanism(AsymMech::Type inMechanism);
+ AsymMech::Type getMechanism();
+
+ void setParameters(void* inParam, size_t inParamLen);
+ void* getParameters(size_t& inParamLen);
+
+ void setReAuthentication(bool inReAuthentication);
+ bool getReAuthentication();
+
+ void setAllowMultiPartOp(bool inAllowMultiPartOp);
+ bool getAllowMultiPartOp();
+
+ void setAllowSinglePartOp(bool inAllowSinglePartOp);
+ bool getAllowSinglePartOp();
+
+ void setPublicKey(PublicKey* inPublicKey);
+ PublicKey* getPublicKey();
+
+ void setPrivateKey(PrivateKey* inPrivateKey);
+ PrivateKey* getPrivateKey();
+
+ void setSymmetricKey(SymmetricKey* inSymmetricKey);
+ SymmetricKey* getSymmetricKey();
+
+private:
+ // Constructor
+ Session();
+
+ // Slot and token
+ Slot* slot;
+ Token* token;
+
+ // Application data (not in use)
+ CK_VOID_PTR pApplication;
+ CK_NOTIFY notify;
+
+ // Session properties
+ bool isReadWrite;
+ CK_SESSION_HANDLE hSession;
+
+ // Operations
+ int operation;
+
+ // Find
+ FindOperation *findOp;
+
+ // Digest
+ HashAlgorithm* digestOp;
+ HashAlgo::Type hashAlgo;
+
+ // Mac
+ MacAlgorithm* macOp;
+
+ // Asymmetric Crypto
+ AsymmetricAlgorithm* asymmetricCryptoOp;
+
+ // Symmetric Crypto
+ SymmetricAlgorithm* symmetricCryptoOp;
+
+ AsymMech::Type mechanism;
+ void* param;
+ size_t paramLen;
+ bool reAuthentication;
+ bool allowMultiPartOp;
+ bool allowSinglePartOp;
+ PublicKey* publicKey;
+ PrivateKey* privateKey;
+
+ // Symmetric Crypto
+ SymmetricKey* symmetricKey;
+};
+
+#endif // !_SOFTHSM_V2_SESSION_H
diff --git a/SoftHSMv2/src/lib/session_mgr/SessionManager.cpp b/SoftHSMv2/src/lib/session_mgr/SessionManager.cpp
new file mode 100644
index 0000000..b665210
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/SessionManager.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionManager.cpp
+
+ Keeps track of the sessions within SoftHSM. The sessions are stored in a
+ vector. When a session is closed, its spot in the vector will be replaced
+ with NULL. Because we want to keep track of the session ID which is
+ equal to its location in the vector. New sessions will first fill up the NULL
+ locations and if there is no empty spots, then they are added to the end.
+ *****************************************************************************/
+
+#include "SessionManager.h"
+#include "log.h"
+
+// Constructor
+SessionManager::SessionManager()
+{
+ sessionsMutex = MutexFactory::i()->getMutex();
+}
+
+// Destructor
+SessionManager::~SessionManager()
+{
+ std::vector<Session*> toDelete = sessions;
+ sessions.clear();
+
+ for (std::vector<Session*>::iterator i = toDelete.begin(); i != toDelete.end(); i++)
+ {
+ if (*i != NULL) delete *i;
+ }
+
+ MutexFactory::i()->recycleMutex(sessionsMutex);
+}
+
+// Open a new session
+CK_RV SessionManager::openSession
+(
+ Slot* slot,
+ CK_FLAGS flags,
+ CK_VOID_PTR pApplication,
+ CK_NOTIFY notify,
+ CK_SESSION_HANDLE_PTR phSession
+)
+{
+ if (phSession == NULL_PTR) return CKR_ARGUMENTS_BAD;
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+ if ((flags & CKF_SERIAL_SESSION) == 0) return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Get the token
+ Token* token = slot->getToken();
+ if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
+ if (!token->isInitialized()) return CKR_TOKEN_NOT_RECOGNIZED;
+
+ // Can not open a Read-Only session when in SO mode
+ if ((flags & CKF_RW_SESSION) == 0 && token->isSOLoggedIn()) return CKR_SESSION_READ_WRITE_SO_EXISTS;
+
+ // TODO: Do we want to check for maximum number of sessions?
+ // return CKR_SESSION_COUNT
+
+ // Create the session
+ bool rwSession = ((flags & CKF_RW_SESSION) == CKF_RW_SESSION) ? true : false;
+ Session* session = new Session(slot, rwSession, pApplication, notify);
+
+ // First fill any empty spot in the list
+ for (size_t i = 0; i < sessions.size(); i++)
+ {
+ if (sessions[i] != NULL)
+ {
+ continue;
+ }
+
+ sessions[i] = session;
+ session->setHandle(i + 1);
+ *phSession = session->getHandle();
+
+ return CKR_OK;
+ }
+
+ // Or add it to the end
+ sessions.push_back(session);
+ session->setHandle(sessions.size());
+ *phSession = session->getHandle();
+
+ return CKR_OK;
+}
+
+// Close a session
+CK_RV SessionManager::closeSession(CK_SESSION_HANDLE hSession)
+{
+ if (hSession == CK_INVALID_HANDLE) return CKR_SESSION_HANDLE_INVALID;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Check if we are out of range
+ if (hSession > sessions.size()) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if it is a closed session
+ unsigned long sessionID = hSession - 1;
+ if (sessions[sessionID] == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ // Check if this is the last session on the token
+ bool lastSession = true;
+ const CK_SLOT_ID slotID( sessions[sessionID]->getSlot()->getSlotID() );
+ for (size_t i = 0; i < sessions.size(); i++)
+ {
+ if (sessions[i] == NULL) continue;
+
+ if (sessions[i]->getSlot()->getSlotID() == slotID && i != sessionID)
+ {
+ lastSession = false;
+ break;
+ }
+ }
+
+ // Logout if this is the last session on the token
+ if (lastSession)
+ {
+ sessions[sessionID]->getSlot()->getToken()->logout();
+ }
+
+ // Close the session
+ delete sessions[sessionID];
+ sessions[sessionID] = NULL;
+
+ return CKR_OK;
+}
+
+// Close all sessions
+CK_RV SessionManager::closeAllSessions(Slot* slot)
+{
+ if (slot == NULL) return CKR_SLOT_ID_INVALID;
+
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // Get the token
+ Token* token = slot->getToken();
+ if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
+
+ // Close all sessions on this slot
+ const CK_SLOT_ID slotID( slot->getSlotID() );
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() == slotID)
+ {
+ delete *i;
+ *i = NULL;
+ }
+ }
+
+ // Logout from the token
+ token->logout();
+
+ return CKR_OK;
+}
+
+// Get session info
+CK_RV SessionManager::getSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
+{
+ // Get the session
+ Session* session = getSession(hSession);
+ if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+
+ return session->getInfo(pInfo);
+}
+
+// Get the session
+Session* SessionManager::getSession(CK_SESSION_HANDLE hSession)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ // We do not want to get a negative number below
+ if (hSession == CK_INVALID_HANDLE) return NULL;
+
+ // Check if we are out of range
+ if (hSession > sessions.size()) return NULL;
+
+ return sessions[hSession - 1];
+}
+
+bool SessionManager::haveSession(CK_SLOT_ID slotID)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() == slotID)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool SessionManager::haveROSession(CK_SLOT_ID slotID)
+{
+ // Lock access to the vector
+ MutexLocker lock(sessionsMutex);
+
+ for (std::vector<Session*>::iterator i = sessions.begin(); i != sessions.end(); i++)
+ {
+ if (*i == NULL) continue;
+
+ if ((*i)->getSlot()->getSlotID() != slotID) continue;
+
+ if ((*i)->isRW() == false) return true;
+ }
+
+ return false;
+}
diff --git a/SoftHSMv2/src/lib/session_mgr/SessionManager.h b/SoftHSMv2/src/lib/session_mgr/SessionManager.h
new file mode 100644
index 0000000..1091782
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/SessionManager.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionManager.h
+
+ Keeps track of the sessions within SoftHSM
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONMANAGER_H
+#define _SOFTHSM_V2_SESSIONMANAGER_H
+
+#include "Slot.h"
+#include "Session.h"
+#include "MutexFactory.h"
+#include "config.h"
+#include "cryptoki.h"
+#include <memory>
+#include <vector>
+
+class SessionManager
+{
+public:
+ SessionManager();
+
+ virtual ~SessionManager();
+
+ CK_RV openSession(Slot* slot, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession);
+ CK_RV closeSession(CK_SESSION_HANDLE hSession);
+ CK_RV closeAllSessions(Slot* slot);
+ CK_RV getSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo);
+ Session* getSession(CK_SESSION_HANDLE hSession);
+ bool haveSession(CK_SLOT_ID slotID);
+ bool haveROSession(CK_SLOT_ID slotID);
+
+private:
+ // The sessions
+ std::vector<Session*> sessions;
+ Mutex* sessionsMutex;
+};
+
+#endif // !_SOFTHSM_V2_SESSIONMANAGER_H
+
diff --git a/SoftHSMv2/src/lib/session_mgr/test/Makefile.am b/SoftHSMv2/src/lib/session_mgr/test/Makefile.am
new file mode 100644
index 0000000..6395038
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/test/Makefile.am
@@ -0,0 +1,26 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../pkcs11 \
+ -I$(srcdir)/../../session_mgr \
+ -I$(srcdir)/../../slot_mgr \
+ @CPPUNIT_CFLAGS@ \
+ @CRYPTO_INCLUDES@
+
+check_PROGRAMS = sessionmgrtest
+
+sessionmgrtest_SOURCES = sessionmgrtest.cpp \
+ SessionManagerTests.cpp
+
+sessionmgrtest_LDADD = ../../libsofthsm_convarch.la
+
+sessionmgrtest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install -pthread
+
+TESTS = sessionmgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp b/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp
new file mode 100644
index 0000000..2c2e51a
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionManagerTests.cpp
+
+ Contains test cases for SessionManager
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SessionManagerTests.h"
+#include "ObjectStore.h"
+#include "SessionManager.h"
+#include "Session.h"
+#include "SlotManager.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionManagerTests);
+
+void SessionManagerTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void SessionManagerTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void SessionManagerTests::testOpenClose()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create the managers
+ SlotManager slotManager(&store);
+ SessionManager sessionManager;
+
+ // Get a slot
+ CK_SLOT_ID slotID = 0;
+ Slot* slot = slotManager.getSlot(slotID);
+
+ // Use some bad data
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = sessionManager.openSession(NULL, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+ rv = sessionManager.openSession(slot, 0, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_PARALLEL_NOT_SUPPORTED);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ // Try open a slot with an uninitialized token
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_TOKEN_NOT_RECOGNIZED);
+
+ // Initialize the token
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(slot->initToken(soPIN, label) == CKR_OK);
+
+ // Open a session
+ bool haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == false);
+ bool haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == false);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == true);
+ haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == true);
+
+ // Close session
+ rv = sessionManager.closeSession(CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+ haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == false);
+ haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == false);
+
+ // Try open a Read-Only session when in SO mode
+ rv = slot->getToken()->loginSO(soPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_WRITE_SO_EXISTS);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == true);
+ haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == false);
+
+ // Close session and check that we are logged out
+ bool isLoggedIn = slot->getToken()->isSOLoggedIn();
+ CPPUNIT_ASSERT(isLoggedIn == true);
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ isLoggedIn = slot->getToken()->isSOLoggedIn();
+ CPPUNIT_ASSERT(isLoggedIn == false);
+ haveSession = sessionManager.haveSession(slotID);
+ CPPUNIT_ASSERT(haveSession == false);
+ haveROSession = sessionManager.haveROSession(slotID);
+ CPPUNIT_ASSERT(haveROSession == false);
+
+ // Open a new logged in session
+ rv = slot->getToken()->loginSO(soPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close all sessions and check that we are logged out
+ isLoggedIn = slot->getToken()->isSOLoggedIn();
+ CPPUNIT_ASSERT(isLoggedIn == true);
+ rv = sessionManager.closeAllSessions(NULL);
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+ rv = sessionManager.closeAllSessions(slot);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ isLoggedIn = slot->getToken()->isSOLoggedIn();
+ CPPUNIT_ASSERT(isLoggedIn == false);
+}
+
+void SessionManagerTests::testSessionInfo()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create the managers
+ SlotManager slotManager(&store);
+ SessionManager sessionManager;
+
+ // Get a slot
+ CK_SLOT_ID slotID = 0;
+ Slot* slot = slotManager.getSlot(slotID);
+
+ // Initialize the token
+ ByteString soPIN((unsigned char*)"1234", 4);
+ ByteString userPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(slot->initToken(soPIN, label) == CKR_OK);
+ CPPUNIT_ASSERT(slot->getToken()->loginSO(soPIN) == CKR_OK);
+ CPPUNIT_ASSERT(slot->getToken()->initUserPIN(userPIN) == CKR_OK);
+ slot->getToken()->logout();
+
+ // Get a session
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get session info
+ CK_SESSION_INFO info;
+ rv = sessionManager.getSessionInfo(CK_INVALID_HANDLE, &info);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+ rv = sessionManager.getSessionInfo(hSession, NULL_PTR);
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+ rv = sessionManager.getSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Public RO session info
+ CPPUNIT_ASSERT(info.slotID == slotID);
+ CPPUNIT_ASSERT(info.state == CKS_RO_PUBLIC_SESSION);
+ CPPUNIT_ASSERT(info.flags == CKF_SERIAL_SESSION);
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Public RW session info
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ Session* session = sessionManager.getSession(CK_INVALID_HANDLE);
+ CPPUNIT_ASSERT(session == NULL);
+ session = sessionManager.getSession(hSession);
+ CPPUNIT_ASSERT(session != NULL);
+ rv = session->getInfo(&info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(info.state == CKS_RW_PUBLIC_SESSION);
+ CPPUNIT_ASSERT(info.flags == (CKF_SERIAL_SESSION | CKF_RW_SESSION));
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // User RO session info
+ rv = slot->getToken()->loginUser(userPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.getSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(info.state == CKS_RO_USER_FUNCTIONS);
+ CPPUNIT_ASSERT(info.flags == CKF_SERIAL_SESSION);
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // User RW session info
+ rv = slot->getToken()->loginUser(userPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.getSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(info.state == CKS_RW_USER_FUNCTIONS);
+ CPPUNIT_ASSERT(info.flags == (CKF_SERIAL_SESSION | CKF_RW_SESSION));
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // SO RW session info
+ rv = slot->getToken()->loginSO(soPIN);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = sessionManager.getSessionInfo(hSession, &info);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(info.state == CKS_RW_SO_FUNCTIONS);
+ CPPUNIT_ASSERT(info.flags == (CKF_SERIAL_SESSION | CKF_RW_SESSION));
+
+ rv = sessionManager.closeSession(hSession);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h b/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h
new file mode 100644
index 0000000..23f9d8c
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/test/SessionManagerTests.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionManagerTests.h
+
+ Contains test cases for SessionManager
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONMANAGERTESTS_H
+#define _SOFTHSM_V2_SESSIONMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SessionManagerTests);
+ CPPUNIT_TEST(testOpenClose);
+ CPPUNIT_TEST(testSessionInfo);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testOpenClose();
+ void testSessionInfo();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONMANAGERTESTS_H
diff --git a/SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp b/SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp
new file mode 100644
index 0000000..28eeee8
--- /dev/null
+++ b/SoftHSMv2/src/lib/session_mgr/test/sessionmgrtest.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ sessionmgrtest.cpp
+
+ The main test executor for tests on the session manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestFailure.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/SourceLine.h>
+#include <cppunit/Message.h>
+#include <cppunit/Exception.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+#include <stdlib.h>
+#include <iostream>
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "SecureMemoryRegistry.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#endif
+
+class MyListener : public CPPUNIT_NS::TestListener {
+ virtual void startTest( CPPUNIT_NS::Test*const pTest ) {
+ std::cout << std::endl << pTest->getName() << ' ' << pTest->countTestCases() << std::endl << std::endl;
+ }
+ virtual void addFailure( const CPPUNIT_NS::TestFailure & failure ) {
+ const CPPUNIT_NS::SourceLine solurceLine( failure.sourceLine() );
+ CPPUNIT_NS::Message message( failure.thrownException()->message() );
+ std::cout << solurceLine.fileName() << ' ' << solurceLine.lineNumber() << ' ' << message.shortDescription() << std::endl;
+ std::cout << message.details() << std::endl << std::endl;
+ }
+};
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ MyListener progress;
+ controller.addListener(&progress);
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ CryptoFactory::reset();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/SoftHSMv2/src/lib/slot_mgr/Makefile.am b/SoftHSMv2/src/lib/slot_mgr/Makefile.am
new file mode 100644
index 0000000..1e8cf33
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Makefile.am
@@ -0,0 +1,18 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../crypto \
+ -I$(srcdir)/../data_mgr \
+ -I$(srcdir)/../object_store \
+ -I$(srcdir)/../pkcs11 \
+ -I$(srcdir)/../session_mgr
+
+noinst_LTLIBRARIES = libsofthsm_slotmgr.la
+libsofthsm_slotmgr_la_SOURCES = SlotManager.cpp \
+ Slot.cpp \
+ Token.cpp
+
+SUBDIRS = test
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/slot_mgr/Slot.cpp b/SoftHSMv2/src/lib/slot_mgr/Slot.cpp
new file mode 100644
index 0000000..fea260b
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Slot.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Slot.h
+
+ This class represents a single PKCS #11 slot
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "SessionManager.h"
+#include "SlotManager.h"
+#include "Token.h"
+#include <stdio.h>
+#include <string.h>
+#include <sstream>
+
+// Constructor
+Slot::Slot(ObjectStore* inObjectStore, CK_SLOT_ID inSlotID, ObjectStoreToken* inToken /* = NULL */)
+{
+ objectStore = inObjectStore;
+ slotID = inSlotID;
+
+ if (inToken != NULL)
+ {
+ token = new Token(inToken);
+ }
+ else
+ {
+ token = new Token();
+ }
+}
+
+// Destructor
+Slot::~Slot()
+{
+ delete token;
+}
+
+// Retrieve the token in the slot
+Token* Slot::getToken()
+{
+ return token;
+}
+
+// Initialise the token in the slot
+CK_RV Slot::initToken(ByteString& soPIN, CK_UTF8CHAR_PTR label)
+{
+ return token->createToken(objectStore, soPIN, label);
+}
+
+// Retrieve slot information for the slot
+CK_RV Slot::getSlotInfo(CK_SLOT_INFO_PTR info)
+{
+ if (info == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ std::ostringstream osDescription;
+ osDescription << "SoftHSM slot ID 0x" << std::hex << slotID;
+ const std::string sDescription(osDescription.str());
+
+ char mfgID[33];
+ snprintf(mfgID, 33, "SoftHSM project");
+
+ memset(info->slotDescription, ' ', 64);
+ memset(info->manufacturerID, ' ', 32);
+ memcpy(info->slotDescription, sDescription.data(), sDescription.size());
+ memcpy(info->manufacturerID, mfgID, strlen(mfgID));
+
+ info->flags = CKF_TOKEN_PRESENT;
+
+ info->hardwareVersion.major = VERSION_MAJOR;
+ info->hardwareVersion.minor = VERSION_MINOR;
+ info->firmwareVersion.major = VERSION_MAJOR;
+ info->firmwareVersion.minor = VERSION_MINOR;
+
+ return CKR_OK;
+}
+
+// Get the slot ID
+CK_SLOT_ID Slot::getSlotID()
+{
+ return slotID;
+}
+
+// Is a token present?
+bool Slot::isTokenPresent()
+{
+ return true;
+}
diff --git a/SoftHSMv2/src/lib/slot_mgr/Slot.h b/SoftHSMv2/src/lib/slot_mgr/Slot.h
new file mode 100644
index 0000000..6ab07c6
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Slot.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Slot.h
+
+ This class represents a single PKCS #11 slot
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOT_H
+#define _SOFTHSM_V2_SLOT_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "ObjectStoreToken.h"
+#include "Token.h"
+#include "cryptoki.h"
+#include <string>
+#include <vector>
+
+class Slot
+{
+public:
+ // Constructor
+ Slot(ObjectStore* inObjectStore, CK_SLOT_ID inSlotID, ObjectStoreToken *inToken = NULL);
+
+ // Destructor
+ virtual ~Slot();
+
+ // Retrieve the token in the slot
+ Token* getToken();
+
+ // Initialise the token in the slot
+ CK_RV initToken(ByteString& pin, CK_UTF8CHAR_PTR label);
+
+ // Retrieve slot information for the slot
+ CK_RV getSlotInfo(CK_SLOT_INFO_PTR info);
+
+ // Get the slot ID
+ CK_SLOT_ID getSlotID();
+
+ // Is a token present?
+ bool isTokenPresent();
+
+private:
+ // A reference to the object store
+ ObjectStore* objectStore;
+
+ // The token in the slot
+ Token* token;
+
+ // The slot ID
+ CK_SLOT_ID slotID;
+};
+
+#endif // !_SOFTHSM_V2_SLOT_H
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/SlotManager.cpp b/SoftHSMv2/src/lib/slot_mgr/SlotManager.cpp
new file mode 100644
index 0000000..1f96909
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/SlotManager.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SlotManager.cpp
+
+ The slot manager is a class that forms part of the PKCS #11 core. It manages
+ all the slots that SoftHSM is aware of. To make it possible to add new
+ tokens, SoftHSM always has one slot available that contains an uninitialised
+ token. Users can choose to initialise this token to create a new token.
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "SlotManager.h"
+#include <cassert>
+#include <stdexcept>
+typedef std::pair<CK_SLOT_ID, Slot*> SlotMapElement;
+typedef std::pair<SlotMap::iterator, bool> InsertResult;
+
+// Constructor
+SlotManager::SlotManager(ObjectStore*const objectStore)
+{
+ // Add a slot for each token that already exists
+ for (size_t i = 0; i < objectStore->getTokenCount(); i++)
+ {
+ ObjectStoreToken*const pToken(objectStore->getToken(i));
+ ByteString bs;
+ pToken->getTokenSerial(bs);
+ const std::string s((const char*)bs.const_byte_str(), bs.size());
+
+ // parse serial string that is expected to have only hex digits.
+ CK_SLOT_ID l;
+ if (s.size() < 8)
+ {
+ l = strtoul(s.c_str(), NULL, 16);
+ }
+ else
+ {
+ l = strtoul(s.substr(s.size() - 8).c_str(), NULL, 16);
+ }
+
+ // mask for 31 bits.
+ // this since sunpkcs11 java wrapper is parsing the slot ID to a java int that needs to be positive.
+ // java int is 32 bit and the the sign bit is removed.
+ const CK_SLOT_ID mask( ((CK_SLOT_ID)1<<31)-1 );
+ const CK_SLOT_ID slotID(mask&l);
+
+ insertToken(objectStore, slotID, pToken);
+ }
+
+ // Add an empty slot
+ insertToken(objectStore, objectStore->getTokenCount(), NULL);
+}
+
+void SlotManager::insertToken(ObjectStore*const objectStore, const CK_SLOT_ID slotID, ObjectStoreToken*const pToken) {
+ Slot*const newSlot( new Slot(objectStore, slotID, pToken) );
+ const InsertResult result( slots.insert(SlotMapElement(slotID, newSlot)) );
+ assert(result.second);// fails if there is already a token on this slot
+}
+
+// Destructor
+SlotManager::~SlotManager()
+{
+ SlotMap toDelete = slots;
+ slots.clear();
+
+ for (SlotMap::iterator i = toDelete.begin(); i != toDelete.end(); i++)
+ {
+ delete i->second;
+ }
+}
+
+// Get the slot list
+CK_RV SlotManager::getSlotList(ObjectStore* objectStore, CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
+{
+ size_t size( 0 );
+
+ if (pulCount == NULL) return CKR_ARGUMENTS_BAD;
+
+ // Calculate the size of the list
+ bool uninitialized = false;
+ for (SlotMap::iterator i = slots.begin(); i != slots.end(); i++)
+ {
+ if ((tokenPresent == CK_FALSE) || i->second->isTokenPresent())
+ {
+ size++;
+ }
+
+ if (i->second->getToken() != NULL && i->second->getToken()->isInitialized() == false)
+ {
+ uninitialized = true;
+ }
+ }
+
+ // The user wants the size of the list
+ if (pSlotList == NULL)
+ {
+ // Always have an uninitialized token
+ if (uninitialized == false)
+ {
+ insertToken(objectStore, objectStore->getTokenCount(), NULL);
+ size++;
+ }
+
+ *pulCount = size;
+
+ return CKR_OK;
+ }
+
+ // Is the given buffer too small?
+ if (*pulCount < size)
+ {
+ *pulCount = size;
+
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ size_t startIx( 0 );
+ size_t endIx( size-1 );
+
+ for (SlotMap::iterator i = slots.begin(); i != slots.end(); i++)
+ {
+ if ((tokenPresent == CK_TRUE) && !i->second->isTokenPresent())
+ {// only show token if present on slot. But this slot has no token so we continue
+ continue;
+ }
+ // put uninitialized last. After all initialized or slots without tokens.
+ if ( i->second->isTokenPresent() && !i->second->getToken()->isInitialized() ) {
+ pSlotList[endIx--] = i->second->getSlotID();
+ } else {
+ pSlotList[startIx++] = i->second->getSlotID();
+ }
+ }
+ assert(startIx==endIx+1);
+ *pulCount = size;
+
+ return CKR_OK;
+}
+
+// Get the slots
+SlotMap SlotManager::getSlots()
+{
+ return slots;
+}
+
+// Get one slot
+Slot* SlotManager::getSlot(CK_SLOT_ID slotID)
+{
+ try {
+ return slots.at(slotID);
+ } catch( const std::out_of_range &oor) {
+ DEBUG_MSG("slotID is out of range: %s", oor.what());
+ return NULL_PTR;
+ }
+}
diff --git a/SoftHSMv2/src/lib/slot_mgr/SlotManager.h b/SoftHSMv2/src/lib/slot_mgr/SlotManager.h
new file mode 100644
index 0000000..04f51c0
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/SlotManager.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SlotManager.h
+
+ The slot manager is a class that forms part of the PKCS #11 core. It manages
+ all the slots that SoftHSM is aware of. To make it possible to add new
+ tokens, SoftHSM always has one slot available that contains an uninitialised
+ token. Users can choose to initialise this token to create a new token.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOTMANAGER_H
+#define _SOFTHSM_V2_SLOTMANAGER_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "Slot.h"
+#include <string>
+#include <map>
+typedef std::map<const CK_SLOT_ID, Slot*const> SlotMap;
+
+class SlotManager
+{
+public:
+ // Constructor
+ SlotManager(ObjectStore* objectStore);
+
+ // Destructor
+ virtual ~SlotManager();
+
+ // Get the slots
+ SlotMap getSlots();
+
+ // Get the slot list
+ CK_RV getSlotList(ObjectStore* objectStore, CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
+
+ // Get one slot
+ Slot* getSlot(CK_SLOT_ID slotID);
+private:
+ void insertToken(ObjectStore* objectStore, CK_SLOT_ID slotID, ObjectStoreToken* pToken);
+ // The slots
+ SlotMap slots;
+};
+
+#endif // !_SOFTHSM_V2_SLOTMANAGER_H
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/Token.cpp b/SoftHSMv2/src/lib/slot_mgr/Token.cpp
new file mode 100644
index 0000000..b4c9401
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Token.cpp
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "log.h"
+#include "ObjectStore.h"
+#include "Token.h"
+#include "OSAttribute.h"
+#include "ByteString.h"
+#include "SecureDataManager.h"
+#include <cstdio>
+
+#ifndef _WIN32
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
+// Constructor
+Token::Token()
+{
+ tokenMutex = MutexFactory::i()->getMutex();
+
+ token = NULL;
+ sdm = NULL;
+ valid = false;
+}
+
+// Constructor
+Token::Token(ObjectStoreToken* inToken)
+{
+ tokenMutex = MutexFactory::i()->getMutex();
+
+ token = inToken;
+
+ ByteString soPINBlob, userPINBlob;
+
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ sdm = new SecureDataManager(soPINBlob, userPINBlob);
+}
+
+// Destructor
+Token::~Token()
+{
+ if (sdm != NULL) delete sdm;
+
+ MutexFactory::i()->recycleMutex(tokenMutex);
+}
+
+// Check if the token is still valid
+bool Token::isValid()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ return (valid && token->isValid());
+}
+
+// Check if the token is initialized
+bool Token::isInitialized()
+{
+ if (token == NULL) return false;
+
+ return true;
+}
+
+// Check if SO is logged in
+bool Token::isSOLoggedIn()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->isSOLoggedIn();
+}
+
+// Check if user is logged in
+bool Token::isUserLoggedIn()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->isUserLoggedIn();
+}
+
+// Login SO
+CK_RV Token::loginSO(ByteString& pin)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // User cannot be logged in
+ if (sdm->isUserLoggedIn()) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ // SO cannot be logged in
+ if (sdm->isSOLoggedIn()) return CKR_USER_ALREADY_LOGGED_IN;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Login
+ if (!sdm->loginSO(pin))
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_OK;
+}
+
+// Login user
+CK_RV Token::loginUser(ByteString& pin)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // SO cannot be logged in
+ if (sdm->isSOLoggedIn()) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
+
+ // User cannot be logged in
+ if (sdm->isUserLoggedIn()) return CKR_USER_ALREADY_LOGGED_IN;
+
+ // The user PIN has to be initialized;
+ if (sdm->getUserPINBlob().size() == 0) return CKR_USER_PIN_NOT_INITIALIZED;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Login
+ if (!sdm->loginUser(pin))
+ {
+ flags |= CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_OK;
+}
+
+CK_RV Token::reAuthenticate(ByteString& pin)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (sdm->isSOLoggedIn())
+ {
+ // Login
+ if (!sdm->reAuthenticateSO(pin))
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+ else
+ {
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ }
+ }
+ else if (sdm->isUserLoggedIn())
+ {
+ // Login
+ if (!sdm->reAuthenticateUser(pin))
+ {
+ flags |= CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+ else
+ {
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ }
+ }
+ else
+ {
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ return CKR_OK;
+}
+
+// Logout any user on this token;
+void Token::logout()
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return;
+
+ sdm->logout();
+}
+
+// Change SO PIN
+CK_RV Token::setSOPIN(ByteString& oldPIN, ByteString& newPIN)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Verify oldPIN
+ SecureDataManager* verifier = new SecureDataManager(sdm->getSOPINBlob(), sdm->getUserPINBlob());
+ bool result = verifier->loginSO(oldPIN);
+ delete verifier;
+ if (result == false)
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ return CKR_PIN_INCORRECT;
+ }
+
+ if (sdm->setSOPIN(newPIN) == false) return CKR_GENERAL_ERROR;
+
+ // Save PIN to token file
+ if (token->setSOPIN(sdm->getSOPINBlob()) == false) return CKR_GENERAL_ERROR;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ return CKR_OK;
+}
+
+// Change the user PIN
+CK_RV Token::setUserPIN(ByteString& oldPIN, ByteString& newPIN)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ // Check if user should stay logged in
+ bool stayLoggedIn = sdm->isUserLoggedIn();
+
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Verify oldPIN
+ SecureDataManager* newSdm = new SecureDataManager(sdm->getSOPINBlob(), sdm->getUserPINBlob());
+ if (newSdm->loginUser(oldPIN) == false)
+ {
+ flags |= CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+ delete newSdm;
+ return CKR_PIN_INCORRECT;
+ }
+
+ // Set the new user PIN
+ if (newSdm->setUserPIN(newPIN) == false)
+ {
+ delete newSdm;
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Save PIN to token file
+ if (token->setUserPIN(newSdm->getUserPINBlob()) == false)
+ {
+ delete newSdm;
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Restore previous login state
+ if (!stayLoggedIn) newSdm->logout();
+
+ // Switch sdm
+ delete sdm;
+ sdm = newSdm;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ flags &= ~CKF_USER_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ return CKR_OK;
+}
+
+// Init the user PIN
+CK_RV Token::initUserPIN(ByteString& pin)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return CKR_GENERAL_ERROR;
+
+ if (sdm->setUserPIN(pin) == false) return CKR_GENERAL_ERROR;
+
+ // Save PIN to token file
+ if (token->setUserPIN(sdm->getUserPINBlob()) == false) return CKR_GENERAL_ERROR;
+
+ ByteString soPINBlob, userPINBlob;
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ return CKR_OK;
+}
+
+// Create a new token
+CK_RV Token::createToken(ObjectStore* objectStore, ByteString& soPIN, CK_UTF8CHAR_PTR label)
+{
+ CK_ULONG flags;
+
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (objectStore == NULL) return CKR_GENERAL_ERROR;
+ if (label == NULL_PTR) return CKR_ARGUMENTS_BAD;
+
+ // Convert the label
+ ByteString labelByteStr((const unsigned char*) label, 32);
+
+ if (token != NULL)
+ {
+ // Get token flags
+ if (!token->getTokenFlags(flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Verify SO PIN
+ if (sdm->getSOPINBlob().size() > 0 && !sdm->loginSO(soPIN))
+ {
+ flags |= CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ ERROR_MSG("Incorrect SO PIN");
+ return CKR_PIN_INCORRECT;
+ }
+ flags &= ~CKF_SO_PIN_COUNT_LOW;
+ token->setTokenFlags(flags);
+
+ // Reset the token
+ if (!token->resetToken(labelByteStr))
+ {
+ ERROR_MSG("Could not reset the token");
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ else
+ {
+ // Generate the SO PIN blob
+ SecureDataManager soPINBlobGen;
+
+ if (!soPINBlobGen.setSOPIN(soPIN))
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Create the token
+ ObjectStoreToken* newToken = objectStore->newToken(labelByteStr);
+
+ if (newToken == NULL)
+ {
+ ERROR_MSG("Could not create the token");
+ return CKR_DEVICE_ERROR;
+ }
+
+ // Set the SO PIN on the token
+ if (!newToken->setSOPIN(soPINBlobGen.getSOPINBlob()))
+ {
+ ERROR_MSG("Failed to set SO PIN on new token");
+
+ if (!objectStore->destroyToken(newToken))
+ {
+ ERROR_MSG("Failed to destroy incomplete token");
+ }
+
+ return CKR_DEVICE_ERROR;
+ }
+
+ token = newToken;
+ }
+
+ ByteString soPINBlob, userPINBlob;
+
+ valid = token->getSOPIN(soPINBlob) && token->getUserPIN(userPINBlob);
+
+ if (sdm != NULL) delete sdm;
+ sdm = new SecureDataManager(soPINBlob, userPINBlob);
+
+ return CKR_OK;
+}
+
+// Retrieve token information for the token
+CK_RV Token::getTokenInfo(CK_TOKEN_INFO_PTR info)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ ByteString label, serial;
+
+ if (info == NULL)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ memset(info->label, ' ', 32);
+ memset(info->serialNumber, ' ', 16);
+
+ // Token specific information
+ if (token)
+ {
+ if (!token->getTokenFlags(info->flags))
+ {
+ ERROR_MSG("Could not get the token flags");
+ return CKR_GENERAL_ERROR;
+ }
+
+ if (token->getTokenLabel(label))
+ {
+ strncpy((char*) info->label, (char*) label.byte_str(), label.size());
+ }
+
+ if (token->getTokenSerial(serial))
+ {
+ strncpy((char*) info->serialNumber, (char*) serial.byte_str(), serial.size());
+ }
+ }
+ else
+ {
+ info->flags = CKF_RNG |
+ CKF_LOGIN_REQUIRED |
+ CKF_RESTORE_KEY_NOT_NEEDED |
+ CKF_SO_PIN_LOCKED |
+ CKF_SO_PIN_TO_BE_CHANGED;
+ }
+
+ // Information shared by all tokens
+ char mfgID[33];
+ char model[17];
+
+ snprintf(mfgID, 33, "SoftHSM project");
+ snprintf(model, 17, "SoftHSM v2");
+
+ memset(info->manufacturerID, ' ', 32);
+ memset(info->model, ' ', 16);
+ memcpy(info->manufacturerID, mfgID, strlen(mfgID));
+ memcpy(info->model, model, strlen(model));
+
+ // TODO: Can we set these?
+ info->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
+ info->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
+
+ info->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulMaxPinLen = MAX_PIN_LEN;
+ info->ulMinPinLen = MIN_PIN_LEN;
+ info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->hardwareVersion.major = VERSION_MAJOR;
+ info->hardwareVersion.minor = VERSION_MINOR;
+ info->firmwareVersion.major = VERSION_MAJOR;
+ info->firmwareVersion.minor = VERSION_MINOR;
+
+ // Current time
+ time_t rawtime;
+ time(&rawtime);
+ char dateTime[17];
+ strftime(dateTime, 17, "%Y%m%d%H%M%S00", gmtime(&rawtime));
+ memcpy(info->utcTime, dateTime, 16);
+
+ return CKR_OK;
+}
+
+// Create an object
+OSObject* Token::createObject()
+{
+ return token->createObject();
+}
+
+void Token::getObjects(std::set<OSObject *> &objects)
+{
+ token->getObjects(objects);
+}
+
+bool Token::decrypt(const ByteString &encrypted, ByteString &plaintext)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->decrypt(encrypted,plaintext);
+}
+
+bool Token::encrypt(const ByteString &plaintext, ByteString &encrypted)
+{
+ // Lock access to the token
+ MutexLocker lock(tokenMutex);
+
+ if (sdm == NULL) return false;
+
+ return sdm->encrypt(plaintext,encrypted);
+}
diff --git a/SoftHSMv2/src/lib/slot_mgr/Token.h b/SoftHSMv2/src/lib/slot_mgr/Token.h
new file mode 100644
index 0000000..8f67433
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/Token.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ Token.h
+
+ This class represents a single PKCS #11 token
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TOKEN_H
+#define _SOFTHSM_V2_TOKEN_H
+
+#include "config.h"
+#include "ByteString.h"
+#include "ObjectStore.h"
+#include "ObjectStoreToken.h"
+#include "SecureDataManager.h"
+#include "cryptoki.h"
+#include <string>
+#include <vector>
+
+class Token
+{
+public:
+ // Constructor
+ Token();
+ Token(ObjectStoreToken *inToken);
+
+ // Destructor
+ virtual ~Token();
+
+ // Create a new token
+ CK_RV createToken(ObjectStore* objectStore, ByteString& soPIN, CK_UTF8CHAR_PTR label);
+
+ // Is the token valid?
+ bool isValid();
+
+ // Is the token initialized?
+ bool isInitialized();
+
+ // Is SO or user logged in?
+ bool isSOLoggedIn();
+ bool isUserLoggedIn();
+
+ // Login
+ CK_RV loginSO(ByteString& pin);
+ CK_RV loginUser(ByteString& pin);
+
+ // Re-authentication
+ CK_RV reAuthenticate(ByteString& pin);
+
+ // Logout any user on this token;
+ void logout();
+
+ // Change PIN
+ CK_RV setSOPIN(ByteString& oldPIN, ByteString& newPIN);
+ CK_RV setUserPIN(ByteString& oldPIN, ByteString& newPIN);
+ CK_RV initUserPIN(ByteString& pin);
+
+ // Retrieve token information for the token
+ CK_RV getTokenInfo(CK_TOKEN_INFO_PTR info);
+
+ // Create object
+ OSObject *createObject();
+
+ // Insert all token objects into the given set.
+ void getObjects(std::set<OSObject *> &objects);
+
+ // Decrypt the supplied data
+ bool decrypt(const ByteString& encrypted, ByteString& plaintext);
+
+ // Encrypt the supplied data
+ bool encrypt(const ByteString& plaintext, ByteString& encrypted);
+
+private:
+ // Token validity
+ bool valid;
+
+ // A reference to the object store token
+ ObjectStoreToken* token;
+
+ // The secure data manager for this token
+ SecureDataManager* sdm;
+
+ Mutex* tokenMutex;
+};
+
+#endif // !_SOFTHSM_V2_TOKEN_H
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/test/Makefile.am b/SoftHSMv2/src/lib/slot_mgr/test/Makefile.am
new file mode 100644
index 0000000..8e2d161
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/test/Makefile.am
@@ -0,0 +1,25 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../.. \
+ -I$(srcdir)/../../common \
+ -I$(srcdir)/../../crypto \
+ -I$(srcdir)/../../data_mgr \
+ -I$(srcdir)/../../object_store \
+ -I$(srcdir)/../../pkcs11 \
+ -I$(srcdir)/../../session_mgr \
+ @CPPUNIT_CFLAGS@ \
+ @CRYPTO_INCLUDES@
+
+check_PROGRAMS = slotmgrtest
+
+slotmgrtest_SOURCES = slotmgrtest.cpp \
+ SlotManagerTests.cpp
+
+slotmgrtest_LDADD = ../../libsofthsm_convarch.la
+
+slotmgrtest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install -pthread
+
+TESTS = slotmgrtest
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.cpp b/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.cpp
new file mode 100644
index 0000000..c5f6687
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.cpp
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SlotManagerTests.cpp
+
+ Contains test cases to test the object store implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "SlotManagerTests.h"
+#include "SlotManager.h"
+#include "Token.h"
+#include "ObjectStore.h"
+#include "ObjectFile.h"
+#include "File.h"
+#include "Directory.h"
+#include "OSAttribute.h"
+#include "OSAttributes.h"
+#include "CryptoFactory.h"
+#include "cryptoki.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SlotManagerTests);
+
+void SlotManagerTests::setUp()
+{
+ CPPUNIT_ASSERT(!system("mkdir testdir"));
+}
+
+void SlotManagerTests::tearDown()
+{
+#ifndef _WIN32
+ CPPUNIT_ASSERT(!system("rm -rf testdir"));
+#else
+ CPPUNIT_ASSERT(!system("rmdir /s /q testdir 2> nul"));
+#endif
+}
+
+void SlotManagerTests::testNoExistingTokens()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 1);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testExistingTokens()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create two tokens
+ ByteString label1 = "DEADBEEF";
+ ByteString label2 = "DEADC0FFEE";
+
+ CPPUNIT_ASSERT(store.newToken(label1) != NULL);
+ CPPUNIT_ASSERT(store.newToken(label2) != NULL);
+
+ // Now attach the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 3);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotID() == testList[1]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getSlotID() == testList[2]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testInitialiseTokenInLastSlot()
+{
+ {
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 1);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+
+ // Now initialise the token in the first slot
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->initToken(soPIN, label) == CKR_OK);
+
+ // Retrieve slot information about the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+ }
+
+ // Attach a fresh slot manager
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 2);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotID() == testList[1]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
+void SlotManagerTests::testReinitialiseExistingToken()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Create two tokens
+ ByteString label1 = "DEADBEEF";
+ ByteString label2 = "DEADC0FFEE";
+
+ CPPUNIT_ASSERT(store.newToken(label1) != NULL);
+ CPPUNIT_ASSERT(store.newToken(label2) != NULL);
+
+ // Now attach the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 3);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotID() == testList[0]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotID() == testList[1]);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getSlotID() == testList[2]);
+
+ // Retrieve slot information about the first slot
+ CK_SLOT_INFO slotInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CK_TOKEN_INFO tokenInfo;
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, &label1[0], label1.size()) ||
+ !memcmp(tokenInfo.label, &label2[0], label2.size()));
+
+ // Retrieve slot information about the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the third slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+
+ // Now reinitialise the token in the second slot
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->initToken(soPIN, label) == CKR_OK);
+
+ // Retrieve slot information about the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getSlotInfo(&slotInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);
+
+ // Retrieve token information about the token in the first slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(!memcmp(tokenInfo.label, label, 32));
+}
+
+void SlotManagerTests::testUninitialisedToken()
+{
+ // Create an empty object store
+#ifndef _WIN32
+ ObjectStore store("./testdir");
+#else
+ ObjectStore store(".\\testdir");
+#endif
+
+ // Now attach the slot manager
+ SlotManager slotManager(&store);
+
+ CPPUNIT_ASSERT(slotManager.getSlots().size() == 1);
+
+ // Test C_GetSlotList
+ CK_SLOT_ID testList[10];
+ CK_ULONG ulCount = 10;
+
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+
+ // Initialise the token in the first slot
+ ByteString soPIN((unsigned char*)"1234", 4);
+ CK_UTF8CHAR label[33] = "My test token ";
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->initToken(soPIN, label) == CKR_OK);
+
+ // Check if a new slot is added
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 1);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, NULL_PTR, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, NULL_PTR, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+
+ // get new list
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+
+ // Retrieve token information about the tokens
+ CK_TOKEN_INFO tokenInfo;
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+
+ // Initialise the token in the second slot
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->initToken(soPIN, label) == CKR_OK);
+
+ // Check if a new slot is added
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 2);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_FALSE, NULL_PTR, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+ ulCount = 10;
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, NULL_PTR, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ // get new list
+ CPPUNIT_ASSERT(slotManager.getSlotList(&store, CK_TRUE, testList, &ulCount) == CKR_OK);
+ CPPUNIT_ASSERT(ulCount == 3);
+
+ // Retrieve token information about the tokens
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[0]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[1]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken() != NULL);
+ CPPUNIT_ASSERT(slotManager.getSlots()[testList[2]]->getToken()->getTokenInfo(&tokenInfo) == CKR_OK);
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) != CKF_TOKEN_INITIALIZED);
+}
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.h b/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.h
new file mode 100644
index 0000000..8d4e57f
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/test/SlotManagerTests.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SlotManagerTests.h
+
+ Contains test cases to test the slot manager implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SLOTMANAGERTESTS_H
+#define _SOFTHSM_V2_SLOTMANAGERTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class SlotManagerTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SlotManagerTests);
+ CPPUNIT_TEST(testNoExistingTokens);
+ CPPUNIT_TEST(testExistingTokens);
+ CPPUNIT_TEST(testInitialiseTokenInLastSlot);
+ CPPUNIT_TEST(testReinitialiseExistingToken);
+ CPPUNIT_TEST(testUninitialisedToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testNoExistingTokens();
+ void testExistingTokens();
+ void testInitialiseTokenInLastSlot();
+ void testReinitialiseExistingToken();
+ void testUninitialisedToken();
+
+ void setUp();
+ void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_SLOTMANAGERTESTS_H
+
diff --git a/SoftHSMv2/src/lib/slot_mgr/test/slotmgrtest.cpp b/SoftHSMv2/src/lib/slot_mgr/test/slotmgrtest.cpp
new file mode 100644
index 0000000..4172b63
--- /dev/null
+++ b/SoftHSMv2/src/lib/slot_mgr/test/slotmgrtest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ slotmgrtest.cpp
+
+ The main test executor for tests on the slot manager in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+
+#include "config.h"
+#include "MutexFactory.h"
+#include "SecureMemoryRegistry.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+// Initialise the one-and-only instance
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#endif
+
+int main(int /*argc*/, char** /*argv*/)
+{
+ CppUnit::TestResult controller;
+ CppUnit::TestResultCollector result;
+ CppUnit::TextUi::TestRunner runner;
+ controller.addListener(&result);
+ CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
+
+ runner.addTest(registry.makeTest());
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ CryptoFactory::reset();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.cpp b/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.cpp
new file mode 100644
index 0000000..6f06a42
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymEncryptDecryptTests.cpp
+
+ Contains test cases for C_EncryptInit, C_Encrypt, C_DecryptInit, C_Decrypt
+ using asymmetrical algorithms (i.e., RSA)
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "AsymEncryptDecryptTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AsymEncryptDecryptTests);
+
+CK_RV AsymEncryptDecryptTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+void AsymEncryptDecryptTests::rsaEncryptDecrypt(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
+{
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, 1, NULL_PTR, 0 };
+ CK_BYTE plainText[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE cipherText[256];
+ CK_ULONG ulCipherTextLen;
+ CK_BYTE recoveredText[256];
+ CK_ULONG ulRecoveredTextLen;
+ CK_RV rv;
+
+ if (mechanismType == CKM_RSA_PKCS_OAEP)
+ {
+ mechanism.pParameter = &oaepParams;
+ mechanism.ulParameterLen = sizeof(oaepParams);
+ }
+
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulCipherTextLen = sizeof(cipherText);
+ rv =CRYPTOKI_F_PTR( C_Encrypt(hSession,plainText,sizeof(plainText),cipherText,&ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechanism,hPrivateKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulRecoveredTextLen = sizeof(recoveredText);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CPPUNIT_ASSERT(memcmp(plainText, &recoveredText[ulRecoveredTextLen-sizeof(plainText)], sizeof(plainText)) == 0);
+}
+
+// Check that RSA OAEP mechanism properly validates all input parameters
+void AsymEncryptDecryptTests::rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey)
+{
+ // This is only supported combination of parameters
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, CKZ_DATA_SPECIFIED, NULL_PTR, 0 };
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_OAEP, NULL, 0 };
+ CK_RV rv;
+
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ mechanism.pParameter = &oaepParams;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ mechanism.ulParameterLen = sizeof(oaepParams);
+
+ oaepParams.hashAlg = CKM_AES_CBC;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.hashAlg = CKM_SHA_1;
+ oaepParams.mgf = CKG_MGF1_SHA256;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.mgf = CKG_MGF1_SHA1;
+ oaepParams.source = CKZ_DATA_SPECIFIED - 1;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.source = CKZ_DATA_SPECIFIED;
+ oaepParams.pSourceData = &oaepParams;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.ulSourceDataLen = sizeof(oaepParams);
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.pSourceData = NULL;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+}
+
+void AsymEncryptDecryptTests::testRsaEncryptDecrypt()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token public/private key pairs.
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPublicKey,hPrivateKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rsaOAEPParams(hSessionRO,hPublicKey);
+ rsaEncryptDecrypt(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey);
+ rsaEncryptDecrypt(CKM_RSA_X_509,hSessionRO,hPublicKey,hPrivateKey);
+ rsaEncryptDecrypt(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey);
+}
diff --git a/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.h b/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.h
new file mode 100644
index 0000000..0b8db04
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymEncryptDecryptTests.h
+
+ Contains test cases for C_EncryptInit, C_Encrypt, C_DecryptInit, C_Decrypt
+ using asymmetrical algorithms (i.e., RSA)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMENCRYPTDECRYPTTESTS_H
+#define _SOFTHSM_V2_ASYMENCRYPTDECRYPTTESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class AsymEncryptDecryptTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(AsymEncryptDecryptTests);
+ CPPUNIT_TEST(testRsaEncryptDecrypt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRsaEncryptDecrypt();
+
+protected:
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ void rsaEncryptDecrypt(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey);
+ void rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey);
+};
+
+#endif // !_SOFTHSM_V2_ASYMENCRYPTDECRYPTTESTS_H
diff --git a/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.cpp b/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.cpp
new file mode 100644
index 0000000..9614e69
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2014 Red Hat
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymWrapUnwrapTests.cpp
+
+ Contains test cases for C_WrapKey and C_UnwrapKey
+ using asymmetrical algorithms (RSA)
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "AsymWrapUnwrapTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AsymWrapUnwrapTests);
+
+// Generate throw-away (session) symmetric key
+CK_RV AsymWrapUnwrapTests::generateAesKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_ULONG bytes = 16;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bFalse, sizeof(bTrue) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV AsymWrapUnwrapTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_VERIFY, &bFalse, sizeof(bFalse) },
+ { CKA_WRAP, &bTrue, sizeof(bTrue) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_SIGN, &bFalse, sizeof(bFalse) },
+ { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+void AsymWrapUnwrapTests::rsaWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
+{
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, CKZ_DATA_SPECIFIED, NULL_PTR, 0 };
+ CK_BYTE cipherText[2048];
+ CK_ULONG ulCipherTextLen;
+ CK_BYTE symValue[64];
+ CK_ULONG ulSymValueLen = sizeof(symValue);
+ CK_BYTE unwrappedValue[64];
+ CK_ULONG ulUnwrappedValueLen = sizeof(unwrappedValue);
+ CK_OBJECT_HANDLE symKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE unwrappedKey = CK_INVALID_HANDLE;
+ CK_RV rv;
+ CK_ULONG wrappedLenEstimation;
+
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_AES;
+ CK_ATTRIBUTE unwrapTemplate[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
+ };
+
+ CK_ATTRIBUTE valueTemplate[] = {
+ { CKA_VALUE, &symValue, ulSymValueLen }
+ };
+
+ CK_MECHANISM_INFO mechInfo;
+
+ if (mechanismType == CKM_RSA_PKCS_OAEP)
+ {
+ mechanism.pParameter = &oaepParams;
+ mechanism.ulParameterLen = sizeof(oaepParams);
+ }
+
+ // Generate temporary symmetric key and remember it's value
+ rv = generateAesKey(hSession, symKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, symKey, valueTemplate, sizeof(valueTemplate)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ ulSymValueLen = valueTemplate[0].ulValueLen;
+
+ // CKM_RSA_PKCS Wrap/Unwrap support
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, CKM_RSA_PKCS, &mechInfo) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ CPPUNIT_ASSERT(mechInfo.flags&CKF_WRAP);
+ CPPUNIT_ASSERT(mechInfo.flags&CKF_UNWRAP);
+
+ // Estimate wrapped length
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hPublicKey, symKey, NULL_PTR, &wrappedLenEstimation) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ CPPUNIT_ASSERT(wrappedLenEstimation>0);
+
+ // This should always fail because wrapped data have to be longer than 0 bytes
+ ulCipherTextLen = 0;
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hPublicKey, symKey, cipherText, &ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_BUFFER_TOO_SMALL);
+
+ // Do real wrapping
+ ulCipherTextLen = sizeof(cipherText);
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hPublicKey, symKey, cipherText, &ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ // Check length 'estimation'
+ CPPUNIT_ASSERT(wrappedLenEstimation>=ulCipherTextLen);
+
+ rv = CRYPTOKI_F_PTR( C_UnwrapKey(hSession, &mechanism, hPrivateKey, cipherText, ulCipherTextLen, unwrapTemplate, sizeof(unwrapTemplate)/sizeof(CK_ATTRIBUTE), &unwrappedKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ valueTemplate[0].pValue = &unwrappedValue;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, unwrappedKey, valueTemplate, sizeof(valueTemplate)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ ulUnwrappedValueLen = valueTemplate[0].ulValueLen;
+
+ CPPUNIT_ASSERT(ulSymValueLen == ulUnwrappedValueLen);
+ CPPUNIT_ASSERT(memcmp(symValue, unwrappedValue, ulSymValueLen) == 0);
+}
+
+void AsymWrapUnwrapTests::testRsaWrapUnwrap()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token public/private key pairs.
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPublicKey,hPrivateKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rsaWrapUnwrap(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey);
+ rsaWrapUnwrap(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey);
+}
diff --git a/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.h b/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.h
new file mode 100644
index 0000000..97f6940
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014 Red Hat
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymWrapUnwrapTests.h
+
+ Contains test cases for C_WrapKey and C_UnwrapKey
+ using asymmetrical algorithms (RSA)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMWRAPUNWRAPTESTS_H
+#define _SOFTHSM_V2_ASYMWRAPUNWRAPTESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class AsymWrapUnwrapTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(AsymWrapUnwrapTests);
+ CPPUNIT_TEST(testRsaWrapUnwrap);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRsaWrapUnwrap();
+
+protected:
+ CK_RV generateAesKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ void rsaWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey);
+};
+
+#endif // !_SOFTHSM_V2_ASYMWRAPUNWRAPTESTS_H
diff --git a/SoftHSMv2/src/lib/test/DeriveTests.cpp b/SoftHSMv2/src/lib/test/DeriveTests.cpp
new file mode 100644
index 0000000..588d0b9
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/DeriveTests.cpp
@@ -0,0 +1,737 @@
+/*
+ * Copyright (c) 2014 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DeriveTests.cpp
+
+ Contains test cases for:
+ C_DeriveKey
+
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "DeriveTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DeriveTests);
+
+CK_RV DeriveTests::generateDhKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BYTE bn1024[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
+ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
+ 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74,
+ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22,
+ 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
+ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b,
+ 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37,
+ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
+ 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
+ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b,
+ 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
+ 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5,
+ 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6,
+ 0x49, 0x28, 0x66, 0x51, 0xec, 0xe6, 0x53, 0x81,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ CK_BYTE bn2[] = { 2 };
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_PRIME, &bn1024, sizeof(bn1024) },
+ { CKA_BASE, &bn2, sizeof(bn2) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+#ifdef WITH_ECC
+CK_RV DeriveTests::generateEcKeyPair(const char* curve, CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_KEY_TYPE keyType = CKK_EC;
+ CK_BYTE oidP256[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 };
+ CK_BYTE oidP384[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 };
+ CK_BYTE oidP521[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23 };
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_EC_PARAMS, NULL, 0 },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ /* Select the curve */
+ if (strcmp(curve, "P-256") == 0)
+ {
+ pukAttribs[0].pValue = oidP256;
+ pukAttribs[0].ulValueLen = sizeof(oidP256);
+ }
+ else if (strcmp(curve, "P-384") == 0)
+ {
+ pukAttribs[0].pValue = oidP384;
+ pukAttribs[0].ulValueLen = sizeof(oidP384);
+ }
+ else if (strcmp(curve, "P-521") == 0)
+ {
+ pukAttribs[0].pValue = oidP521;
+ pukAttribs[0].ulValueLen = sizeof(oidP521);
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+#endif
+
+CK_RV DeriveTests::generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_ULONG bytes = 16;
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+#ifndef WITH_FIPS
+CK_RV DeriveTests::generateDesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+#endif
+
+CK_RV DeriveTests::generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES2_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV DeriveTests::generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+void DeriveTests::dhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey)
+{
+ CK_ATTRIBUTE valAttrib = { CKA_VALUE, NULL_PTR, 0 };
+ CK_RV rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ valAttrib.pValue = (CK_BYTE_PTR)malloc(valAttrib.ulValueLen);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_MECHANISM mechanism = { CKM_DH_PKCS_DERIVE, NULL_PTR, 0 };
+ mechanism.pParameter = valAttrib.pValue;
+ mechanism.ulParameterLen = valAttrib.ulValueLen;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ULONG secLen = 32;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_PRIVATE, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &secLen, sizeof(secLen) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hPrivateKey,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ free(valAttrib.pValue);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+#ifdef WITH_ECC
+void DeriveTests::ecdhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey, bool useRaw)
+{
+ CK_ATTRIBUTE valAttrib = { CKA_EC_POINT, NULL_PTR, 0 };
+ CK_RV rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ valAttrib.pValue = (CK_BYTE_PTR)malloc(valAttrib.ulValueLen);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_ECDH1_DERIVE_PARAMS parms = { CKD_NULL, 0, NULL_PTR, 0, NULL_PTR };
+ // Use RAW or DER format
+ if (useRaw)
+ {
+ size_t offset = 0;
+ unsigned char* buf = (unsigned char*)valAttrib.pValue;
+ if (valAttrib.ulValueLen > 2 && buf[0] == 0x04)
+ {
+ if (buf[1] < 0x80)
+ {
+ offset = 2;
+ }
+ else
+ {
+ if (valAttrib.ulValueLen > ((buf[1] & 0x7F) + (unsigned int)2))
+ {
+ offset = 2 + (buf[1] & 0x7F);
+ }
+ }
+ }
+ parms.pPublicData = buf + offset;
+ parms.ulPublicDataLen = valAttrib.ulValueLen - offset;
+ }
+ else
+ {
+ parms.pPublicData = (unsigned char*)valAttrib.pValue;
+ parms.ulPublicDataLen = valAttrib.ulValueLen;
+ }
+
+ CK_MECHANISM mechanism = { CKM_ECDH1_DERIVE, NULL, 0 };
+ mechanism.pParameter = &parms;
+ mechanism.ulParameterLen = sizeof(parms);
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ULONG secLen = 32;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_PRIVATE, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &secLen, sizeof(secLen) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hPrivateKey,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ free(valAttrib.pValue);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+#endif
+
+bool DeriveTests::compareSecret(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey1, CK_OBJECT_HANDLE hKey2)
+{
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_VALUE, NULL_PTR, 0 },
+ { CKA_CHECK_VALUE, NULL_PTR, 0 }
+ };
+ CK_BYTE val1[128];
+ CK_BYTE check1[3];
+ keyAttribs[0].pValue = val1;
+ keyAttribs[0].ulValueLen = sizeof(val1);
+ keyAttribs[1].pValue = check1;
+ keyAttribs[1].ulValueLen = sizeof(check1);
+ CK_RV rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hKey1, keyAttribs, 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(keyAttribs[0].ulValueLen == 32);
+ CPPUNIT_ASSERT(keyAttribs[1].ulValueLen == 3);
+ CK_BYTE val2[128];
+ CK_BYTE check2[3];
+ keyAttribs[0].pValue = val2;
+ keyAttribs[0].ulValueLen = sizeof(val2);
+ keyAttribs[1].pValue = check2;
+ keyAttribs[1].ulValueLen = sizeof(check2);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hKey2, keyAttribs, 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(keyAttribs[0].ulValueLen == 32);
+ CPPUNIT_ASSERT(keyAttribs[1].ulValueLen == 3);
+ return memcmp(val1, val2, 32) == 0 &&
+ memcmp(check1, check2, 3) == 0;
+}
+
+void DeriveTests::testDhDerive()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Public Session keys
+ CK_OBJECT_HANDLE hPuk1 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk1 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPuk2 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk2 = CK_INVALID_HANDLE;
+
+ rv = generateDhKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDhKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_OBJECT_HANDLE hKey1 = CK_INVALID_HANDLE;
+ dhDerive(hSessionRW,hPuk1,hPrk2,hKey1);
+ CK_OBJECT_HANDLE hKey2 = CK_INVALID_HANDLE;
+ dhDerive(hSessionRW,hPuk2,hPrk1,hKey2);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Private Session Keys
+ rv = generateDhKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDhKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ dhDerive(hSessionRW,hPuk1,hPrk2,hKey1);
+ dhDerive(hSessionRW,hPuk2,hPrk1,hKey2);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Public Token Keys
+ rv = generateDhKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDhKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ dhDerive(hSessionRW,hPuk1,hPrk2,hKey1);
+ dhDerive(hSessionRW,hPuk2,hPrk1,hKey2);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Private Token Keys
+ rv = generateDhKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDhKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ dhDerive(hSessionRW,hPuk1,hPrk2,hKey1);
+ dhDerive(hSessionRW,hPuk2,hPrk1,hKey2);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+}
+
+#ifdef WITH_ECC
+void DeriveTests::testEcdhDerive()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Public Session keys
+ CK_OBJECT_HANDLE hPuk1 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk1 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPuk2 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk2 = CK_INVALID_HANDLE;
+
+ rv = generateEcKeyPair("P-256",hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateEcKeyPair("P-256",hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_OBJECT_HANDLE hKey1 = CK_INVALID_HANDLE;
+ ecdhDerive(hSessionRW,hPuk1,hPrk2,hKey1,true);
+ CK_OBJECT_HANDLE hKey2 = CK_INVALID_HANDLE;
+ ecdhDerive(hSessionRW,hPuk2,hPrk1,hKey2,false);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Private Session Keys
+ rv = generateEcKeyPair("P-384",hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateEcKeyPair("P-384",hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ ecdhDerive(hSessionRW,hPuk1,hPrk2,hKey1,true);
+ ecdhDerive(hSessionRW,hPuk2,hPrk1,hKey2,false);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Public Token Keys
+ rv = generateEcKeyPair("P-521",hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateEcKeyPair("P-521",hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ ecdhDerive(hSessionRW,hPuk1,hPrk2,hKey1,true);
+ ecdhDerive(hSessionRW,hPuk2,hPrk1,hKey2,false);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Private Token Keys
+ rv = generateEcKeyPair("P-256",hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateEcKeyPair("P-256",hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ ecdhDerive(hSessionRW,hPuk1,hPrk2,hKey1,true);
+ ecdhDerive(hSessionRW,hPuk2,hPrk1,hKey2,false);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+}
+#endif
+
+void DeriveTests::symDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE &hDerive, CK_MECHANISM_TYPE mechType, CK_KEY_TYPE keyType)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechType, NULL_PTR, 0 };
+ CK_MECHANISM mechEncrypt = { CKM_VENDOR_DEFINED, NULL_PTR, 0 };
+ CK_KEY_DERIVATION_STRING_DATA param1;
+ CK_DES_CBC_ENCRYPT_DATA_PARAMS param2;
+ CK_AES_CBC_ENCRYPT_DATA_PARAMS param3;
+
+ CK_BYTE data[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32
+ };
+ CK_ULONG secLen = 0;
+
+ switch (mechType)
+ {
+ case CKM_DES_ECB_ENCRYPT_DATA:
+ case CKM_DES3_ECB_ENCRYPT_DATA:
+ case CKM_AES_ECB_ENCRYPT_DATA:
+ param1.pData = &data[0];
+ param1.ulLen = sizeof(data);
+ mechanism.pParameter = &param1;
+ mechanism.ulParameterLen = sizeof(param1);
+ break;
+ case CKM_DES_CBC_ENCRYPT_DATA:
+ case CKM_DES3_CBC_ENCRYPT_DATA:
+ memcpy(param2.iv, "12345678", 8);
+ param2.pData = &data[0];
+ param2.length = sizeof(data);
+ mechanism.pParameter = &param2;
+ mechanism.ulParameterLen = sizeof(param2);
+ break;
+ case CKM_AES_CBC_ENCRYPT_DATA:
+ memcpy(param3.iv, "1234567890ABCDEF", 16);
+ param3.pData = &data[0];
+ param3.length = sizeof(data);
+ mechanism.pParameter = &param3;
+ mechanism.ulParameterLen = sizeof(param3);
+ break;
+ default:
+ CPPUNIT_FAIL("Invalid mechanism");
+ }
+
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ secLen = 32;
+ break;
+ case CKK_DES:
+ mechEncrypt.mechanism = CKM_DES_ECB;
+ break;
+ case CKK_DES2:
+ case CKK_DES3:
+ mechEncrypt.mechanism = CKM_DES3_ECB;
+ break;
+ case CKK_AES:
+ mechEncrypt.mechanism = CKM_AES_ECB;
+ secLen = 32;
+ break;
+ default:
+ CPPUNIT_FAIL("Invalid key type");
+ }
+
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_PRIVATE, &bFalse, sizeof(bFalse) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &secLen, sizeof(secLen) }
+ };
+
+ hDerive = CK_INVALID_HANDLE;
+ if (secLen > 0)
+ {
+ rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hKey,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hDerive) );
+ }
+ else
+ {
+ rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hKey,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE) - 1,
+ &hDerive) );
+ }
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check that KCV has been set
+ CK_ATTRIBUTE checkAttribs[] = {
+ { CKA_CHECK_VALUE, NULL_PTR, 0 }
+ };
+ CK_BYTE check[3];
+ checkAttribs[0].pValue = check;
+ checkAttribs[0].ulValueLen = sizeof(check);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hDerive, checkAttribs, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(checkAttribs[0].ulValueLen == 3);
+
+ if (keyType == CKK_GENERIC_SECRET) return;
+
+ CK_BYTE cipherText[300];
+ CK_ULONG ulCipherTextLen;
+ CK_BYTE recoveredText[300];
+ CK_ULONG ulRecoveredTextLen;
+
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechEncrypt,hDerive) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulCipherTextLen = sizeof(cipherText);
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,data,sizeof(data),cipherText,&ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechEncrypt,hDerive) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulRecoveredTextLen = sizeof(recoveredText);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ CPPUNIT_ASSERT(ulRecoveredTextLen==sizeof(data));
+
+ CPPUNIT_ASSERT(memcmp(data, recoveredText, sizeof(data)) == 0);
+}
+
+void DeriveTests::testSymDerive()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Generate base key
+#ifndef WITH_FIPS
+ CK_OBJECT_HANDLE hKeyDes = CK_INVALID_HANDLE;
+#endif
+ CK_OBJECT_HANDLE hKeyDes2 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hKeyDes3 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hKeyAes = CK_INVALID_HANDLE;
+#ifndef WITH_FIPS
+ rv = generateDesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKeyDes);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+#endif
+ rv = generateDes2Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKeyDes2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDes3Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKeyDes3);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateAesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKeyAes);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Derive keys
+ CK_OBJECT_HANDLE hDerive = CK_INVALID_HANDLE;
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_DES);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_AES);
+#endif
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_AES);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_AES);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_AES);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_DES);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_AES);
+#endif
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_AES);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_AES);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_AES);
+}
+
diff --git a/SoftHSMv2/src/lib/test/DeriveTests.h b/SoftHSMv2/src/lib/test/DeriveTests.h
new file mode 100644
index 0000000..5b2aef5
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/DeriveTests.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DeriveTests.h
+
+ Contains test cases to C_DeriveKey
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DERIVETESTS_H
+#define _SOFTHSM_V2_DERIVETESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class DeriveTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(DeriveTests);
+ CPPUNIT_TEST(testDhDerive);
+#ifdef WITH_ECC
+ CPPUNIT_TEST(testEcdhDerive);
+#endif
+ CPPUNIT_TEST(testSymDerive);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testDhDerive();
+#ifdef WITH_ECC
+ void testEcdhDerive();
+#endif
+ void testSymDerive();
+
+protected:
+ CK_RV generateDhKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ CK_RV generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+#ifndef WITH_FIPS
+ CK_RV generateDesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+#endif
+ CK_RV generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ void dhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey);
+#ifdef WITH_ECC
+ CK_RV generateEcKeyPair(const char* curve, CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ void ecdhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey, bool useRaw);
+#endif
+ bool compareSecret(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey1, CK_OBJECT_HANDLE hKey2);
+ void symDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE &hDerive, CK_MECHANISM_TYPE mechType, CK_KEY_TYPE keyType);
+};
+
+#endif // !_SOFTHSM_V2_DERIVETESTS_H
diff --git a/SoftHSMv2/src/lib/test/DigestTests.cpp b/SoftHSMv2/src/lib/test/DigestTests.cpp
new file mode 100644
index 0000000..b5e7e7e
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/DigestTests.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DigestTests.cpp
+
+ Contains test cases to C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "DigestTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DigestTests);
+
+void DigestTests::testDigestInit()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mechanism = {
+ CKM_VENDOR_DEFINED, NULL_PTR, 0
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(CK_INVALID_HANDLE, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ mechanism.mechanism = CKM_SHA512;
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_ACTIVE);
+}
+
+void DigestTests::testDigest()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mechanism = {
+ CKM_SHA512, NULL_PTR, 0
+ };
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+ CK_BYTE data[] = {"Text to digest"};
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(CK_INVALID_HANDLE, data, sizeof(data)-1, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, NULL_PTR, sizeof(data)-1, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ digest = (CK_BYTE_PTR)malloc(digestLen);
+ digestLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+ free(digest);
+}
+
+void DigestTests::testDigestUpdate()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mechanism = {
+ CKM_SHA512, NULL_PTR, 0
+ };
+ CK_BYTE data[] = {"Text to digest"};
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_DigestUpdate(hSession, data, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestUpdate(CK_INVALID_HANDLE, data, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_DigestUpdate(hSession, data, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestUpdate(hSession, NULL_PTR, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_DigestUpdate(hSession, data, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void DigestTests::testDigestKey()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mechanism = {
+ CKM_SHA512, NULL_PTR, 0
+ };
+ CK_BYTE data[] = {"Text to digest"};
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_DigestKey(hSession, (CK_OBJECT_HANDLE)123UL) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create the generic secret key to digest
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE genKeyType = CKK_GENERIC_SECRET;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_VALUE, data, sizeof(data) - 1 }
+ };
+ CK_OBJECT_HANDLE hKey;
+
+ hKey = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hKey != CK_INVALID_HANDLE);
+
+ rv = CRYPTOKI_F_PTR( C_DigestKey(CK_INVALID_HANDLE, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_DigestKey(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestKey(hSession, CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_KEY_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_DigestKey(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void DigestTests::testDigestFinal()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mechanism = {
+ CKM_SHA512, NULL_PTR, 0
+ };
+ CK_BYTE data[] = {"Text to digest"};
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(CK_INVALID_HANDLE, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestUpdate(hSession, data, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ digest = (CK_BYTE_PTR)malloc(digestLen);
+ digestLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, digest, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, digest, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(digest);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+}
+
+void DigestTests::testDigestAll()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanisms[] = {
+#ifndef WITH_FIPS
+ { CKM_MD5, NULL_PTR, 0 },
+#endif
+ { CKM_SHA_1, NULL_PTR, 0 },
+ { CKM_SHA224, NULL_PTR, 0 },
+ { CKM_SHA256, NULL_PTR, 0 },
+ { CKM_SHA384, NULL_PTR, 0 },
+ { CKM_SHA512, NULL_PTR, 0 },
+#ifdef WITH_GOST
+ { CKM_GOSTR3411, NULL_PTR, 0 },
+#endif
+ };
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+ CK_BYTE data[] = {"Text to digest"};
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ for (unsigned int i = 0; i < sizeof(mechanisms)/sizeof(CK_MECHANISM); i++)
+ {
+ rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanisms[i]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ digest = (CK_BYTE_PTR)malloc(digestLen);
+
+ rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(digest);
+ }
+}
diff --git a/SoftHSMv2/src/lib/test/DigestTests.h b/SoftHSMv2/src/lib/test/DigestTests.h
new file mode 100644
index 0000000..e724a39
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/DigestTests.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DigestTests.h
+
+ Contains test cases to C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DIGESTTESTS_H
+#define _SOFTHSM_V2_DIGESTTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class DigestTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(DigestTests);
+ CPPUNIT_TEST(testDigestInit);
+ CPPUNIT_TEST(testDigest);
+ CPPUNIT_TEST(testDigestUpdate);
+ CPPUNIT_TEST(testDigestKey);
+ CPPUNIT_TEST(testDigestFinal);
+ CPPUNIT_TEST(testDigestAll);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testDigestInit();
+ void testDigest();
+ void testDigestUpdate();
+ void testDigestKey();
+ void testDigestFinal();
+ void testDigestAll();
+};
+
+#endif // !_SOFTHSM_V2_DIGESTTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/InfoTests.cpp b/SoftHSMv2/src/lib/test/InfoTests.cpp
new file mode 100644
index 0000000..958d96e
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/InfoTests.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InfoTests.cpp
+
+ Contains test cases to C_GetInfo, C_GetFunctionList, C_GetSlotList,
+ C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, and C_GetMechanismInfo
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "InfoTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(InfoTests);
+
+void InfoTests::testGetInfo()
+{
+ CK_RV rv;
+ CK_INFO ckInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetInfo(&ckInfo) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetInfo(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetInfo(&ckInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InfoTests::testGetFunctionList()
+{
+ CK_RV rv;
+ CK_FUNCTION_LIST_PTR ckFuncList;
+
+ rv = CRYPTOKI_F_PTR( C_GetFunctionList(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetFunctionList(&ckFuncList) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InfoTests::testGetSlotList()
+{
+ CK_RV rv;
+ CK_ULONG ulSlotCount = 0;
+ CK_SLOT_ID_PTR pSlotList;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_FALSE, NULL_PTR, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ // Get the size of the buffer
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ pSlotList = (CK_SLOT_ID_PTR)malloc(ulSlotCount * sizeof(CK_SLOT_ID));
+
+ // Check if we have a too small buffer
+ ulSlotCount = 0;
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the slot list
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pSlotList);
+
+ // Get the number of slots with tokens
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ pSlotList = (CK_SLOT_ID_PTR)malloc(ulSlotCount * sizeof(CK_SLOT_ID));
+
+ // Check if we have a too small buffer
+ ulSlotCount = 0;
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, pSlotList, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the slot list
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, pSlotList, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pSlotList);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InfoTests::testGetSlotInfo()
+{
+ CK_RV rv;
+ CK_SLOT_INFO slotInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_invalidSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT ) == CKF_TOKEN_PRESENT);
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_REMOVABLE_DEVICE ) == 0);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InfoTests::testGetSlotInfoAlt()
+{
+ CK_RV rv;
+ CK_SLOT_INFO slotInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+#ifndef _WIN32
+ setenv("SOFTHSM2_CONF", "./softhsm2-alt.conf", 1);
+#else
+ setenv("SOFTHSM2_CONF", ".\\softhsm2-alt.conf", 1);
+#endif
+
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_invalidSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT ) == CKF_TOKEN_PRESENT);
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_REMOVABLE_DEVICE ) == CKF_REMOVABLE_DEVICE);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+#ifndef _WIN32
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+#else
+ setenv("SOFTHSM2_CONF", ".\\softhsm2.conf", 1);
+#endif
+}
+
+
+void InfoTests::testGetTokenInfo()
+{
+ CK_RV rv;
+ CK_TOKEN_INFO tokenInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_notInitializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_notInitializedTokenSlotID, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_invalidSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_notInitializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0);
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_initializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InfoTests::testGetMechanismList()
+{
+ CK_RV rv;
+ CK_ULONG ulMechCount = 0;
+ CK_MECHANISM_TYPE_PTR pMechanismList;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, NULL_PTR, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, NULL_PTR, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_invalidSlotID, NULL_PTR, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ // Get the size of the buffer
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, NULL_PTR, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ pMechanismList = (CK_MECHANISM_TYPE_PTR)malloc(ulMechCount * sizeof(CK_MECHANISM_TYPE_PTR));
+
+ // Check if we have a too small buffer
+ ulMechCount = 0;
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, pMechanismList, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the mechanism list
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, pMechanismList, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pMechanismList);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InfoTests::testGetMechanismInfo()
+{
+ CK_RV rv;
+ CK_MECHANISM_INFO info;
+ CK_ULONG ulMechCount = 0;
+ CK_MECHANISM_TYPE_PTR pMechanismList;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, CKM_RSA_PKCS, &info) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get the mechanism list
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, NULL_PTR, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(ulMechCount != 0);
+ pMechanismList = (CK_MECHANISM_TYPE_PTR)malloc(ulMechCount * sizeof(CK_MECHANISM_TYPE_PTR));
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, pMechanismList, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, pMechanismList[0], NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_invalidSlotID, pMechanismList[0], &info) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, CKM_VENDOR_DEFINED, &info) );
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ for (unsigned int i = 0; i < ulMechCount; i++)
+ {
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, pMechanismList[i], &info) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ }
+
+ free(pMechanismList);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
diff --git a/SoftHSMv2/src/lib/test/InfoTests.h b/SoftHSMv2/src/lib/test/InfoTests.h
new file mode 100644
index 0000000..4acf770
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/InfoTests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InfoTests.h
+
+ Contains test cases to C_GetInfo, C_GetFunctionList, C_GetSlotList,
+ C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, and C_GetMechanismInfo
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_INFOTESTS_H
+#define _SOFTHSM_V2_INFOTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class InfoTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(InfoTests);
+ CPPUNIT_TEST(testGetInfo);
+ CPPUNIT_TEST(testGetFunctionList);
+ CPPUNIT_TEST(testGetSlotList);
+ CPPUNIT_TEST(testGetSlotInfo);
+ CPPUNIT_TEST(testGetTokenInfo);
+ CPPUNIT_TEST(testGetMechanismList);
+ CPPUNIT_TEST(testGetMechanismInfo);
+ CPPUNIT_TEST(testGetSlotInfoAlt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testGetInfo();
+ void testGetFunctionList();
+ void testGetSlotList();
+ void testGetSlotInfo();
+ void testGetTokenInfo();
+ void testGetMechanismList();
+ void testGetMechanismInfo();
+ void testGetSlotInfoAlt();
+};
+
+#endif // !_SOFTHSM_V2_INFOTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/InitTests.cpp b/SoftHSMv2/src/lib/test/InitTests.cpp
new file mode 100644
index 0000000..71611f8
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/InitTests.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InitTests.cpp
+
+ Contains test cases to C_Initialize and C_Finalize
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "InitTests.h"
+#include "cryptoki.h"
+#include "osmutex.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(InitTests);
+
+void InitTests::setUp()
+{
+// printf("\nInitTests\n");
+
+#ifndef _WIN32
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+#else
+ setenv("SOFTHSM2_CONF", ".\\softhsm2.conf", 1);
+#endif
+}
+
+void InitTests::tearDown()
+{
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InitTests::testInit1()
+{
+ CK_RV rv;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit2()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+#ifdef CreateMutex
+#undef CreateMutex
+#endif
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = (CK_VOID_PTR)1;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.pReserved = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit3()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = (CK_UNLOCKMUTEX)1;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit4()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = (CK_UNLOCKMUTEX)1;
+ InitArgs.flags = CKF_OS_LOCKING_OK;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit5()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = OSCreateMutex;
+ InitArgs.DestroyMutex = OSDestroyMutex;
+ InitArgs.LockMutex = OSLockMutex;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = OSUnlockMutex;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit6()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = OSCreateMutex;
+ InitArgs.DestroyMutex = OSDestroyMutex;
+ InitArgs.LockMutex = OSLockMutex;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = CKF_OS_LOCKING_OK;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = OSUnlockMutex;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testFinal()
+{
+ CK_RV rv;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // pReserved is reserved for future versions
+ rv = CRYPTOKI_F_PTR( C_Finalize((CK_VOID_PTR)1) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/SoftHSMv2/src/lib/test/InitTests.h b/SoftHSMv2/src/lib/test/InitTests.h
new file mode 100644
index 0000000..ba22ec0
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/InitTests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InitTests.h
+
+ Contains test cases to C_Initialize and C_Finalize
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_INITTESTS_H
+#define _SOFTHSM_V2_INITTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "TestsNoPINInitBase.h"
+
+class InitTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(InitTests);
+ CPPUNIT_TEST(testInit1);
+ CPPUNIT_TEST(testInit2);
+ CPPUNIT_TEST(testInit3);
+ CPPUNIT_TEST(testInit4);
+ CPPUNIT_TEST(testInit5);
+ CPPUNIT_TEST(testInit6);
+ CPPUNIT_TEST(testFinal);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInit1();
+ void testInit2();
+ void testInit3();
+ void testInit4();
+ void testInit5();
+ void testInit6();
+ void testFinal();
+
+ virtual void setUp();
+ virtual void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_INITTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/Makefile.am b/SoftHSMv2/src/lib/test/Makefile.am
new file mode 100644
index 0000000..4345878
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/Makefile.am
@@ -0,0 +1,40 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../pkcs11 \
+ @CPPUNIT_CFLAGS@
+
+check_PROGRAMS = p11test
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+p11test_SOURCES = p11test.cpp \
+ SymmetricAlgorithmTests.cpp \
+ DigestTests.cpp \
+ InitTests.cpp \
+ InfoTests.cpp \
+ RandomTests.cpp \
+ SessionTests.cpp \
+ TokenTests.cpp \
+ UserTests.cpp \
+ ObjectTests.cpp \
+ DeriveTests.cpp \
+ SignVerifyTests.cpp \
+ AsymEncryptDecryptTests.cpp \
+ AsymWrapUnwrapTests.cpp \
+ TestsBase.cpp \
+ TestsNoPINInitBase.cpp \
+ ../common/log.cpp \
+ ../common/osmutex.cpp
+
+p11test_LDADD = ../libsofthsm2.la
+
+p11test_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install -pthread -static
+
+TESTS = p11test
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/softhsm2-alt.conf.win32 \
+ $(srcdir)/softhsm2.conf.win32 \
+ $(srcdir)/tokens/dummy.in
diff --git a/SoftHSMv2/src/lib/test/ObjectTests.cpp b/SoftHSMv2/src/lib/test/ObjectTests.cpp
new file mode 100644
index 0000000..cd6c676
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/ObjectTests.cpp
@@ -0,0 +1,2393 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectTests.cpp
+
+ Contains test cases for:
+ C_CreateObject
+ C_CopyObject
+ C_DestroyObject
+ C_GetAttributeValue
+ C_SetAttributeValue
+ C_FindObjectsInit
+ C_FindObjects
+ C_FindObjectsFinal
+ C_GenererateKeyPair
+
+ Below is a list of tests we need to add in order to verify that the PKCS#11 library
+ is working as expected.
+
+ We want to be sure that order of attributes does not impact the tests, therefore
+ every function involving attributes should have the order of the attributes
+ in the template randomized.
+
+ We want to be sure that only attributes that are specified as being part of an
+ object class can be used when creating an object.
+ Using other attributes should return an error on creation of the object.
+
+ We want to be sure that attributes that are required but missing will result
+ in a template incomplete return value.
+
+ We want to be sure that we get an error when trying to modify an attribute that
+ may not be modified
+
+ We want to be sure that attributes that may be changed to one value but not
+ back to the previous value are handled correctly.
+
+ We want to verify that an error is returned when we are trying to modify
+ read-only attributes.
+
+ We want to verify that sensitive attributes cannot be read.
+
+ Because the teardown also removes token objects it is not really
+ required to destroy objects created during the test in the CreateObject tests.
+
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ObjectTests.h"
+
+// Common object attributes
+const CK_BBOOL CKA_TOKEN_DEFAULT = CK_FALSE;
+//const CK_BBOOL CKA_PRIVATE_DEFAULT = <token/object attribute dependent>
+const CK_BBOOL CKA_MODIFIABLE_DEFAULT = CK_TRUE;
+const CK_UTF8CHAR_PTR CKA_LABEL_DEFAULT = NULL;
+const CK_BBOOL CKA_COPYABLE_DEFAULT = CK_TRUE;
+const CK_BBOOL CKA_DESTROYABLE_DEFAULT = CK_TRUE;
+
+// Data Object Attributes
+const CK_UTF8CHAR_PTR CKA_APPLICATION_DEFAULT = NULL;
+const CK_BYTE_PTR CKA_OBJECT_ID_DEFAULT = NULL;
+const CK_BYTE_PTR CKA_VALUE_DEFAULT = NULL;
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectTests);
+
+void ObjectTests::checkCommonObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_OBJECT_CLASS objClass)
+{
+ CK_RV rv;
+
+ CK_OBJECT_CLASS obj_class = CKO_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CLASS, &obj_class, sizeof(obj_class) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(obj_class == objClass);
+}
+
+void ObjectTests::checkCommonStorageObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BBOOL bToken, CK_BBOOL /*bPrivate*/, CK_BBOOL bModifiable, CK_UTF8CHAR_PTR pLabel, CK_ULONG ulLabelLen, CK_BBOOL bCopyable, CK_BBOOL bDestroyable)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_token = CK_FALSE;
+ CK_BBOOL obj_private = CK_FALSE;
+ CK_BBOOL obj_modifiable = CK_FALSE;
+ CK_BBOOL obj_copyable = CK_FALSE;
+ CK_BBOOL obj_destroyable = CK_FALSE;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, NULL_PTR, 0 },
+ { CKA_TOKEN, &obj_token, sizeof(obj_token) },
+ { CKA_PRIVATE, &obj_private, sizeof(obj_private) },
+ { CKA_MODIFIABLE, &obj_modifiable, sizeof(obj_modifiable) },
+ { CKA_COPYABLE, &obj_copyable, sizeof(obj_copyable) },
+ { CKA_DESTROYABLE, &obj_destroyable, sizeof(obj_destroyable) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 6) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulLabelLen);
+ CPPUNIT_ASSERT(obj_token == bToken);
+ /* Default is token-specifict
+ CPPUNIT_ASSERT(obj_private == bPrivate); */
+ CPPUNIT_ASSERT(obj_modifiable == bModifiable);
+ CPPUNIT_ASSERT(obj_copyable == bCopyable);
+ CPPUNIT_ASSERT(obj_destroyable == bDestroyable);
+ if (ulLabelLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pLabel, ulLabelLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkDataObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_UTF8CHAR_PTR pApplication, CK_ULONG ulApplicationLen, CK_BYTE_PTR pObjectID, CK_ULONG ulObjectIdLen, CK_BYTE_PTR pValue, CK_ULONG ulValueLen)
+{
+ CK_RV rv;
+
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_APPLICATION, NULL_PTR, 0 },
+ { CKA_OBJECT_ID, NULL_PTR, 0 },
+ { CKA_VALUE, NULL_PTR, 0 }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 3) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+ attribs[2].pValue = (CK_VOID_PTR)malloc(attribs[2].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 3) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulApplicationLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulObjectIdLen);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulValueLen);
+ if (ulApplicationLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pApplication, ulApplicationLen) == 0);
+ if (ulObjectIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pObjectID, ulObjectIdLen) == 0);
+ if (ulValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[2].pValue, pValue, ulValueLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+ free(attribs[2].pValue);
+}
+
+void ObjectTests::checkCommonCertificateObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_CERTIFICATE_TYPE certType, CK_BBOOL bTrusted, CK_ULONG ulCertificateCategory, CK_BYTE_PTR pCheckValue, CK_ULONG ulCheckValueLen, CK_DATE startDate, CK_ULONG ulStartDateLen, CK_DATE endDate, CK_ULONG ulEndDateLen)
+{
+ CK_RV rv;
+
+ CK_CERTIFICATE_TYPE obj_type = CKC_X_509;
+ CK_BBOOL obj_trusted = CK_FALSE;
+ CK_ULONG obj_category = 0;
+ CK_DATE obj_start;
+ CK_DATE obj_end;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CHECK_VALUE, NULL_PTR, 0 },
+ { CKA_CERTIFICATE_TYPE, &obj_type, sizeof(obj_type) },
+ { CKA_TRUSTED, &obj_trusted, sizeof(obj_trusted) },
+ { CKA_CERTIFICATE_CATEGORY, &obj_category, sizeof(obj_category) },
+ { CKA_START_DATE, &obj_start, sizeof(obj_start) },
+ { CKA_END_DATE, &obj_end, sizeof(obj_end) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 6) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulCheckValueLen);
+ CPPUNIT_ASSERT(obj_type == certType);
+ CPPUNIT_ASSERT(obj_trusted == bTrusted);
+ CPPUNIT_ASSERT(obj_category == ulCertificateCategory);
+ CPPUNIT_ASSERT(attribs[4].ulValueLen == ulStartDateLen);
+ CPPUNIT_ASSERT(attribs[5].ulValueLen == ulEndDateLen);
+ if (ulCheckValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pCheckValue, ulCheckValueLen) == 0);
+ if (ulStartDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[4].pValue, &startDate, ulStartDateLen) == 0);
+ if (ulEndDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[5].pValue, &endDate, ulEndDateLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkX509CertificateObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BYTE_PTR pId, CK_ULONG ulIdLen, CK_BYTE_PTR pIssuer, CK_ULONG ulIssuerLen, CK_BYTE_PTR pSerialNumber, CK_ULONG ulSerialNumberLen, CK_BYTE_PTR pValue, CK_ULONG ulValueLen, CK_BYTE_PTR pUrl, CK_ULONG ulUrlLen, CK_BYTE_PTR pHashOfSubjectPublicKey, CK_ULONG ulHashOfSubjectPublicKeyLen, CK_BYTE_PTR pHashOfIssuerPublicKey, CK_ULONG ulHashOfIssuerPublicKeyLen, CK_ULONG ulJavaMidpSecurityDomain, CK_MECHANISM_TYPE nameHashAlgorithm)
+{
+ CK_RV rv;
+
+ CK_ULONG obj_java = 0;
+ CK_MECHANISM_TYPE obj_mech = CKM_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_ID, NULL_PTR, 0 },
+ { CKA_ISSUER, NULL_PTR, 0 },
+ { CKA_SERIAL_NUMBER, NULL_PTR, 0 },
+ { CKA_VALUE, NULL_PTR, 0 },
+ { CKA_URL, NULL_PTR, 0 },
+ { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, NULL_PTR, 0 },
+ { CKA_HASH_OF_ISSUER_PUBLIC_KEY, NULL_PTR, 0 },
+ { CKA_JAVA_MIDP_SECURITY_DOMAIN, &obj_java, sizeof(obj_java) },
+ { CKA_NAME_HASH_ALGORITHM, &obj_mech, sizeof(obj_mech) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 8) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+ attribs[2].pValue = (CK_VOID_PTR)malloc(attribs[2].ulValueLen);
+ attribs[3].pValue = (CK_VOID_PTR)malloc(attribs[3].ulValueLen);
+ attribs[4].pValue = (CK_VOID_PTR)malloc(attribs[4].ulValueLen);
+ attribs[5].pValue = (CK_VOID_PTR)malloc(attribs[5].ulValueLen);
+ attribs[6].pValue = (CK_VOID_PTR)malloc(attribs[6].ulValueLen);
+ attribs[7].pValue = (CK_VOID_PTR)malloc(attribs[7].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 10) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulIdLen);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulIssuerLen);
+ CPPUNIT_ASSERT(attribs[3].ulValueLen == ulSerialNumberLen);
+ CPPUNIT_ASSERT(attribs[4].ulValueLen == ulValueLen);
+ CPPUNIT_ASSERT(attribs[5].ulValueLen == ulUrlLen);
+ CPPUNIT_ASSERT(attribs[6].ulValueLen == ulHashOfSubjectPublicKeyLen);
+ CPPUNIT_ASSERT(attribs[7].ulValueLen == ulHashOfIssuerPublicKeyLen);
+ CPPUNIT_ASSERT(obj_java == ulJavaMidpSecurityDomain);
+ CPPUNIT_ASSERT(obj_mech == nameHashAlgorithm);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+ if (ulIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pId, ulIdLen) == 0);
+ if (ulIssuerLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[2].pValue, pIssuer, ulIssuerLen) == 0);
+ if (ulSerialNumberLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[3].pValue, pSerialNumber, ulSerialNumberLen) == 0);
+ if (ulValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[4].pValue, pValue, ulValueLen) == 0);
+ if (ulUrlLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[5].pValue, pUrl, ulUrlLen) == 0);
+ if (ulHashOfSubjectPublicKeyLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[6].pValue, pHashOfSubjectPublicKey, ulHashOfSubjectPublicKeyLen) == 0);
+ if (ulHashOfIssuerPublicKeyLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[7].pValue, pHashOfIssuerPublicKey, ulHashOfIssuerPublicKeyLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+ free(attribs[2].pValue);
+ free(attribs[3].pValue);
+ free(attribs[4].pValue);
+ free(attribs[5].pValue);
+ free(attribs[6].pValue);
+ free(attribs[7].pValue);
+}
+
+void ObjectTests::checkCommonKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_KEY_TYPE keyType, CK_BYTE_PTR pId, CK_ULONG ulIdLen, CK_DATE startDate, CK_ULONG ulStartDateLen, CK_DATE endDate, CK_ULONG ulEndDateLen, CK_BBOOL bDerive, CK_BBOOL bLocal, CK_MECHANISM_TYPE keyMechanismType, CK_MECHANISM_TYPE_PTR pAllowedMechanisms, CK_ULONG ulAllowedMechanismsLen)
+{
+ CK_RV rv;
+
+ CK_KEY_TYPE obj_type = CKK_VENDOR_DEFINED;
+ CK_DATE obj_start;
+ CK_DATE obj_end;
+ CK_BBOOL obj_derive = CK_FALSE;
+ CK_BBOOL obj_local = CK_FALSE;
+ CK_MECHANISM_TYPE obj_mech = CKM_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_ID, NULL_PTR, 0 },
+ { CKA_KEY_TYPE, &obj_type, sizeof(obj_type) },
+ { CKA_START_DATE, &obj_start, sizeof(obj_start) },
+ { CKA_END_DATE, &obj_end, sizeof(obj_end) },
+ { CKA_DERIVE, &obj_derive, sizeof(obj_derive) },
+ { CKA_LOCAL, &obj_local, sizeof(obj_local) },
+ { CKA_KEY_GEN_MECHANISM, &obj_mech, sizeof(obj_mech) },
+ { CKA_ALLOWED_MECHANISMS, NULL_PTR, 0 }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 8) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulIdLen);
+ CPPUNIT_ASSERT(obj_type == keyType);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulStartDateLen);
+ CPPUNIT_ASSERT(attribs[3].ulValueLen == ulEndDateLen);
+ CPPUNIT_ASSERT(obj_derive == bDerive);
+ CPPUNIT_ASSERT(obj_local == bLocal);
+ CPPUNIT_ASSERT(obj_mech == keyMechanismType);
+ CPPUNIT_ASSERT(attribs[7].ulValueLen == ulAllowedMechanismsLen);
+
+ if (ulIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pId, ulIdLen) == 0);
+ if (ulStartDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[2].pValue, &startDate, ulStartDateLen) == 0);
+ if (ulEndDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[3].pValue, &endDate, ulEndDateLen) == 0);
+ if (ulAllowedMechanismsLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[7].pValue, pAllowedMechanisms, ulAllowedMechanismsLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonPublicKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BBOOL /*bEncrypt*/, CK_BBOOL /*bVerify*/, CK_BBOOL /*bVerifyRecover*/, CK_BBOOL /*bWrap*/, CK_BBOOL bTrusted, CK_ATTRIBUTE_PTR pWrapTemplate, CK_ULONG ulWrapTemplateLen)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_encrypt = CK_FALSE;
+ CK_BBOOL obj_verify = CK_FALSE;
+ CK_BBOOL obj_verify_recover = CK_FALSE;
+ CK_BBOOL obj_wrap = CK_FALSE;
+ CK_BBOOL obj_trusted = CK_FALSE;
+ CK_LONG len_wrap_template = ulWrapTemplateLen;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_ENCRYPT, &obj_encrypt, sizeof(obj_encrypt) },
+ { CKA_VERIFY, &obj_verify, sizeof(obj_verify) },
+ { CKA_VERIFY_RECOVER, &obj_verify_recover, sizeof(obj_verify_recover) },
+ { CKA_WRAP, &obj_wrap, sizeof(obj_wrap) },
+ { CKA_TRUSTED, &obj_trusted, sizeof(obj_trusted) },
+ { CKA_WRAP_TEMPLATE, pWrapTemplate, ulWrapTemplateLen }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 7) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ /* Default is token-specifict
+ CPPUNIT_ASSERT(obj_encrypt == bEncrypt);
+ CPPUNIT_ASSERT(obj_verify == bVerify);
+ CPPUNIT_ASSERT(obj_verify_recover == bVerifyRecover);
+ CPPUNIT_ASSERT(obj_wrap == bWrap); */
+ CPPUNIT_ASSERT(obj_trusted == bTrusted);
+ len_wrap_template = attribs[6].ulValueLen;
+ CPPUNIT_ASSERT(len_wrap_template == 0);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonPrivateKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BBOOL bSensitive, CK_BBOOL bDecrypt, CK_BBOOL bSign, CK_BBOOL bSignRecover, CK_BBOOL bUnwrap, CK_BBOOL bExtractable, CK_BBOOL bAlwaysSensitive, CK_BBOOL bNeverExtractable, CK_BBOOL bWrapWithTrusted, CK_ATTRIBUTE_PTR pUnwrapTemplate, CK_ULONG ulUnwrapTemplateLen, CK_BBOOL bAlwaysAuthenticate)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_sensitive = CK_FALSE;
+ CK_BBOOL obj_decrypt = CK_FALSE;
+ CK_BBOOL obj_sign = CK_FALSE;
+ CK_BBOOL obj_sign_recover = CK_FALSE;
+ CK_BBOOL obj_unwrap = CK_FALSE;
+ CK_BBOOL obj_extractable = CK_FALSE;
+ CK_BBOOL obj_always_sensitive = CK_FALSE;
+ CK_BBOOL obj_never_extractable = CK_FALSE;
+ CK_BBOOL obj_wrap_with_trusted = CK_FALSE;
+ CK_BBOOL obj_always_authenticate = CK_FALSE;
+ CK_LONG len_unwrap_template = ulUnwrapTemplateLen;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_SENSITIVE, &obj_sensitive, sizeof(obj_sensitive) },
+ { CKA_DECRYPT, &obj_decrypt, sizeof(obj_decrypt) },
+ { CKA_SIGN, &obj_sign, sizeof(obj_sign) },
+ { CKA_SIGN_RECOVER, &obj_sign_recover, sizeof(obj_sign_recover) },
+ { CKA_UNWRAP, &obj_unwrap, sizeof(obj_unwrap) },
+ { CKA_EXTRACTABLE, &obj_extractable, sizeof(obj_extractable) },
+ { CKA_ALWAYS_SENSITIVE, &obj_always_sensitive, sizeof(obj_always_sensitive) },
+ { CKA_NEVER_EXTRACTABLE, &obj_never_extractable, sizeof(obj_never_extractable) },
+ { CKA_WRAP_WITH_TRUSTED, &obj_wrap_with_trusted, sizeof(obj_wrap_with_trusted) },
+ { CKA_UNWRAP_TEMPLATE, pUnwrapTemplate, ulUnwrapTemplateLen },
+ { CKA_ALWAYS_AUTHENTICATE, &obj_always_authenticate, sizeof(obj_always_authenticate) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 12) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ CPPUNIT_ASSERT(obj_sensitive == bSensitive);
+ CPPUNIT_ASSERT(obj_decrypt == bDecrypt);
+ CPPUNIT_ASSERT(obj_sign == bSign);
+ CPPUNIT_ASSERT(obj_sign_recover == bSignRecover);
+ CPPUNIT_ASSERT(obj_unwrap == bUnwrap);
+ CPPUNIT_ASSERT(obj_extractable == bExtractable);
+ CPPUNIT_ASSERT(obj_always_sensitive == bAlwaysSensitive);
+ CPPUNIT_ASSERT(obj_never_extractable == bNeverExtractable);
+ CPPUNIT_ASSERT(obj_wrap_with_trusted == bWrapWithTrusted);
+ CPPUNIT_ASSERT(obj_always_authenticate == bAlwaysAuthenticate);
+ len_unwrap_template = attribs[10].ulValueLen;
+ CPPUNIT_ASSERT(len_unwrap_template == 0);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonRSAPublicKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen, CK_ULONG ulModulusBits, CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen)
+{
+ CK_RV rv;
+
+ CK_ULONG obj_bits = 0;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_MODULUS, NULL_PTR, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 },
+ { CKA_MODULUS_BITS, &obj_bits, sizeof(obj_bits) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 3) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulModulusLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulPublicExponentLen);
+ CPPUNIT_ASSERT(obj_bits == ulModulusBits);
+ if (ulModulusLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pModulus, ulModulusLen) == 0);
+ if (ulPublicExponentLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pPublicExponent, ulPublicExponentLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+}
+
+void ObjectTests::checkCommonRSAPrivateKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen, CK_BYTE_PTR /*pPublicExponent*/, CK_ULONG /*ulPublicExponentLen*/, CK_BYTE_PTR pPrivateExponent, CK_ULONG ulPrivateExponentLen, CK_BYTE_PTR /*pPrime1*/, CK_ULONG /*ulPrime1Len*/, CK_BYTE_PTR /*pPrime2*/, CK_ULONG /*ulPrime2Len*/, CK_BYTE_PTR /*pExponent1*/, CK_ULONG /*ulExponent1Len*/, CK_BYTE_PTR /*pExponent2*/, CK_ULONG /*ulExponent2Len*/, CK_BYTE_PTR /*pCoefficient*/, CK_ULONG /*ulCoefficientLen*/)
+{
+ CK_RV rv;
+
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_MODULUS, NULL_PTR, 0 },
+ { CKA_PRIVATE_EXPONENT, NULL_PTR, 0 }
+ /* Some tokens may only store modulus and private exponent
+ { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 },
+ { CKA_PRIME_1, NULL_PTR, 0 },
+ { CKA_PRIME_2, NULL_PTR, 0 },
+ { CKA_EXPONENT_1, NULL_PTR, 0 },
+ { CKA_EXPONENT_2, NULL_PTR, 0 },
+ { CKA_COEFFICIENT, NULL_PTR, 0 }, */
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulModulusLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulPrivateExponentLen);
+ if (ulModulusLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pModulus, ulModulusLen) == 0);
+ if (ulPrivateExponentLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pPrivateExponent, ulPrivateExponentLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+}
+
+CK_RV ObjectTests::createDataObjectMinimal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_UTF8CHAR label[] = "A data object";
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ //CKA_MODIFIABLE
+ { CKA_LABEL, label, sizeof(label)-1 },
+ //CKA_COPYABLE
+ //CKA_DESTROYABLE
+
+ // Data
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::createDataObjectMCD(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_BBOOL bModifiable, CK_BBOOL bCopyable, CK_BBOOL bDestroyable, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_UTF8CHAR label[] = "A data object";
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_MODIFIABLE, &bModifiable, sizeof(bModifiable) },
+ { CKA_LABEL, label, sizeof(label)-1 },
+ { CKA_COPYABLE, &bCopyable, sizeof(bCopyable) },
+ { CKA_DESTROYABLE, &bDestroyable, sizeof(bDestroyable) }
+
+ // Data
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::createDataObjectNormal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_UTF8CHAR label[] = "A data object";
+
+ CK_UTF8CHAR application[] = "An application";
+ CK_BYTE objectID[] = "invalid object id";
+ CK_BYTE data[] = "Sample data";
+
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ //CKA_MODIFIABLE
+ { CKA_LABEL, label, sizeof(label)-1 },
+ //CKA_COPYABLE
+ //CKA_DESTROYABLE
+
+ // Data
+ { CKA_APPLICATION, application, sizeof(application)-1 },
+ { CKA_OBJECT_ID, objectID, sizeof(objectID) },
+ { CKA_VALUE, data, sizeof(data) }
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::createCertificateObjectIncomplete(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_CERTIFICATE;
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) }
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::createCertificateObjectX509(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE cType = CKC_X_509;
+ const char *pSubject = "invalid subject der";
+ const char *pValue = "invalid certificate der";
+
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ // Common Certificate Object Attributes
+ { CKA_CERTIFICATE_TYPE, &cType, sizeof(cType) },
+ // X.509 Certificate Object Attributes
+ { CKA_SUBJECT, (CK_VOID_PTR)pSubject, strlen(pSubject) },
+ { CKA_VALUE, (CK_VOID_PTR)pValue, strlen(pValue) }
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+void ObjectTests::testCreateObject()
+{
+// printf("\ntestCreateObject\n");
+
+ // [PKCS#11 v2.40, C_CreateObject]
+ // a. Only session objects can be created during read-only session.
+ // b. Only public objects can be created unless the normal user is logged in.
+ // c. Key object will have CKA_LOCAL == CK_FALSE.
+ // d. If key object is secret or a private key then both CKA_ALWAYS_SENSITIVE == CK_FALSE and CKA_NEVER_EXTRACTABLE == CKA_FALSE.
+
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject;
+
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE genKeyType = CKK_GENERIC_SECRET;
+ CK_BYTE keyPtr[128];
+ CK_ULONG keyLen = 128;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) },
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE, keyPtr, keyLen }
+ };
+
+ CK_BBOOL local;
+ CK_BBOOL always;
+ CK_BBOOL never;
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_LOCAL, &local, sizeof(local) },
+ { CKA_ALWAYS_SENSITIVE, &always, sizeof(always) },
+ { CKA_NEVER_EXTRACTABLE, &never, sizeof(never) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-ONLY & PUBLIC
+ /////////////////////////////////
+
+ // Open read-only session and don't login
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should not be allowed to create token objects because the session is read-only
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ /////////////////////////////////
+ // READ-ONLY & USER
+ /////////////////////////////////
+
+ // Login USER into the read-only session
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create private session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should not be allowed to create token objects.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & PUBLIC
+ /////////////////////////////////
+
+ // Open as read-write session but don't login.
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should not be able to create private token objects because we are not logged in now
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & USER
+ /////////////////////////////////
+
+ // Open as read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login to the read-write session
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should always be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be able allowed to create private session objects because we are logged in.
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be able to create private token objects because we are logged in now
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & SO
+ /////////////////////////////////
+
+ // Open as read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login to the read-write session
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_SO,m_soPin1,m_soPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should always be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in.
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & USER
+ /////////////////////////////////
+
+ // Open as read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login to the read-write session
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Create a secret object
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, keyPtr, keyLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, getTemplate, 3) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(local == CK_FALSE);
+ CPPUNIT_ASSERT(always == CK_FALSE);
+ CPPUNIT_ASSERT(never == CK_FALSE);
+
+ // Destroy the secret object
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testCopyObject()
+{
+// printf("\ntestCopyObject\n");
+
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject;
+ CK_OBJECT_HANDLE hObjectCopy;
+ CK_OBJECT_HANDLE hObject1;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session and don't login
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get a public session object
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMCD(hSession, IN_SESSION, IS_PUBLIC, CK_TRUE, CK_FALSE, CK_TRUE, hObjectCopy);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Allowed to copy it
+ const char *pLabel = "Label modified via C_CopyObject";
+ CK_BBOOL bToken = CK_FALSE;
+ CK_BBOOL bPrivate = CK_FALSE;
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, (CK_UTF8CHAR_PTR)pLabel, strlen(pLabel) },
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_CLASS, &cClass, sizeof(cClass) }
+ };
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 1, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Not allowed to copy.
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObjectCopy, &attribs[0], 1, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_ACTION_PROHIBITED);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObjectCopy) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Still allowed when still session and public
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Not allowed to overwrite an !ck8 attribute
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 4, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+
+ // Not allowed to go on token
+ bToken = CK_TRUE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ bToken = CK_FALSE;
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // Not allowed to go to private
+ bPrivate = CK_TRUE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ bPrivate = CK_FALSE;
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create a read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private object
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get a public session object
+ rv = createDataObjectNormal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Allowed to go on token
+ bToken = CK_TRUE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Allowed to go to private
+ bPrivate = CK_TRUE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Not allowed to change a !ck8 parameter
+ CK_BYTE id[] = "Another object ID";
+ attribs[3].type = CKA_OBJECT_ID;
+ attribs[3].pValue = id;
+ attribs[3].ulValueLen = sizeof(id);
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 4, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+
+ // Not allowed to downgrade privacy
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectNormal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ bToken = CK_FALSE;
+ bPrivate = CK_FALSE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_TEMPLATE_INCONSISTENT);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testDestroyObject()
+{
+// printf("\ntestDestroyObject\n");
+
+ // [PKCS#11 v2.40, C_Logout] When logout is successful...
+ // a. Any of the application's handles to private objects become invalid.
+ // b. Even if a user is later logged back into the token those handles remain invalid.
+ // c. All private session objects from sessions belonging to the application area destroyed.
+
+ // [PKCS#11 v2.40, C_CreateObject]
+ // Only session objects can be created during read-only session.
+ // Only public objects can be created unless the normal user is logged in.
+
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+ CK_OBJECT_HANDLE hObjectDestroy;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Try to destroy an invalid object using an invalid session
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ // Create a read-only session.
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Trying to destroy an invalid object in a read-only session
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // Create a read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Trying to destroy an invalid object in a read-write session
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMCD(hSessionRW, IN_SESSION, IS_PUBLIC, CK_TRUE, CK_TRUE, CK_FALSE, hObjectDestroy);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should not be able to destroy a non-destroyable object.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,hObjectDestroy) );
+ CPPUNIT_ASSERT(rv == CKR_ACTION_PROHIBITED);
+
+ // On a read-only session we should not be able to destroy the public token object
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,hObjectTokenPublic) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // On a read-only session we should not be able to destroy the private token object
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,hObjectTokenPrivate) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // Logout with a different session than the one used for login should be fine.
+ rv = CRYPTOKI_F_PTR( C_Logout(hSessionRW) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Login USER into the sessions so we can destroy private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should be able to destroy the public session object from a read-only session.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,hObjectSessionPublic) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // All private session objects should have been destroyed when logging out.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRW,hObjectSessionPrivate) );
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // We should be able to destroy the public token object now.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRW,hObjectTokenPublic) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // All handles to private token objects should have been invalidated when logging out.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRW,hObjectTokenPrivate) );
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testGetObjectSize()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open a session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get an object
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get the object size
+ CK_ULONG objectSize;
+ rv = CRYPTOKI_F_PTR( C_GetObjectSize(hSession, hObject, &objectSize) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(objectSize == CK_UNAVAILABLE_INFORMATION);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testGetAttributeValue()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Try to destroy an invalid object using an invalid session
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSessionRO,CK_INVALID_HANDLE,NULL,1) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_OBJECT_CLASS cClass = CKO_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CLASS, &cClass, sizeof(cClass) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1) );//sizeof(attribs)/sizeof(CK_ATTRIBUTE));
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testSetAttributeValue()
+{
+ // [PKCS#11 v2.40, 4.1.1 Creating objects]
+ // 1. If the supplied template specifies a value for an invalid attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_TYPE_INVALID. An attribute
+ // is valid if it is either one of the attributes described in the Cryptoki specification or an
+ // additional vendor-specific attribute supported by the library and token.
+ //
+ // 2. If the supplied template specifies an invalid value for a valid attribute, then the
+ // attempt should fail with the error code CKR_ATTRIBUTE_VALUE_INVALID.
+ // The valid values for Cryptoki attributes are described in the Cryptoki specification.
+ //
+ // 3. If the supplied template specifies a value for a read-only attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_READ_ONLY. Whether or not a
+ // given Cryptoki attribute is read-only is explicitly stated in the Cryptoki specification;
+ // however, a particular library and token may be even more restrictive than Cryptoki
+ // specifies. In other words, an attribute which Cryptoki says is not read-only may
+ // nonetheless be read-only under certain circumstances (i.e., in conjunction with some
+ // combinations of other attributes) for a particular library and token. Whether or not a
+ // given non-Cryptoki attribute is read-only is obviously outside the scope of Cryptoki.
+ //
+ // 4. N/A (Does not apply to C_SetAttributeValue)
+ //
+ // 5. If the attribute values in the supplied template, together with any default attribute
+ // values and any attribute values contributed to the object by the object-creation
+ // function itself, are inconsistent, then the attempt should fail with the error code
+ // CKR_TEMPLATE_INCONSISTENT. A set of attribute values is inconsistent if not
+ // all of its members can be satisfied simultaneously by the token, although each value
+ // individually is valid in Cryptoki. One example of an inconsistent template would be
+ // using a template which specifies two different values for the same attribute. Another
+ // example would be trying to create a secret key object with an attribute which is
+ // appropriate for various types of public keys or private keys, but not for secret keys.
+ // A final example would be a template with an attribute that violates some token
+ // specific requirement. Note that this final example of an inconsistent template is
+ // token-dependent—on a different token, such a template might not be inconsistent.
+ //
+ // 6. If the supplied template specifies the same value for a particular attribute more than
+ // once (or the template specifies the same value for a particular attribute that the object-
+ // creation function itself contributes to the object), then the behavior of Cryptoki is not
+ // completely specified. The attempt to create an object can either succeed—thereby
+ // creating the same object that would have been created if the multiply-specified
+ // attribute had only appeared once—or it can fail with error code
+ // CKR_TEMPLATE_INCONSISTENT. Library developers are encouraged to make
+ // their libraries behave as though the attribute had only appeared once in the template;
+ // application developers are strongly encouraged never to put a particular attribute into
+ // a particular template more than once.
+
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+ CK_OBJECT_HANDLE hObjectSet;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMCD(hSessionRO, IN_SESSION, IS_PUBLIC, CK_FALSE, CK_TRUE, CK_TRUE, hObjectSet);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check that label can be modified on all combintations of session/token and public/private objects
+ const char *pLabel = "Label modified via C_SetAttributeValue";
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, (CK_UTF8CHAR_PTR)pLabel, strlen(pLabel) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSessionPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectTokenPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRW,hObjectTokenPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectTokenPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRW,hObjectTokenPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSet,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_ACTION_PROHIBITED);
+
+ attribs[0].pValue = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSessionRO,hObjectSessionPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == strlen(pLabel));
+
+ char pStoredLabel[64];
+ attribs[0].pValue = &pStoredLabel[0];
+ attribs[0].ulValueLen = 64;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSessionRO,hObjectSessionPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == strlen(pLabel));
+ CPPUNIT_ASSERT(memcmp(pLabel,pStoredLabel,strlen(pLabel)) == 0);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testFindObjects()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Set labels for the objects
+ const char *pLabel = "Label modified via C_SetAttributeValue";
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, (CK_UTF8CHAR_PTR)pLabel, strlen(pLabel) }
+ };
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSessionPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRW,hObjectTokenPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRW,hObjectTokenPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find the objects while logged in should find them all.
+ rv = CRYPTOKI_F_PTR( C_FindObjectsInit(hSessionRO,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_OBJECT_HANDLE hObjects[16];
+ CK_ULONG ulObjectCount = 0;
+ rv = CRYPTOKI_F_PTR( C_FindObjects(hSessionRO,&hObjects[0],16,&ulObjectCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(4 == ulObjectCount);
+ rv = CRYPTOKI_F_PTR( C_FindObjectsFinal(hSessionRO) );
+
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find the objects while no longer logged in should find only 2
+ rv = CRYPTOKI_F_PTR( C_FindObjectsInit(hSessionRO,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_FindObjects(hSessionRO,&hObjects[0],16,&ulObjectCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(2 == ulObjectCount);
+ rv = CRYPTOKI_F_PTR( C_FindObjectsFinal(hSessionRO) );
+
+ // Close the session used to create the session objects, should also destroy the session objects.
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find just the public token object as public session object should be gone now.
+ rv = CRYPTOKI_F_PTR( C_FindObjectsInit(hSessionRW,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_FindObjects(hSessionRW,&hObjects[0],16,&ulObjectCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(1 == ulObjectCount);
+ rv = CRYPTOKI_F_PTR( C_FindObjectsFinal(hSessionRW) );
+
+ // Login USER into the sessions so we can gain access to private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRW,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Now find just the public token object as public session object should be gone now.
+ rv = CRYPTOKI_F_PTR( C_FindObjectsInit(hSessionRW,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_FindObjects(hSessionRW,&hObjects[0],16,&ulObjectCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(2 == ulObjectCount);
+ rv = CRYPTOKI_F_PTR( C_FindObjectsFinal(hSessionRW) );
+}
+
+
+void ObjectTests::testGenerateKeys()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token public/private key pairs.
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testCreateCertificates()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ rv = createCertificateObjectIncomplete(hSession,IN_SESSION,IS_PUBLIC,hObject);
+ CPPUNIT_ASSERT(rv == CKR_TEMPLATE_INCOMPLETE);
+ rv = createCertificateObjectX509(hSession,IN_SESSION,IS_PUBLIC,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_BYTE pCheckValue[] = { 0x2b, 0x84, 0xf6 };
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CHECK_VALUE, pCheckValue, sizeof(pCheckValue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue(hSession, hObject, attribs, 1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+}
+
+void ObjectTests::testDefaultDataAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal data object
+ CK_OBJECT_CLASS objClass = CKO_DATA;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal data object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in data object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_TRUE, CK_TRUE, NULL_PTR, 0, CK_TRUE, CK_TRUE);
+ checkDataObjectAttributes(hSession, hObject, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0);
+}
+
+void ObjectTests::testDefaultX509CertAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal X509 certificate object
+ CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE certificateType = CKC_X_509;
+ CK_BYTE pSubject[] = "Test1";
+ CK_BYTE pValue[] = "Test2";
+ CK_BYTE pCheckValue[] = { 0x2b, 0x84, 0xf6 };
+ CK_DATE emptyDate;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_CERTIFICATE_TYPE, &certificateType, sizeof(certificateType) },
+ { CKA_SUBJECT, pSubject, sizeof(pSubject)-1 },
+ { CKA_VALUE, pValue, sizeof(pValue)-1 }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal X509 certificate
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in X509 certificate object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_FALSE, CK_TRUE, NULL_PTR, 0, CK_TRUE, CK_TRUE);
+ memset(&emptyDate, 0, sizeof(emptyDate));
+ checkCommonCertificateObjectAttributes(hSession, hObject, CKC_X_509, CK_FALSE, 0, pCheckValue, sizeof(pCheckValue), emptyDate, 0, emptyDate, 0);
+ checkX509CertificateObjectAttributes(hSession, hObject, pSubject, sizeof(pSubject)-1, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, pValue, sizeof(pValue)-1, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, 0, CKM_SHA_1);
+}
+
+void ObjectTests::testDefaultRSAPubAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal RSA public key object
+ CK_OBJECT_CLASS objClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE objType = CKK_RSA;
+ CK_BYTE pN[] = { 0xC6, 0x47, 0xDD, 0x74, 0x3B, 0xCB, 0xDC, 0x6F, 0xCE, 0xA7,
+ 0xF0, 0x5F, 0x29, 0x4B, 0x27, 0x00, 0xCC, 0x92, 0xE9, 0x20,
+ 0x8A, 0x2C, 0x87, 0x36, 0x47, 0x24, 0xB0, 0xD5, 0x7D, 0xB0,
+ 0x92, 0x01, 0xA0, 0xA3, 0x55, 0x2E, 0x3F, 0xFE, 0xA7, 0x4C,
+ 0x4B, 0x3F, 0x9D, 0x4E, 0xCB, 0x78, 0x12, 0xA9, 0x42, 0xAD,
+ 0x51, 0x1F, 0x3B, 0xBD, 0x3D, 0x6A, 0xE5, 0x38, 0xB7, 0x45,
+ 0x65, 0x50, 0x30, 0x35 };
+ CK_BYTE pE[] = { 0x01, 0x00, 0x01 };
+ CK_DATE emptyDate;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_KEY_TYPE, &objType, sizeof(objType) },
+ { CKA_MODULUS, pN, sizeof(pN) },
+ { CKA_PUBLIC_EXPONENT, pE, sizeof(pE) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal RSA public key object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in RSA public key object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_FALSE, CK_TRUE, NULL_PTR, 0, CK_TRUE, CK_TRUE);
+ memset(&emptyDate, 0, sizeof(emptyDate));
+ checkCommonKeyAttributes(hSession, hObject, objType, NULL_PTR, 0, emptyDate, 0, emptyDate, 0, CK_FALSE, CK_FALSE, CK_UNAVAILABLE_INFORMATION, NULL_PTR, 0);
+ checkCommonPublicKeyAttributes(hSession, hObject, NULL_PTR, 0, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_FALSE, NULL_PTR, 0);
+ checkCommonRSAPublicKeyAttributes(hSession, hObject, pN, sizeof(pN), 512, pE, sizeof(pE));
+}
+
+void ObjectTests::testDefaultRSAPrivAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal RSA private key object
+ CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE objType = CKK_RSA;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BYTE pN[] = { 0xC6, 0x47, 0xDD, 0x74, 0x3B, 0xCB, 0xDC, 0x6F, 0xCE, 0xA7,
+ 0xF0, 0x5F, 0x29, 0x4B, 0x27, 0x00, 0xCC, 0x92, 0xE9, 0x20,
+ 0x8A, 0x2C, 0x87, 0x36, 0x47, 0x24, 0xB0, 0xD5, 0x7D, 0xB0,
+ 0x92, 0x01, 0xA0, 0xA3, 0x55, 0x2E, 0x3F, 0xFE, 0xA7, 0x4C,
+ 0x4B, 0x3F, 0x9D, 0x4E, 0xCB, 0x78, 0x12, 0xA9, 0x42, 0xAD,
+ 0x51, 0x1F, 0x3B, 0xBD, 0x3D, 0x6A, 0xE5, 0x38, 0xB7, 0x45,
+ 0x65, 0x50, 0x30, 0x35 };
+ CK_BYTE pD[] = { 0x6D, 0x94, 0x6B, 0xEB, 0xFF, 0xDC, 0x03, 0x80, 0x7B, 0x0A,
+ 0x4F, 0x0A, 0x98, 0x6C, 0xA3, 0x2A, 0x8A, 0xE4, 0xAA, 0x18,
+ 0x44, 0xA4, 0xA5, 0x39, 0x37, 0x0A, 0x2C, 0xFC, 0x5F, 0xD1,
+ 0x44, 0x6E, 0xCE, 0x25, 0x9B, 0xE5, 0xD1, 0x51, 0xAF, 0xA8,
+ 0x30, 0xD1, 0x4D, 0x3C, 0x60, 0x33, 0xB5, 0xED, 0x4C, 0x39,
+ 0xDA, 0x68, 0x78, 0xF9, 0x6B, 0x4F, 0x47, 0x55, 0xB2, 0x02,
+ 0x00, 0x7E, 0x9C, 0x05 };
+ CK_DATE emptyDate;
+ // Make the key non-sensitive and extractable so that we can test it.
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_KEY_TYPE, &objType, sizeof(objType) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_MODULUS, pN, sizeof(pN) },
+ { CKA_PRIVATE_EXPONENT, pD, sizeof(pD) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal RSA public key object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in RSA public key object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_TRUE, CK_TRUE, NULL_PTR, 0, CK_TRUE, CK_TRUE);
+ memset(&emptyDate, 0, sizeof(emptyDate));
+ checkCommonKeyAttributes(hSession, hObject, objType, NULL_PTR, 0, emptyDate, 0, emptyDate, 0, CK_FALSE, CK_FALSE, CK_UNAVAILABLE_INFORMATION, NULL_PTR, 0);
+ checkCommonPrivateKeyAttributes(hSession, hObject, NULL_PTR, 0, CK_FALSE, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_FALSE, CK_FALSE, CK_FALSE, NULL_PTR, 0, CK_FALSE);
+ checkCommonRSAPrivateKeyAttributes(hSession, hObject, pN, sizeof(pN), NULL_PTR, 0, pD, sizeof(pD), NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0);
+}
+
+void ObjectTests::testAlwaysNeverAttribute()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BBOOL always;
+ CK_BBOOL never;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_ALWAYS_SENSITIVE, &always, sizeof(always) },
+ { CKA_NEVER_EXTRACTABLE, &never, sizeof(never) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create object
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, getTemplate, 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(always == CK_TRUE);
+ CPPUNIT_ASSERT(never == CK_TRUE);
+
+ // Set value
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue(hSession, hPrk, prkAttribs, 2) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+
+ // Create object
+ prkAttribs[0].pValue = &bFalse;
+ prkAttribs[1].pValue = &bTrue;
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, getTemplate, 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(always == CK_FALSE);
+ CPPUNIT_ASSERT(never == CK_FALSE);
+}
+
+void ObjectTests::testSensitiveAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BBOOL bSensitive = CK_TRUE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) }
+ };
+ // Sensitive attributes cannot be revealed in plaintext even if wrapping is allowed
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_SENSITIVE, &bSensitive, sizeof(bSensitive) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_PRIVATE_EXPONENT, NULL_PTR, 0 },
+ { CKA_PRIME_1, NULL_PTR, 0 },
+ { CKA_PRIME_2, NULL_PTR, 0 },
+ { CKA_EXPONENT_1, NULL_PTR, 0 },
+ { CKA_EXPONENT_2, NULL_PTR, 0 },
+ { CKA_COEFFICIENT, NULL_PTR, 0 }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create object
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ for (int i = 0; i < 6; i++)
+ {
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, &getTemplate[i], 1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_SENSITIVE);
+ }
+
+ // Retry with non-sensitive object
+ bSensitive = CK_FALSE;
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ for (int i = 0; i < 6; i++)
+ {
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, &getTemplate[i], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ }
+}
+
+void ObjectTests::testGetInvalidAttribute()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal data object
+ CK_OBJECT_CLASS objClass = CKO_DATA;
+ CK_BBOOL bSign;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_SIGN, &bSign, sizeof(bSign) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal data object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, 1, &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, getTemplate, 1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_TYPE_INVALID);
+}
+
+void ObjectTests::testReAuthentication()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1024;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_ALWAYS_AUTHENTICATE, &bTrue, sizeof(bTrue) }
+ };
+
+ CK_MECHANISM signMech = { CKM_SHA256_RSA_PKCS, NULL_PTR, 0 };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ CK_BYTE signature256[256];
+ CK_ULONG signature256Len = sizeof(signature256);
+
+ CK_MECHANISM encMech = { CKM_RSA_PKCS, NULL_PTR, 0 };
+ CK_BYTE cipherText[256];
+ CK_ULONG ulCipherTextLen = sizeof(cipherText);
+ CK_BYTE recoveredText[256];
+ CK_ULONG ulRecoveredTextLen = sizeof(recoveredText);
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create object
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 4, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Test C_Sign with re-authentication with invalid and valid PIN
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length-1) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Test C_Sign without re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ // Test C_SignUpdate with re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignUpdate(hSession, data, sizeof(data)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignFinal(hSession, signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Test C_SignUpdate without re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignUpdate(hSession, data, sizeof(data)) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+ rv = CRYPTOKI_F_PTR( C_SignUpdate(hSession, data, sizeof(data)) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ // Test C_SignFinal with re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignFinal(hSession, signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Test C_SignFinal without re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignFinal(hSession, signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+ rv = CRYPTOKI_F_PTR( C_SignFinal(hSession, signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ // Encrypt some data
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&encMech,hPuk) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,data,sizeof(data),cipherText,&ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Test C_Decrypt with re-authentication
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&encMech,hPrk) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ CPPUNIT_ASSERT(memcmp(data, &recoveredText[ulRecoveredTextLen-sizeof(data)], sizeof(data)) == 0);
+
+ // Test C_Decrypt without re-authentication
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&encMech,hPrk) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+}
+
+void ObjectTests::testAllowedMechanisms()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
+ CK_BYTE key[65] = { "0000000000000000000000000000000000000000000000000000000000000000" };
+ CK_MECHANISM_TYPE allowedMechs[] = { CKM_SHA256_HMAC, CKM_SHA512_HMAC };
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_VALUE, &key, sizeof(key)-1 },
+ { CKA_ALLOWED_MECHANISMS, &allowedMechs, sizeof(allowedMechs) }
+ };
+
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+
+ // SHA_1_HMAC is not an allowed mechanism
+ CK_MECHANISM mechanism = { CKM_SHA_1_HMAC, NULL_PTR, 0 };
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ // SHA256_HMAC is an allowed mechanism
+ mechanism.mechanism = CKM_SHA256_HMAC;
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_BYTE signature256[256];
+ CK_ULONG signature256Len = sizeof(signature256);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // SHA384_HMAC is not an allowed mechanism
+ mechanism.mechanism = CKM_SHA384_HMAC;
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ // SHA512_HMAC is an allowed mechanism
+ mechanism.mechanism = CKM_SHA512_HMAC;
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_BYTE signature512[512];
+ CK_ULONG signature512Len = sizeof(signature512);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature512, &signature512Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testTemplateAttribute()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+ CK_BYTE pE[] = { 0x01, 0x00, 0x01 };
+ CK_MECHANISM_TYPE allowedMechs[] = { CKM_SHA256_HMAC, CKM_SHA512_HMAC };
+
+ // Wrap template
+ CK_KEY_TYPE wrapType = CKK_SHA256_HMAC;;
+ CK_ATTRIBUTE wrapTemplate[] = {
+ { CKA_KEY_TYPE, &wrapType, sizeof(wrapType) },
+ { CKA_PUBLIC_EXPONENT, pE, sizeof(pE) },
+ { CKA_ALLOWED_MECHANISMS, &allowedMechs, sizeof(allowedMechs) }
+ };
+
+ // Minimal public key object
+ CK_OBJECT_CLASS objClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE objType = CKK_RSA;
+ CK_BYTE pN[] = { 0xC6, 0x47, 0xDD, 0x74, 0x3B, 0xCB, 0xDC, 0x6F, 0xCE, 0xA7,
+ 0xF0, 0x5F, 0x29, 0x4B, 0x27, 0x00, 0xCC, 0x92, 0xE9, 0x20,
+ 0x8A, 0x2C, 0x87, 0x36, 0x47, 0x24, 0xB0, 0xD5, 0x7D, 0xB0,
+ 0x92, 0x01, 0xA0, 0xA3, 0x55, 0x2E, 0x3F, 0xFE, 0xA7, 0x4C,
+ 0x4B, 0x3F, 0x9D, 0x4E, 0xCB, 0x78, 0x12, 0xA9, 0x42, 0xAD,
+ 0x51, 0x1F, 0x3B, 0xBD, 0x3D, 0x6A, 0xE5, 0x38, 0xB7, 0x45,
+ 0x65, 0x50, 0x30, 0x35 };
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_KEY_TYPE, &objType, sizeof(objType) },
+ { CKA_MODULUS, pN, sizeof(pN) },
+ { CKA_PUBLIC_EXPONENT, pE, sizeof(pE) },
+ { CKA_WRAP_TEMPLATE, wrapTemplate, sizeof(wrapTemplate) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal RSA public key object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_ATTRIBUTE wrapAttribs[] = {
+ { 0, NULL_PTR, 0 },
+ { 0, NULL_PTR, 0 },
+ { 0, NULL_PTR, 0 }
+ };
+ CK_ATTRIBUTE wrapAttrib = { CKA_WRAP_TEMPLATE, NULL_PTR, 0 };
+
+ // Get number of elements
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &wrapAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(wrapAttrib.ulValueLen == 3 * sizeof(CK_ATTRIBUTE));
+
+ // Get element types and sizes
+ wrapAttrib.pValue = wrapAttribs;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &wrapAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(wrapAttrib.ulValueLen == 3 * sizeof(CK_ATTRIBUTE));
+ for (size_t i = 0; i < 3; i++)
+ {
+ switch (wrapAttribs[i].type)
+ {
+ case CKA_KEY_TYPE:
+ CPPUNIT_ASSERT(wrapAttribs[i].ulValueLen == sizeof(CK_KEY_TYPE));
+ break;
+ case CKA_PUBLIC_EXPONENT:
+ CPPUNIT_ASSERT(wrapAttribs[i].ulValueLen == sizeof(pE));
+ break;
+ case CKA_ALLOWED_MECHANISMS:
+ CPPUNIT_ASSERT(wrapAttribs[i].ulValueLen == sizeof(allowedMechs));
+ break;
+ default:
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ // Get values
+ wrapAttribs[0].pValue = (CK_VOID_PTR)malloc(wrapAttribs[0].ulValueLen);
+ wrapAttribs[1].pValue = (CK_VOID_PTR)malloc(wrapAttribs[1].ulValueLen);
+ wrapAttribs[2].pValue = (CK_VOID_PTR)malloc(wrapAttribs[2].ulValueLen);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &wrapAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ for (size_t i = 0; i < 3; i++)
+ {
+ switch (wrapAttribs[i].type)
+ {
+ case CKA_KEY_TYPE:
+ CPPUNIT_ASSERT(*(CK_KEY_TYPE*) wrapAttribs[i].pValue == CKK_SHA256_HMAC);
+ break;
+ case CKA_PUBLIC_EXPONENT:
+ CPPUNIT_ASSERT(memcmp(wrapAttribs[i].pValue, pE, sizeof(pE)) == 0);
+ break;
+ case CKA_ALLOWED_MECHANISMS:
+ CPPUNIT_ASSERT(memcmp(wrapAttribs[i].pValue, allowedMechs, sizeof(allowedMechs)) == 0);
+ break;
+ default:
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ free(wrapAttribs[0].pValue);
+ free(wrapAttribs[1].pValue);
+ free(wrapAttribs[2].pValue);
+}
+
+void ObjectTests::testCreateSecretKey()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_BYTE genericKey[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
+ };
+ CK_BYTE aesKey[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
+ };
+ CK_BYTE desKey[] = {
+ 0x81, 0xdc, 0x9b, 0xdb, 0x52, 0xd0, 0x4d, 0xc2
+ };
+ CK_BYTE des2Key[] = {
+ 0x81, 0xdc, 0x9b, 0xdb, 0x52, 0xd0, 0x4d, 0xc2, 0x00, 0x36,
+ 0xdb, 0xd8, 0x31, 0x3e, 0xd0, 0x55
+ };
+ CK_BYTE des3Key[] = {
+ 0x81, 0xdc, 0x9b, 0xdb, 0x52, 0xd0, 0x4d, 0xc2, 0x00, 0x36,
+ 0xdb, 0xd8, 0x31, 0x3e, 0xd0, 0x55, 0xcc, 0x57, 0x76, 0xd1,
+ 0x6a, 0x1f, 0xb6, 0xe4
+ };
+ CK_BYTE genericKCV[] = { 0x5c, 0x3b, 0x7c };
+ CK_BYTE aesKCV[] = { 0x08, 0xbd, 0x28 };
+ CK_BYTE desKCV[] = { 0x08, 0xa1, 0x50 };
+ CK_BYTE des2KCV[] = { 0xa9, 0x67, 0xae };
+ CK_BYTE des3KCV[] = { 0x5c, 0x5e, 0xec };
+
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_VALUE, genericKey, sizeof(genericKey) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) },
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ CK_BYTE pCheckValue[3];
+ CK_ATTRIBUTE attribKCV[] = {
+ { CKA_CHECK_VALUE, pCheckValue, sizeof(pCheckValue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, genericKCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ keyType = CKK_AES;
+ attribs[0].pValue = aesKey;
+ attribs[0].ulValueLen = sizeof(aesKey);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, aesKCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ keyType = CKK_DES;
+ attribs[0].pValue = desKey;
+ attribs[0].ulValueLen = sizeof(desKey);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, desKCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ keyType = CKK_DES2;
+ attribs[0].pValue = des2Key;
+ attribs[0].ulValueLen = sizeof(des2Key);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, des2KCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ keyType = CKK_DES3;
+ attribs[0].pValue = des3Key;
+ attribs[0].ulValueLen = sizeof(des3Key);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, des3KCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
diff --git a/SoftHSMv2/src/lib/test/ObjectTests.h b/SoftHSMv2/src/lib/test/ObjectTests.h
new file mode 100644
index 0000000..b15ae48
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/ObjectTests.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectTests.h
+
+ Contains test cases to C_CreateObject, C_CopyObject, C_DestroyObject,
+ C_GetAttributeValue, C_SetAttributeValue, C_FindObjectsInit,
+ C_FindObjects, C_FindObjectsFinal, C_GenerateKeyPair
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTTESTS_H
+#define _SOFTHSM_V2_OBJECTTESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class ObjectTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(ObjectTests);
+ CPPUNIT_TEST(testCreateObject);
+ CPPUNIT_TEST(testCopyObject);
+ CPPUNIT_TEST(testDestroyObject);
+ CPPUNIT_TEST(testGetObjectSize);
+ CPPUNIT_TEST(testGetAttributeValue);
+ CPPUNIT_TEST(testSetAttributeValue);
+ CPPUNIT_TEST(testFindObjects);
+ CPPUNIT_TEST(testGenerateKeys);
+ CPPUNIT_TEST(testCreateCertificates);
+ CPPUNIT_TEST(testDefaultDataAttributes);
+ CPPUNIT_TEST(testDefaultX509CertAttributes);
+ CPPUNIT_TEST(testDefaultRSAPubAttributes);
+ CPPUNIT_TEST(testDefaultRSAPrivAttributes);
+ CPPUNIT_TEST(testAlwaysNeverAttribute);
+ CPPUNIT_TEST(testSensitiveAttributes);
+ CPPUNIT_TEST(testGetInvalidAttribute);
+ CPPUNIT_TEST(testAllowedMechanisms);
+ CPPUNIT_TEST(testReAuthentication);
+ CPPUNIT_TEST(testTemplateAttribute);
+ CPPUNIT_TEST(testCreateSecretKey);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testCreateObject();
+ void testCopyObject();
+ void testDestroyObject();
+ void testGetObjectSize();
+ void testGetAttributeValue();
+ void testSetAttributeValue();
+ void testFindObjects();
+ void testGenerateKeys();
+ void testCreateCertificates();
+ void testDefaultDataAttributes();
+ void testDefaultX509CertAttributes();
+ void testDefaultRSAPubAttributes();
+ void testDefaultRSAPrivAttributes();
+ void testAlwaysNeverAttribute();
+ void testSensitiveAttributes();
+ void testGetInvalidAttribute();
+ void testReAuthentication();
+ void testAllowedMechanisms();
+ void testTemplateAttribute();
+ void testCreateSecretKey();
+
+protected:
+ void checkCommonObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_OBJECT_CLASS objectClass
+ );
+ void checkCommonStorageObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BBOOL bToken,
+ CK_BBOOL bPrivate,
+ CK_BBOOL bModifiable,
+ CK_UTF8CHAR_PTR pLabel, CK_ULONG ulLabelLen,
+ CK_BBOOL bCopyable,
+ CK_BBOOL bDestroyable
+ );
+ void checkDataObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_UTF8CHAR_PTR pApplication, CK_ULONG ulApplicationLen,
+ CK_BYTE_PTR pObjectID, CK_ULONG ulObjectIdLen,
+ CK_BYTE_PTR pValue, CK_ULONG ulValueLen
+ );
+ void checkCommonCertificateObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_CERTIFICATE_TYPE certType,
+ CK_BBOOL bTrusted,
+ CK_ULONG ulCertificateCategory,
+ CK_BYTE_PTR pCheckValue, CK_ULONG ulCheckValueLen,
+ CK_DATE startDate, CK_ULONG ulStartDateLen,
+ CK_DATE endDate, CK_ULONG ulEndDateLen
+ );
+ void checkX509CertificateObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BYTE_PTR pId, CK_ULONG ulIdLen,
+ CK_BYTE_PTR pIssuer, CK_ULONG ulIssuerLen,
+ CK_BYTE_PTR pSerialNumber, CK_ULONG ulSerialNumberLen,
+ CK_BYTE_PTR pValue, CK_ULONG ulValueLen,
+ CK_BYTE_PTR pUrl, CK_ULONG ulUrlLen,
+ CK_BYTE_PTR pHashOfSubjectPublicKey, CK_ULONG ulHashOfSubjectPublicKeyLen,
+ CK_BYTE_PTR pHashOfIssuerPublicKey, CK_ULONG ulHashOfIssuerPublicKeyLen,
+ CK_ULONG ulJavaMidpSecurityDomain,
+ CK_MECHANISM_TYPE nameHashAlgorithm
+ );
+ void checkCommonKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_KEY_TYPE keyType,
+ CK_BYTE_PTR pId, CK_ULONG ulIdLen,
+ CK_DATE startDate, CK_ULONG ulStartDateLen,
+ CK_DATE endDate, CK_ULONG ulEndDateLen,
+ CK_BBOOL bDerive,
+ CK_BBOOL bLocal,
+ CK_MECHANISM_TYPE keyMechanismType,
+ CK_MECHANISM_TYPE_PTR pAllowedMechanisms, CK_ULONG ulAllowedMechanismsLen /* len = count * sizeof(CK_MECHANISM_TYPE) */
+ );
+ void checkCommonPublicKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BBOOL bEncrypt,
+ CK_BBOOL bVerify,
+ CK_BBOOL bVerifyRecover,
+ CK_BBOOL bWrap,
+ CK_BBOOL bTrusted,
+ CK_ATTRIBUTE_PTR pWrapTemplate, CK_ULONG ulWrapTemplateLen /* len = count * sizeof(CK_ATTRIBUTE) */
+ );
+ void checkCommonPrivateKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BBOOL bSensitive,
+ CK_BBOOL bDecrypt,
+ CK_BBOOL bSign,
+ CK_BBOOL bSignRecover,
+ CK_BBOOL bUnwrap,
+ CK_BBOOL bExtractable,
+ CK_BBOOL bAlwaysSensitive,
+ CK_BBOOL bNeverExtractable,
+ CK_BBOOL bWrapWithTrusted,
+ CK_ATTRIBUTE_PTR pUnwrapTemplate, CK_ULONG ulUnwrapTemplateLen, /* len = count * sizeof(CK_ATTRIBUTE) */
+ CK_BBOOL bAlwaysAuthenticate
+ );
+ void checkCommonRSAPublicKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen,
+ CK_ULONG ulModulusBits,
+ CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen
+ );
+ void checkCommonRSAPrivateKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen,
+ CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen,
+ CK_BYTE_PTR pPrivateExponent, CK_ULONG ulPrivateExponentLen,
+ CK_BYTE_PTR pPrime1, CK_ULONG ulPrime1Len,
+ CK_BYTE_PTR pPrime2, CK_ULONG ulPrime2Len,
+ CK_BYTE_PTR pExponent1, CK_ULONG ulExponent1Len,
+ CK_BYTE_PTR pExponent2, CK_ULONG ulExponent2Len,
+ CK_BYTE_PTR pCoefficient, CK_ULONG ulCoefficientLen
+ );
+
+ CK_RV createDataObjectMinimal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+ CK_RV createDataObjectMCD(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_BBOOL bModifiable, CK_BBOOL bCopyable, CK_BBOOL bDestroyable, CK_OBJECT_HANDLE &hObject);
+ CK_RV createDataObjectNormal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+
+ CK_RV createCertificateObjectIncomplete(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+ CK_RV createCertificateObjectX509(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+};
+
+#endif // !_SOFTHSM_V2_OBJECTTESTS_H
diff --git a/SoftHSMv2/src/lib/test/README b/SoftHSMv2/src/lib/test/README
new file mode 100644
index 0000000..d9e6cce
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/README
@@ -0,0 +1,17 @@
+To build for test of SoftHSM with static linking:
+make p11test
+
+To build for testing another p11 module provided as shared library:
+make p11test_DEPENDENCIES= p11test_LDADD= CPPFLAGS=-DP11M=\\\"./p11m.so\\\" p11test
+Substitute ./p11m.so with the path to your shared library.
+Note that nothing else of SoftHSMv2 has to be built in order to build the test of an external p11.
+
+To run the test with first a test summary and then specific output of each failure:
+./p11test
+
+To get output of each test after it is executed:
+./p11test direct
+
+To run a specific test:
+./p11test ObjectTests::testArrayAttribute
+Substitute 'ObjectTests::testArrayAttribute' with the test you want to run.
diff --git a/SoftHSMv2/src/lib/test/RandomTests.cpp b/SoftHSMv2/src/lib/test/RandomTests.cpp
new file mode 100644
index 0000000..8fe25bc
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/RandomTests.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RandomTests.cpp
+
+ Contains test cases to C_SeedRandom and C_GenerateRandom
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "RandomTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RandomTests);
+
+void RandomTests::testSeedRandom()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_BYTE seed[] = {"Some random data"};
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_SeedRandom(CK_INVALID_HANDLE, seed, sizeof(seed)) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SeedRandom(hSession, NULL_PTR, sizeof(seed)) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_SeedRandom(hSession, seed, sizeof(seed)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SeedRandom(hSession, seed, sizeof(seed)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void RandomTests::testGenerateRandom()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_BYTE randomData[40];
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(CK_INVALID_HANDLE, randomData, 40) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, NULL_PTR, 40) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, randomData, 40) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, randomData, 40) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/SoftHSMv2/src/lib/test/RandomTests.h b/SoftHSMv2/src/lib/test/RandomTests.h
new file mode 100644
index 0000000..4b7b062
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/RandomTests.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RandomTests.h
+
+ Contains test cases to C_SeedRandom and C_GenerateRandom
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RANDOMTESTS_H
+#define _SOFTHSM_V2_RANDOMTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class RandomTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(RandomTests);
+ CPPUNIT_TEST(testSeedRandom);
+ CPPUNIT_TEST(testGenerateRandom);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testSeedRandom();
+ void testGenerateRandom();
+};
+
+#endif // !_SOFTHSM_V2_RANDOMTESTS_H
diff --git a/SoftHSMv2/src/lib/test/SessionTests.cpp b/SoftHSMv2/src/lib/test/SessionTests.cpp
new file mode 100644
index 0000000..756106a
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SessionTests.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionTests.cpp
+
+ Contains test cases to C_OpenSession, C_CloseSession, C_CloseAllSessions, and
+ C_GetSessionInfo
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "SessionTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionTests);
+
+void SessionTests::testOpenSession()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_invalidSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_notInitializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_TOKEN_NOT_RECOGNIZED);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, 0, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_PARALLEL_NOT_SUPPORTED);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SessionTests::testCloseSession()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession + 1) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
+
+void SessionTests::testCloseAllSessions()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_SESSION_INFO info;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_CloseAllSessions(m_initializedTokenSlotID) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseAllSessions(m_invalidSlotID) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_CloseAllSessions(m_notInitializedTokenSlotID) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, &info) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseAllSessions(m_initializedTokenSlotID) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
+
+void SessionTests::testGetSessionInfo()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_SESSION_INFO info;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, &info) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(CK_INVALID_HANDLE, &info) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession + 1, &info) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, &info) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT(info.state == CKS_RO_PUBLIC_SESSION);
+ CPPUNIT_ASSERT(info.flags == CKF_SERIAL_SESSION);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, &info) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
diff --git a/SoftHSMv2/src/lib/test/SessionTests.h b/SoftHSMv2/src/lib/test/SessionTests.h
new file mode 100644
index 0000000..c940ab0
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SessionTests.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionTests.h
+
+ Contains test cases to C_OpenSession, C_CloseSession, C_CloseAllSessions, and
+ C_GetSessionInfo
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONTESTS_H
+#define _SOFTHSM_V2_SESSIONTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(SessionTests);
+ CPPUNIT_TEST(testOpenSession);
+ CPPUNIT_TEST(testCloseSession);
+ CPPUNIT_TEST(testCloseAllSessions);
+ CPPUNIT_TEST(testGetSessionInfo);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testOpenSession();
+ void testCloseSession();
+ void testCloseAllSessions();
+ void testGetSessionInfo();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/SignVerifyTests.cpp b/SoftHSMv2/src/lib/test/SignVerifyTests.cpp
new file mode 100644
index 0000000..06dbf95
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SignVerifyTests.cpp
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SignVerifyTests.cpp
+
+ Contains test cases for:
+ C_SignInit
+ C_Sign
+ C_SignUpdate
+ C_SignFinal
+ C_VerifyInit
+ C_Verify
+ C_VerifyUpdate
+ C_VerifyFinal
+
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "SignVerifyTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SignVerifyTests);
+
+CK_RV SignVerifyTests::generateRSA(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE label[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_LABEL, &label[0], sizeof(label) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_LABEL, &label[0], sizeof(label) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+#ifdef WITH_ECC
+CK_RV SignVerifyTests::generateEC(const char* curve, CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_KEY_TYPE keyType = CKK_EC;
+ CK_BYTE oidP256[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 };
+ CK_BYTE oidP384[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 };
+ CK_BYTE oidP521[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23 };
+ CK_BYTE label[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_EC_PARAMS, NULL, 0 },
+ { CKA_LABEL, &label[0], sizeof(label) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_LABEL, &label[0], sizeof(label) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }
+ };
+
+ /* Select the curve */
+ if (strcmp(curve, "P-256") == 0)
+ {
+ pukAttribs[0].pValue = oidP256;
+ pukAttribs[0].ulValueLen = sizeof(oidP256);
+ }
+ else if (strcmp(curve, "P-384") == 0)
+ {
+ pukAttribs[0].pValue = oidP384;
+ pukAttribs[0].ulValueLen = sizeof(oidP384);
+ }
+ else if (strcmp(curve, "P-521") == 0)
+ {
+ pukAttribs[0].pValue = oidP521;
+ pukAttribs[0].ulValueLen = sizeof(oidP521);
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+#endif
+
+void SignVerifyTests::signVerifySingle(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param /* = NULL_PTR */, CK_ULONG paramLen /* = 0 */)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, param, paramLen };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE signature[256];
+ CK_ULONG ulSignatureLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession,&mechanism,hPrivateKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession,data,sizeof(data),signature,&ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Verify(hSession,data,sizeof(data),signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = CRYPTOKI_F_PTR( C_Verify(hSession,data,sizeof(data),signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+}
+
+void SignVerifyTests::signVerifySingleData(size_t dataSize, CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param /* = NULL_PTR */, CK_ULONG paramLen /* = 0 */)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, param, paramLen };
+ CK_BYTE *data = (CK_BYTE*)malloc(dataSize);
+ CK_BYTE signature[1024];
+ CK_ULONG ulSignatureLen = 0;
+ unsigned i;
+
+ CPPUNIT_ASSERT(data != NULL);
+
+ for (i=0;i<dataSize;i++)
+ data[i] = i;
+
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession,&mechanism,hPrivateKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession,data,dataSize,signature,&ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Verify(hSession,data,dataSize,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = CRYPTOKI_F_PTR( C_Verify(hSession,data,dataSize,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+
+ free(data);
+}
+
+void SignVerifyTests::signVerifyMulti(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param /* = NULL_PTR */, CK_ULONG paramLen /* = 0 */)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, param, paramLen };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE signature[256];
+ CK_ULONG ulSignatureLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession,&mechanism,hPrivateKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv =CRYPTOKI_F_PTR( C_SignUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv =CRYPTOKI_F_PTR( C_SignFinal(hSession,signature,&ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyFinal(hSession,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = CRYPTOKI_F_PTR( C_VerifyUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyFinal(hSession,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+}
+
+void SignVerifyTests::testRsaSignVerify()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_RSA_PKCS_PSS_PARAMS params[] = {
+ { CKM_SHA_1, CKG_MGF1_SHA1, 0 },
+ { CKM_SHA224, CKG_MGF1_SHA224, 28 },
+ { CKM_SHA256, CKG_MGF1_SHA256, 32 },
+ { CKM_SHA384, CKG_MGF1_SHA384, 0 },
+ { CKM_SHA512, CKG_MGF1_SHA512, 0 }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ // Public Session keys
+ rv = generateRSA(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ signVerifySingle(CKM_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifySingle(CKM_RSA_X_509, hSessionRO, hPuk,hPrk);
+#ifndef WITH_FIPS
+ signVerifyMulti(CKM_MD5_RSA_PKCS, hSessionRO, hPuk,hPrk);
+#endif
+ signVerifyMulti(CKM_SHA1_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA224_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA256_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA384_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA512_RSA_PKCS, hSessionRO, hPuk,hPrk);
+
+#ifdef WITH_RAW_PSS
+ signVerifySingleData(20, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifySingleData(28, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifySingleData(32, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifySingleData(48, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifySingleData(64, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[4], sizeof(params[4]));
+#endif
+
+ signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[4], sizeof(params[4]));
+
+ // Private Session Keys
+ rv = generateRSA(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ signVerifySingle(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifySingle(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+#ifndef WITH_FIPS
+ signVerifyMulti(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+#endif
+ signVerifyMulti(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA224_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[4], sizeof(params[4]));
+
+ // Public Token Keys
+ rv = generateRSA(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ signVerifySingle(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifySingle(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+#ifndef WITH_FIPS
+ signVerifyMulti(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+#endif
+ signVerifyMulti(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA224_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[4], sizeof(params[4]));
+
+ // Private Token Keys
+ rv = generateRSA(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ signVerifySingle(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifySingle(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+#ifndef WITH_FIPS
+ signVerifyMulti(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+#endif
+ signVerifyMulti(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA224_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[4], sizeof(params[4]));
+}
+
+#ifdef WITH_ECC
+void SignVerifyTests::testEcSignVerify()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ // Public Session keys
+ rv = generateEC("P-256", hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-384", hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-521", hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+
+ // Private Session Keys
+ rv = generateEC("P-256", hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-384", hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-521", hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+
+ // Public Token Keys
+ rv = generateEC("P-256", hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-384", hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-521", hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+
+ // Private Token Keys
+ rv = generateEC("P-256", hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-384", hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-521", hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+}
+#endif
+
+CK_RV SignVerifyTests::generateKey(CK_SESSION_HANDLE hSession, CK_KEY_TYPE keyType, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+#ifndef WITH_BOTAN
+#define GEN_KEY_LEN 75
+#else
+#define GEN_KEY_LEN 64
+#endif
+ CK_RV rv;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_BYTE val[GEN_KEY_LEN];
+ //CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BYTE oid[] = { 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x1F, 0x00 };
+ CK_ATTRIBUTE kAttribs[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE, val, sizeof(val) },
+ { CKA_GOST28147_PARAMS, oid, sizeof(oid) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, val, GEN_KEY_LEN) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ hKey = CK_INVALID_HANDLE;
+ if (keyType == CKK_GOST28147)
+ {
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, kAttribs, 9, &hKey) );
+ }
+ else
+ {
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, kAttribs, 8, &hKey) );
+ }
+}
+
+CK_RV SignVerifyTests::generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES2_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV SignVerifyTests::generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV SignVerifyTests::generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_ULONG bytes = 16;
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+void SignVerifyTests::macSignVerify(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE signature[256];
+ CK_ULONG ulSignatureLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv =CRYPTOKI_F_PTR( C_SignUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv =CRYPTOKI_F_PTR( C_SignFinal(hSession,signature,&ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyFinal(hSession,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = CRYPTOKI_F_PTR( C_VerifyUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyFinal(hSession,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+}
+
+void SignVerifyTests::testMacSignVerify()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Public Session keys
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+#ifndef WITH_FIPS
+ rv = generateKey(hSessionRW,CKK_MD5_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_MD5_HMAC, hSessionRO, hKey);
+#endif
+
+ rv = generateKey(hSessionRW,CKK_SHA_1_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA_1_HMAC, hSessionRO, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA224_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA224_HMAC, hSessionRO, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA256_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA256_HMAC, hSessionRO, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA384_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA384_HMAC, hSessionRO, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA512_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA512_HMAC, hSessionRO, hKey);
+
+#ifdef WITH_GOST
+ rv = generateKey(hSessionRW,CKK_GOST28147,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_GOSTR3411_HMAC, hSessionRO, hKey);
+#endif
+
+ rv = generateDes2Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateDes3Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateAesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
+
+ // Private Session Keys
+#ifndef WITH_FIPS
+ rv = generateKey(hSessionRW,CKK_MD5_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_MD5_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateKey(hSessionRW,CKK_SHA_1_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA_1_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA224_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA224_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA256_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA256_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA384_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA384_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA512_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA512_HMAC, hSessionRW, hKey);
+
+#ifdef WITH_GOST
+ rv = generateKey(hSessionRW,CKK_GOST28147,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_GOSTR3411_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateDes2Key(hSessionRW,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateDes3Key(hSessionRW,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateAesKey(hSessionRW,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
+
+ // Public Token Keys
+#ifndef WITH_FIPS
+ rv = generateKey(hSessionRW,CKK_MD5_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_MD5_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateKey(hSessionRW,CKK_SHA_1_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA_1_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA224_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA224_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA256_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA256_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA384_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA384_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA512_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA512_HMAC, hSessionRW, hKey);
+
+#ifdef WITH_GOST
+ rv = generateKey(hSessionRW,CKK_GOST28147,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_GOSTR3411_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateDes2Key(hSessionRW,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateDes3Key(hSessionRW,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateAesKey(hSessionRW,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
+
+ // Private Token Keys
+#ifndef WITH_FIPS
+ rv = generateKey(hSessionRW,CKK_MD5_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_MD5_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateKey(hSessionRW,CKK_SHA_1_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA_1_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA224_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA224_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA256_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA256_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA384_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA384_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA512_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA512_HMAC, hSessionRW, hKey);
+
+#ifdef WITH_GOST
+ rv = generateKey(hSessionRW,CKK_GOST28147,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_GOSTR3411_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateDes2Key(hSessionRW,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateDes3Key(hSessionRW,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateAesKey(hSessionRW,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
+}
+
diff --git a/SoftHSMv2/src/lib/test/SignVerifyTests.h b/SoftHSMv2/src/lib/test/SignVerifyTests.h
new file mode 100644
index 0000000..a251218
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SignVerifyTests.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SignVerifyTests.h
+
+ Contains test cases to C_SignInit,C_Sign,C_SignUpdate,C_SignFinal,
+ C_VerifyInit, C_Verify, C_VerifyUpdate, C_VerifyFinal
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SIGNVERIFYTESTS_H
+#define _SOFTHSM_V2_SIGNVERIFYTESTS_H
+
+#include "config.h"
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class SignVerifyTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(SignVerifyTests);
+ CPPUNIT_TEST(testRsaSignVerify);
+#ifdef WITH_ECC
+ CPPUNIT_TEST(testEcSignVerify);
+#endif
+ CPPUNIT_TEST(testMacSignVerify);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRsaSignVerify();
+#ifdef WITH_ECC
+ void testEcSignVerify();
+#endif
+ void testMacSignVerify();
+
+protected:
+ CK_RV generateRSA(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+#ifdef WITH_ECC
+ CK_RV generateEC(const char* curve, CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+#endif
+ void signVerifySingle(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param = NULL_PTR, CK_ULONG paramLen = 0);
+ void signVerifySingleData(size_t dataSize, CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param = NULL_PTR, CK_ULONG paramLen = 0);
+ void signVerifyMulti(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param = NULL_PTR, CK_ULONG paramLen = 0);
+ CK_RV generateKey(CK_SESSION_HANDLE hSession, CK_KEY_TYPE keyType, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ void macSignVerify(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey);
+};
+
+#endif // !_SOFTHSM_V2_SIGNVERIFYTESTS_H
diff --git a/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.cpp b/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.cpp
new file mode 100644
index 0000000..f301c73
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.cpp
@@ -0,0 +1,998 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricAlgorithmTests.cpp
+
+ Contains test cases for symmetrical algorithms (i.e., AES and DES)
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <climits>
+//#include <iomanip>
+#include "SymmetricAlgorithmTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+#define NR_OF_BLOCKS_IN_TEST 0x10001
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SymmetricAlgorithmTests);
+
+CK_RV SymmetricAlgorithmTests::generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_ULONG bytes = 16;
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+#ifndef WITH_FIPS
+CK_RV SymmetricAlgorithmTests::generateDesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV SymmetricAlgorithmTests::generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES2_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+#endif
+
+CK_RV SymmetricAlgorithmTests::generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+void SymmetricAlgorithmTests::encryptDecrypt(
+ const CK_MECHANISM_TYPE mechanismType,
+ const size_t blockSize,
+ const CK_SESSION_HANDLE hSession,
+ const CK_OBJECT_HANDLE hKey,
+ const size_t messageSize,
+ const bool isSizeOK)
+{
+ class PartSize {// class to get random size for part
+ private: // we want to know for sure that no part length is causing any problem.
+ const int blockSize;
+ const unsigned* pRandom;// point to memory with random data. We are using the data to be encrypted.
+ const unsigned* pBack;// point to memory where random data ends.
+ int current;// the current size.
+ public:
+ PartSize(
+ const int _blockSize,
+ const std::vector<CK_BYTE>* pvData) :
+ blockSize(_blockSize),
+ pRandom((const unsigned*)&pvData->front()),
+ pBack((const unsigned*)&pvData->back()),
+ current(blockSize*4){};
+ int getCurrent() {// current part size
+ return current;
+ }
+ int getNext() {// get next part size.
+ // Check if we do not have more random data
+ if ((pRandom+sizeof(unsigned)-1) > pBack) {
+ current = blockSize*4;
+ return current;
+ }
+ const unsigned random(*(pRandom++));
+ // Bit shift to handle 32- and 64-bit systems.
+ // Just want a simple random part length,
+ // not a perfect random number (bit shifting will
+ // give some loss of precision).
+ current = ((unsigned long)random >> 20)*blockSize*0x100/(UINT_MAX >> 20) + 1;
+ //std::cout << "New random " << std::hex << random << " current " << std::hex << std::setfill('0') << std::setw(4) << current << " block size " << std::hex << blockSize << std::endl;
+ return current;
+ }
+ };
+
+ const std::vector<CK_BYTE> vData(messageSize);
+ std::vector<CK_BYTE> vEncryptedData;
+ std::vector<CK_BYTE> vEncryptedDataParted;
+ PartSize partSize(blockSize, &vData);
+
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_GenerateRandom(hSession, (CK_BYTE_PTR)&vData.front(), messageSize) ) );
+
+ const CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_MECHANISM_PTR pMechanism((CK_MECHANISM_PTR)&mechanism);
+ CK_AES_CTR_PARAMS ctrParams =
+ {
+ 32,
+ {
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+ }
+ };
+ CK_BYTE gcmIV[] = {
+ 0xCA, 0xFE, 0xBA, 0xBE, 0xFA, 0xCE,
+ 0xDB, 0xAD, 0xDE, 0xCA, 0xF8, 0x88
+ };
+ CK_BYTE gcmAAD[] = {
+ 0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF,
+ 0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF,
+ 0xAB, 0xAD, 0xDA, 0xD2
+ };
+ CK_GCM_PARAMS gcmParams =
+ {
+ &gcmIV[0],
+ sizeof(gcmIV),
+ sizeof(gcmIV)*8,
+ &gcmAAD[0],
+ sizeof(gcmAAD),
+ 16*8
+ };
+
+ switch (mechanismType)
+ {
+ case CKM_DES_CBC:
+ case CKM_DES_CBC_PAD:
+ case CKM_DES3_CBC:
+ case CKM_DES3_CBC_PAD:
+ case CKM_AES_CBC:
+ case CKM_AES_CBC_PAD:
+ pMechanism->pParameter = (CK_VOID_PTR)&vData.front();
+ pMechanism->ulParameterLen = blockSize;
+ break;
+ case CKM_AES_CTR:
+ pMechanism->pParameter = &ctrParams;
+ pMechanism->ulParameterLen = sizeof(ctrParams);
+ break;
+ case CKM_AES_GCM:
+ pMechanism->pParameter = &gcmParams;
+ pMechanism->ulParameterLen = sizeof(gcmParams);
+ break;
+ default:
+ break;
+ }
+
+ // Single-part encryption
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptInit(hSession,pMechanism,hKey) ) );
+ {
+ CK_ULONG ulEncryptedDataLen;
+ const CK_RV rv( CRYPTOKI_F_PTR( C_Encrypt(hSession,(CK_BYTE_PTR)&vData.front(),messageSize,NULL_PTR,&ulEncryptedDataLen) ) );
+ if ( isSizeOK ) {
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedData.resize(ulEncryptedDataLen);
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Encrypt(hSession,(CK_BYTE_PTR)&vData.front(),messageSize,&vEncryptedData.front(),&ulEncryptedDataLen) ) );
+ vEncryptedData.resize(ulEncryptedDataLen);
+ } else {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("C_Encrypt should fail with C_CKR_DATA_LEN_RANGE", (CK_RV)CKR_DATA_LEN_RANGE, rv);
+ vEncryptedData = vData;
+ }
+ }
+
+ // Multi-part encryption
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptInit(hSession,pMechanism,hKey) ) );
+
+ for ( std::vector<CK_BYTE>::const_iterator i(vData.begin()); i<vData.end(); i+=partSize.getCurrent() ) {
+ const CK_ULONG lPartLen( i+partSize.getNext()<vData.end() ? partSize.getCurrent() : vData.end()-i );
+ CK_ULONG ulEncryptedPartLen;
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,(CK_BYTE_PTR)&(*i),lPartLen,NULL_PTR,&ulEncryptedPartLen) ) );
+ const size_t oldSize( vEncryptedDataParted.size() );
+ vEncryptedDataParted.resize(oldSize+ulEncryptedPartLen);
+ CK_BYTE dummy;
+ const CK_BYTE_PTR pEncryptedPart( ulEncryptedPartLen>0 ? &vEncryptedDataParted.at(oldSize) : &dummy );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,(CK_BYTE_PTR)&(*i),lPartLen,pEncryptedPart,&ulEncryptedPartLen) ) );
+ vEncryptedDataParted.resize(oldSize+ulEncryptedPartLen);
+ }
+ {
+ CK_ULONG ulLastEncryptedPartLen;
+ const CK_RV rv( CRYPTOKI_F_PTR( C_EncryptFinal(hSession,NULL_PTR,&ulLastEncryptedPartLen) ) );
+ if ( isSizeOK ) {
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ const size_t oldSize( vEncryptedDataParted.size() );
+ CK_BYTE dummy;
+ vEncryptedDataParted.resize(oldSize+ulLastEncryptedPartLen);
+ const CK_BYTE_PTR pLastEncryptedPart( ulLastEncryptedPartLen>0 ? &vEncryptedDataParted.at(oldSize) : &dummy );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptFinal(hSession,pLastEncryptedPart,&ulLastEncryptedPartLen) ) );
+ vEncryptedDataParted.resize(oldSize+ulLastEncryptedPartLen);
+ } else {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("C_EncryptFinal should fail with C_CKR_DATA_LEN_RANGE", (CK_RV)CKR_DATA_LEN_RANGE, rv);
+ vEncryptedDataParted = vData;
+ }
+ }
+
+ // Single-part decryption
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptInit(hSession,pMechanism,hKey) ) );
+
+ {
+ CK_ULONG ulDataLen;
+ const CK_RV rv( CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),NULL_PTR,&ulDataLen) ) );
+ if ( isSizeOK ) {
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ std::vector<CK_BYTE> vDecryptedData(ulDataLen);
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),&vDecryptedData.front(),&ulDataLen) ) );
+ vDecryptedData.resize(ulDataLen);
+ CPPUNIT_ASSERT_MESSAGE("C_Encrypt C_Decrypt does not give the original", vData==vDecryptedData);
+ } else {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "C_Decrypt should fail with CKR_ENCRYPTED_DATA_LEN_RANGE", (CK_RV)CKR_ENCRYPTED_DATA_LEN_RANGE, rv );
+ }
+ }
+
+ // Multi-part decryption
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptInit(hSession,pMechanism,hKey) ) );
+ {
+ std::vector<CK_BYTE> vDecryptedData;
+ CK_BYTE dummy;
+ for ( std::vector<CK_BYTE>::iterator i(vEncryptedDataParted.begin()); i<vEncryptedDataParted.end(); i+=partSize.getCurrent()) {
+ const CK_ULONG ulPartLen( i+partSize.getNext()<vEncryptedDataParted.end() ? partSize.getCurrent() : vEncryptedDataParted.end()-i );
+ CK_ULONG ulDecryptedPartLen;
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&(*i),ulPartLen,NULL_PTR,&ulDecryptedPartLen) ) );
+ const size_t oldSize( vDecryptedData.size() );
+ vDecryptedData.resize(oldSize+ulDecryptedPartLen);
+ const CK_BYTE_PTR pDecryptedPart( ulDecryptedPartLen>0 ? &vDecryptedData.at(oldSize) : &dummy );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&(*i),ulPartLen,pDecryptedPart,&ulDecryptedPartLen) ) );
+ vDecryptedData.resize(oldSize+ulDecryptedPartLen);
+ }
+ {
+ CK_ULONG ulLastPartLen;
+ const CK_RV rv( CRYPTOKI_F_PTR( C_DecryptFinal(hSession,NULL_PTR,&ulLastPartLen) ) );
+ if ( isSizeOK ) {
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ const size_t oldSize( vDecryptedData.size() );
+ vDecryptedData.resize(oldSize+ulLastPartLen);
+ const CK_BYTE_PTR pLastPart( ulLastPartLen>0 ? &vDecryptedData.at(oldSize) : &dummy );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptFinal(hSession,pLastPart,&ulLastPartLen) ) );
+ vDecryptedData.resize(oldSize+ulLastPartLen);
+ CPPUNIT_ASSERT_MESSAGE("C_EncryptUpdate/C_EncryptFinal C_DecryptUpdate/C_DecryptFinal does not give the original", vData==vDecryptedData);
+ } else {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "C_EncryptFinal should fail with CKR_ENCRYPTED_DATA_LEN_RANGE", (CK_RV)CKR_ENCRYPTED_DATA_LEN_RANGE, rv );
+ }
+ }
+ }
+}
+
+CK_RV SymmetricAlgorithmTests::generateRsaPrivateKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pubAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE privAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
+ };
+
+ CK_OBJECT_HANDLE hPub = CK_INVALID_HANDLE;
+ hKey = CK_INVALID_HANDLE;
+ CK_RV rv;
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pubAttribs, sizeof(pubAttribs)/sizeof(CK_ATTRIBUTE),
+ privAttribs, sizeof(privAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPub, &hKey) );
+ if (hPub != CK_INVALID_HANDLE)
+ {
+ CRYPTOKI_F_PTR( C_DestroyObject(hSession, hPub) );
+ }
+ return rv;
+}
+
+void SymmetricAlgorithmTests::aesWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
+{
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE genKeyType = CKK_GENERIC_SECRET;
+ CK_BYTE keyPtr[128];
+ CK_ULONG keyLen =
+ mechanismType == CKM_AES_KEY_WRAP_PAD ? 125UL : 128UL;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) },
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) }, // Wrapping is allowed even on sensitive objects
+ { CKA_VALUE, keyPtr, keyLen }
+ };
+ CK_OBJECT_HANDLE hSecret;
+ CK_RV rv;
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, keyPtr, keyLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ hSecret = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hSecret) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hSecret != CK_INVALID_HANDLE);
+
+ CK_BYTE_PTR wrappedPtr = NULL_PTR;
+ CK_ULONG wrappedLen = 0UL;
+ CK_ULONG zero = 0UL;
+ CK_ULONG rndKeyLen = keyLen;
+ if (mechanismType == CKM_AES_KEY_WRAP_PAD)
+ rndKeyLen = (keyLen + 7) & ~7;
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_KEY_UNEXTRACTABLE);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hSecret) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ attribs[0].pValue = &bTrue;
+
+ hSecret = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hSecret) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hSecret != CK_INVALID_HANDLE);
+
+ // Estimate wrapped length
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(wrappedLen == rndKeyLen + 8);
+
+ wrappedPtr = (CK_BYTE_PTR) malloc(wrappedLen);
+ CPPUNIT_ASSERT(wrappedPtr != NULL_PTR);
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(wrappedLen == rndKeyLen + 8);
+
+ // This should always fail because wrapped data have to be longer than 0 bytes
+ zero = 0;
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &zero) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ CK_ATTRIBUTE nattribs[] = {
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bFalse,sizeof(bFalse) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) }
+ };
+ CK_OBJECT_HANDLE hNew;
+
+ hNew = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_UnwrapKey(hSession, &mechanism, hKey, wrappedPtr, wrappedLen, nattribs, sizeof(nattribs)/sizeof(CK_ATTRIBUTE), &hNew) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hNew != CK_INVALID_HANDLE);
+
+ free(wrappedPtr);
+ wrappedPtr = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hSecret) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_OBJECT_HANDLE hRsa;
+ hRsa = CK_INVALID_HANDLE;
+ rv = generateRsaPrivateKey(hSession, CK_TRUE, CK_TRUE, hRsa);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hRsa != CK_INVALID_HANDLE);
+
+ CK_OBJECT_CLASS privateClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE rsaKeyType = CKK_RSA;
+ CK_BYTE_PTR p2Ptr = NULL_PTR;
+ CK_ULONG p2Len = 0UL;
+ CK_ATTRIBUTE rsaAttribs[] = {
+ { CKA_CLASS, &privateClass, sizeof(privateClass) },
+ { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) },
+ { CKA_PRIME_2, NULL_PTR, 0UL }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hRsa, rsaAttribs, sizeof(rsaAttribs)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT(rsaAttribs[0].ulValueLen == sizeof(CK_OBJECT_CLASS));
+ CPPUNIT_ASSERT(*(CK_OBJECT_CLASS*)rsaAttribs[0].pValue == CKO_PRIVATE_KEY);
+ CPPUNIT_ASSERT(rsaAttribs[1].ulValueLen == sizeof(CK_KEY_TYPE));
+ CPPUNIT_ASSERT(*(CK_KEY_TYPE*)rsaAttribs[1].pValue == CKK_RSA);
+
+ p2Len = rsaAttribs[2].ulValueLen;
+ p2Ptr = (CK_BYTE_PTR) malloc(2 * p2Len);
+ CPPUNIT_ASSERT(p2Ptr != NULL_PTR);
+ rsaAttribs[2].pValue = p2Ptr;
+ rsaAttribs[2].ulValueLen = p2Len;
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hRsa, rsaAttribs, sizeof(rsaAttribs)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(rsaAttribs[2].ulValueLen == p2Len);
+
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hRsa, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ wrappedPtr = (CK_BYTE_PTR) malloc(wrappedLen);
+ CPPUNIT_ASSERT(wrappedPtr != NULL_PTR);
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hRsa, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hRsa) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_ATTRIBUTE nRsaAttribs[] = {
+ { CKA_CLASS, &privateClass, sizeof(privateClass) },
+ { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bFalse,sizeof(bFalse) },
+ { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
+ };
+
+ hRsa = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_UnwrapKey(hSession, &mechanism, hKey, wrappedPtr, wrappedLen, nRsaAttribs, sizeof(nRsaAttribs)/sizeof(CK_ATTRIBUTE), &hRsa) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hRsa != CK_INVALID_HANDLE);
+
+ rsaAttribs[2].pValue = p2Ptr + p2Len;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hRsa, rsaAttribs, sizeof(rsaAttribs)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT(rsaAttribs[0].ulValueLen == sizeof(CK_OBJECT_CLASS));
+ CPPUNIT_ASSERT(*(CK_OBJECT_CLASS*)rsaAttribs[0].pValue == CKO_PRIVATE_KEY);
+ CPPUNIT_ASSERT(rsaAttribs[1].ulValueLen == sizeof(CK_KEY_TYPE));
+ CPPUNIT_ASSERT(*(CK_KEY_TYPE*)rsaAttribs[1].pValue == CKK_RSA);
+ CPPUNIT_ASSERT(rsaAttribs[2].ulValueLen == p2Len);
+ CPPUNIT_ASSERT(memcmp(p2Ptr, p2Ptr + p2Len, p2Len) == 0);
+
+ free(wrappedPtr);
+ free(p2Ptr);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hRsa) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SymmetricAlgorithmTests::testAesEncryptDecrypt()
+{
+ CK_RV rv;
+ // CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ // CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token keys.
+ rv = generateAesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // AES allways have the block size of 128 bits (0x80 bits 0x10 bytes).
+ // with padding all message sizes could be encrypted-decrypted.
+ // without padding the message size must be a multiple of the block size.
+ const int blockSize(0x10);
+ encryptDecrypt(CKM_AES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_AES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_AES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_AES_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_AES_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_AES_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_AES_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_AES_CTR,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_AES_CTR,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_AES_CTR,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+#ifdef WITH_AES_GCM
+ encryptDecrypt(CKM_AES_GCM,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_AES_GCM,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_AES_GCM,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+#endif
+}
+
+void SymmetricAlgorithmTests::testAesWrapUnwrap()
+{
+ CK_RV rv;
+ // CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ // CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the session so we can create a private object
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ // Generate a wrapping session public key
+ rv = generateAesKey(hSession,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ aesWrapUnwrap(CKM_AES_KEY_WRAP, hSession, hKey);
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ aesWrapUnwrap(CKM_AES_KEY_WRAP_PAD, hSession, hKey);
+#endif
+}
+
+void SymmetricAlgorithmTests::testDesEncryptDecrypt()
+{
+ CK_RV rv;
+ // CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
+ // CK_ULONG sopinLength = sizeof(sopin) - 1;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Open read-only session on when the token is not initialized should fail
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-only session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // 3DES and DES always have the block size of 64 bits (0x40 bits 0x8 bytes).
+ // with padding all message sizes could be encrypted-decrypted.
+ // without padding the message size must be a multiple of the block size.
+ const int blockSize(0x8);
+
+#ifndef WITH_FIPS
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token keys.
+ rv = generateDesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ encryptDecrypt(CKM_DES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_DES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_DES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_DES_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+
+ CK_OBJECT_HANDLE hKey2 = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token keys.
+ rv = generateDes2Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKey2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_DES3_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+#endif
+
+ CK_OBJECT_HANDLE hKey3 = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token keys.
+ rv = generateDes3Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKey3);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_DES3_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+}
+
+void SymmetricAlgorithmTests::testNullTemplate()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanism1 = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
+ CK_MECHANISM mechanism2 = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism1, NULL_PTR, 0, &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism2, NULL_PTR, 0, &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_TEMPLATE_INCOMPLETE);
+}
+
+void SymmetricAlgorithmTests::testNonModifiableDesKeyGeneration()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanism = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BBOOL bToken = IN_SESSION;
+
+ CK_ATTRIBUTE keyAttribs[] =
+ {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_MODIFIABLE, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bTrue, sizeof(bTrue) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // The C_GenerateKey call failed if CKA_MODIFIABLE was bFalse
+ // This was a bug in the SoftHSM implementation
+ keyAttribs[2].pValue = &bFalse;
+ keyAttribs[2].ulValueLen = sizeof(bFalse);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs) / sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ // The call would fail with CKR_ATTRIBUTE_READ_ONLY
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now create a template where the CKA_MODIFIABLE attribute is last in the list
+ CK_ATTRIBUTE keyAttribs1[] =
+ {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bTrue, sizeof(bTrue) },
+ { CKA_MODIFIABLE, &bTrue, sizeof(bTrue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs1, sizeof(keyAttribs1) / sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now when CKA_MODIFIABLE is bFalse the key generation succeeds
+ keyAttribs1[2].pValue = &bFalse;
+ keyAttribs1[2].ulValueLen = sizeof(bFalse);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs1, sizeof(keyAttribs1) / sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SymmetricAlgorithmTests::testCheckValue()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_ULONG bytes = 16;
+ CK_BYTE pCheckValue[] = { 0x2b, 0x84, 0xf6 };
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) },
+ { CKA_CHECK_VALUE, &pCheckValue, sizeof(pCheckValue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, 8,
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_VALUE_INVALID);
+
+ keyAttribs[7].ulValueLen = 0;
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, 8,
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_ATTRIBUTE checkAttrib[] = {
+ { CKA_CHECK_VALUE, &pCheckValue, sizeof(pCheckValue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hKey, checkAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(checkAttrib[0].ulValueLen == 0);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, 7,
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ checkAttrib[0].ulValueLen = sizeof(pCheckValue);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hKey, checkAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(checkAttrib[0].ulValueLen == 3);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SymmetricAlgorithmTests::testAesCtrOverflow()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the session so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ // Generate a session keys.
+ rv = generateAesKey(hSession,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_MECHANISM mechanism = { CKM_AES_CTR, NULL_PTR, 0 };
+ CK_AES_CTR_PARAMS ctrParams =
+ {
+ 2,
+ {
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+ }
+ };
+ mechanism.pParameter = &ctrParams;
+ mechanism.ulParameterLen = sizeof(ctrParams);
+
+ CK_BYTE plainText[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x00 };
+ std::vector<CK_BYTE> vEncryptedData;
+ std::vector<CK_BYTE> vEncryptedDataParted;
+ std::vector<CK_BYTE> vDecryptedData;
+ std::vector<CK_BYTE> vDecryptedDataParted;
+ CK_ULONG ulEncryptedDataLen;
+ CK_ULONG ulEncryptedPartLen;
+ CK_ULONG ulDataLen;
+ CK_ULONG ulDataPartLen;
+
+ // Single-part encryption
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,plainText,sizeof(plainText),NULL_PTR,&ulEncryptedDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_DATA_LEN_RANGE, rv );
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,plainText,sizeof(plainText)-1,NULL_PTR,&ulEncryptedDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedData.resize(ulEncryptedDataLen);
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,plainText,sizeof(plainText)-1,&vEncryptedData.front(),&ulEncryptedDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedData.resize(ulEncryptedDataLen);
+
+ // Multi-part encryption
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,plainText,sizeof(plainText)-1,NULL_PTR,&ulEncryptedPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedDataParted.resize(ulEncryptedPartLen);
+ rv = CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,plainText,sizeof(plainText)-1,&vEncryptedDataParted.front(),&ulEncryptedPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedDataParted.resize(ulEncryptedPartLen);
+ rv = CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,plainText,1,NULL_PTR,&ulEncryptedPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_DATA_LEN_RANGE, rv );
+
+ // Single-part decryption
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size()+1,NULL_PTR,&ulDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_ENCRYPTED_DATA_LEN_RANGE, rv );
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),NULL_PTR,&ulDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vDecryptedData.resize(ulDataLen);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),&vDecryptedData.front(),&ulDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vDecryptedData.resize(ulDataLen);
+
+ // Multi-part decryption
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&vEncryptedData.front(),vEncryptedData.size(),NULL_PTR,&ulDataPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vDecryptedDataParted.resize(ulDataPartLen);
+ rv = CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&vEncryptedData.front(),vEncryptedData.size(),&vDecryptedDataParted.front(),&ulDataPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vDecryptedDataParted.resize(ulDataPartLen);
+ rv = CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&vEncryptedData.front(),1,NULL_PTR,&ulDataPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_ENCRYPTED_DATA_LEN_RANGE, rv );
+}
diff --git a/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.h b/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.h
new file mode 100644
index 0000000..9b96ae1
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricAlgorithmTests.h
+
+ Contains test cases for symmetrical algorithms (i.e., AES and DES)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H
+#define _SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class SymmetricAlgorithmTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(SymmetricAlgorithmTests);
+ CPPUNIT_TEST(testAesEncryptDecrypt);
+ CPPUNIT_TEST(testDesEncryptDecrypt);
+#ifdef HAVE_AES_KEY_WRAP
+ CPPUNIT_TEST(testAesWrapUnwrap);
+#endif
+ CPPUNIT_TEST(testNullTemplate);
+ CPPUNIT_TEST(testNonModifiableDesKeyGeneration);
+ CPPUNIT_TEST(testCheckValue);
+ CPPUNIT_TEST(testAesCtrOverflow);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testAesEncryptDecrypt();
+ void testDesEncryptDecrypt();
+ void testAesWrapUnwrap();
+ void testNullTemplate();
+ void testNonModifiableDesKeyGeneration();
+ void testCheckValue();
+ void testAesCtrOverflow();
+
+protected:
+ CK_RV generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+#ifndef WITH_FIPS
+ CK_RV generateDesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+#endif
+ CK_RV generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ void encryptDecrypt(
+ CK_MECHANISM_TYPE mechanismType,
+ size_t sizeOfIV,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hKey,
+ size_t messageSize,
+ bool isSizeOK=true);
+ void aesWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey);
+ CK_RV generateRsaPrivateKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+};
+
+#endif // !_SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H
diff --git a/SoftHSMv2/src/lib/test/TestsBase.cpp b/SoftHSMv2/src/lib/test/TestsBase.cpp
new file mode 100644
index 0000000..1c8467c
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TestsBase.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TestsBase.cpp
+
+ Base class for test classes.
+ *****************************************************************************/
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+void TestsBase::setUp() {
+ TestsNoPINInitBase::setUp();
+
+ CK_SESSION_HANDLE hSession;
+
+ // Open session
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION|CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession)==CKR_OK ) );
+
+ // Login SO
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_Login(hSession,CKU_SO, m_soPin1, m_soPin1Length)==CKR_OK ) );
+
+ // Initialize the user pin
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length)==CKR_OK ) );
+}
diff --git a/SoftHSMv2/src/lib/test/TestsBase.h b/SoftHSMv2/src/lib/test/TestsBase.h
new file mode 100644
index 0000000..6bcf894
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TestsBase.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TestsBase.h
+
+ Base class for test classes.
+ *****************************************************************************/
+
+#ifndef SRC_LIB_TEST_TESTSBASE_H_
+#define SRC_LIB_TEST_TESTSBASE_H_
+
+#include <TestsNoPINInitBase.h>
+
+class TestsBase : public TestsNoPINInitBase {
+public:
+ virtual void setUp();
+};
+
+
+#endif /* SRC_LIB_TEST_TESTSBASE_H_ */
diff --git a/SoftHSMv2/src/lib/test/TestsNoPINInitBase.cpp b/SoftHSMv2/src/lib/test/TestsNoPINInitBase.cpp
new file mode 100644
index 0000000..f5bb066
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TestsNoPINInitBase.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TestsNoPINInitBase.cpp
+
+ Base class for test classes. Used when there is no need for user login.
+ *****************************************************************************/
+
+#include "TestsNoPINInitBase.h"
+#include <cstring>
+#include <cppunit/extensions/HelperMacros.h>
+#include <vector>
+#include <sstream>
+
+#ifdef P11M
+#ifdef _WIN32
+CK_FUNCTION_LIST_PTR FunctionList::getFunctionListPtr(const char*const libName, HINSTANCE__* p11Library, const char*getFunctionList) {
+#else
+#include <dlfcn.h>
+
+static CK_FUNCTION_LIST_PTR getFunctionListPtr(const char*const libName, void *const p11Library, const char*getFunctionList) {
+#endif //_WIN32
+ CPPUNIT_ASSERT_MESSAGE(libName, p11Library);
+#ifdef _WIN32
+ const CK_C_GetFunctionList pGFL( (CK_C_GetFunctionList)GetProcAddress(
+ p11Library,
+ getFunctionList.c_str()
+ ) );
+#else
+ const CK_C_GetFunctionList pGFL( (CK_C_GetFunctionList)dlsym(
+ p11Library,
+ getFunctionList
+ ) );
+#endif //_WIN32
+ CPPUNIT_ASSERT_MESSAGE(libName, pGFL);
+ CK_FUNCTION_LIST_PTR ptr(NULL_PTR);
+ const CK_RV retCode( pGFL(&ptr) );
+ if ( !ptr && (retCode)!=CKR_OK) {
+ std::ostringstream oss;
+ oss << "C_GetFunctionList failed...error no = 0x" << std::hex << retCode << " libName '" << libName << "'.";
+ CPPUNIT_ASSERT_MESSAGE(oss.str(), false);
+ }
+ return ptr;
+}
+#endif //P11M
+void TestsNoPINInitBase::getSlotIDs() {
+ bool hasFoundFree(false);
+ bool hasFoundInitialized(false);
+ CK_ULONG nrOfSlots;
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, NULL_PTR, &nrOfSlots)==CKR_OK ) );
+ std::vector<CK_SLOT_ID> slotIDs(nrOfSlots);
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, &slotIDs.front(), &nrOfSlots)==CKR_OK ) );
+ for ( std::vector<CK_SLOT_ID>::iterator i=slotIDs.begin(); i!=slotIDs.end(); i++ ) {
+ CK_TOKEN_INFO tokenInfo;
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_GetTokenInfo(*i, &tokenInfo)==CKR_OK ) );
+ if ( tokenInfo.flags&CKF_TOKEN_INITIALIZED ) {
+ if ( !hasFoundInitialized ) {
+ hasFoundInitialized = true;
+ m_initializedTokenSlotID = *i;
+ }
+ } else {
+ if ( !hasFoundFree ) {
+ hasFoundFree = true;
+ m_notInitializedTokenSlotID = *i;
+ }
+ }
+ }
+ if ( !hasFoundInitialized ) {
+ m_initializedTokenSlotID = m_notInitializedTokenSlotID;
+ }
+}
+
+TestsNoPINInitBase::TestsNoPINInitBase() :
+#ifdef P11M
+#ifdef _WIN32
+ p11Library( LoadLibrary(libName.c_str()) ),
+#else
+ p11Library( dlopen(P11M, RTLD_LAZY) ),
+#endif
+ m_ptr(getFunctionListPtr(P11M, p11Library, "C_GetFunctionList")),
+#endif
+ m_invalidSlotID(((CK_SLOT_ID)1<<31)),
+ m_initializedTokenSlotID(m_invalidSlotID),
+ m_notInitializedTokenSlotID(m_invalidSlotID),
+ m_soPin1((CK_UTF8CHAR_PTR)"12345678"),
+ m_soPin1Length(strlen((char*)m_soPin1)),
+ m_userPin1((CK_UTF8CHAR_PTR)"1234"),
+ m_userPin1Length(strlen((char*)m_userPin1)) {};
+
+void TestsNoPINInitBase::setUp() {
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // initialize cryptoki
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) ) );
+ // update slot IDs to initialized and not initialized token.
+ getSlotIDs();
+ // (Re)initialize the token
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) ) );
+ // Reset cryptoki to get new slot IDs.
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) ) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) ) );
+ // slot IDs must be updated since the ID of the initialized token has changed.
+ getSlotIDs();
+}
+
+void TestsNoPINInitBase::tearDown() {
+ const CK_RV result(CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) ) );
+ if ( result==CKR_OK||result==CKR_CRYPTOKI_NOT_INITIALIZED ) {
+ return;
+ }
+ std::ostringstream oss;
+ oss << "C_Finalize failed with CK_RV: " << std::hex << result;
+ CPPUNIT_ASSERT_MESSAGE(oss.str(), false);
+}
+
+#ifdef P11M
+TestsNoPINInitBase::~TestsNoPINInitBase() {
+ if ( !p11Library ) {
+ return;
+ }
+#ifdef _WIN32
+ FreeLibrary(p11Library);
+#else
+ dlclose(p11Library);
+#endif // _WIN32
+}
+
+void softHSMLog(const int, const char*, const char*, const int, const char*, ...)
+{
+
+}
+#else
+TestsNoPINInitBase::~TestsNoPINInitBase() {}
+#endif // P11M
diff --git a/SoftHSMv2/src/lib/test/TestsNoPINInitBase.h b/SoftHSMv2/src/lib/test/TestsNoPINInitBase.h
new file mode 100644
index 0000000..acce9f1
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TestsNoPINInitBase.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TestsNoPINInitBase.h
+
+ Base class for test classes. Used when there is no need for user login.
+ *****************************************************************************/
+
+#ifndef SRC_LIB_TEST_TESTSNOPININITBASE_H_
+#define SRC_LIB_TEST_TESTSNOPININITBASE_H_
+
+#include "cryptoki.h"
+#include <cppunit/TestFixture.h>
+
+
+#ifdef P11M
+#define CRYPTOKI_F_PTR(func) m_ptr->func
+#else
+#define CRYPTOKI_F_PTR(func) func
+#endif
+
+class TestsNoPINInitBase : public CppUnit::TestFixture {
+public:
+ TestsNoPINInitBase();
+ virtual ~TestsNoPINInitBase();
+
+ virtual void setUp();
+ virtual void tearDown();
+private:
+ void getSlotIDs();
+#ifdef P11M
+#ifdef _WIN32
+ HINSTANCE__* p11Library;
+#else
+ void *const p11Library;
+#endif
+protected:
+ const CK_FUNCTION_LIST_PTR m_ptr;
+#else
+protected:
+#endif
+ const CK_SLOT_ID m_invalidSlotID;
+ CK_SLOT_ID m_initializedTokenSlotID;
+ CK_SLOT_ID m_notInitializedTokenSlotID;
+
+ const CK_UTF8CHAR_PTR m_soPin1;
+ const CK_ULONG m_soPin1Length;
+
+ const CK_UTF8CHAR_PTR m_userPin1;
+ const CK_ULONG m_userPin1Length;
+};
+
+
+#endif /* SRC_LIB_TEST_TESTSNOPININITBASE_H_ */
diff --git a/SoftHSMv2/src/lib/test/TokenTests.cpp b/SoftHSMv2/src/lib/test/TokenTests.cpp
new file mode 100644
index 0000000..9fc77ba
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TokenTests.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TokenTests.cpp
+
+ Contains test cases to C_InitToken
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "TokenTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TokenTests);
+
+void TokenTests::testInitToken()
+{
+ CK_RV rv;
+ CK_UTF8CHAR label[32];
+ CK_SESSION_HANDLE hSession;
+ CK_TOKEN_INFO tokenInfo;
+ CK_CHAR serialNumber[16];
+
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, NULL_PTR, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_invalidSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ // Initialize
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get token serial
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_initializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ memcpy(serialNumber, tokenInfo.serialNumber, 16);
+
+ // Initialize with wrong password
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length - 1, label) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_EXISTS);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Re-initialize
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Compare token serial
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_initializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(memcmp(serialNumber, tokenInfo.serialNumber, 16) == 0);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
diff --git a/SoftHSMv2/src/lib/test/TokenTests.h b/SoftHSMv2/src/lib/test/TokenTests.h
new file mode 100644
index 0000000..cc08b72
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TokenTests.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TokenTests.h
+
+ Contains test cases to C_InitToken
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TOKENTESTS_H
+#define _SOFTHSM_V2_TOKENTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class TokenTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(TokenTests);
+ CPPUNIT_TEST(testInitToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInitToken();
+};
+
+#endif // !_SOFTHSM_V2_TOKENTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/UserTests.cpp b/SoftHSMv2/src/lib/test/UserTests.cpp
new file mode 100644
index 0000000..d4999e5
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/UserTests.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UserTests.cpp
+
+ Contains test cases to C_InitPIN, C_SetPIN, C_Login, and C_Logout
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "UserTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(UserTests);
+
+void UserTests::testInitPIN()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(CK_INVALID_HANDLE, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, 0) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void UserTests::testLogin()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession[2];
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Set up user PIN
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_PIN_NOT_INITIALIZED);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession[0], m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(CK_INVALID_HANDLE, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, NULL_PTR, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, 0) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession[1]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY_EXISTS);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession[1]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession[0]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession[0]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length - 1) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);
+}
+
+void UserTests::testLogout()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void UserTests::testSetPIN()
+{
+ CK_RV rv;
+ const CK_UTF8CHAR_PTR pin2((CK_UTF8CHAR_PTR)"12345");
+ const CK_ULONG pin2Length(strlen((char*)pin2));
+ const CK_UTF8CHAR_PTR so2pin((CK_UTF8CHAR_PTR)"123456789");
+ const CK_ULONG so2pinLength(strlen((char*)so2pin));
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Set up user PIN
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(CK_INVALID_HANDLE, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, NULL_PTR, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, NULL_PTR, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, 0) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, pin2, pin2Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, pin2, pin2Length, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, so2pin, so2pinLength, so2pin, so2pinLength) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_soPin1, m_soPin1Length, so2pin, so2pinLength) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_soPin1, m_soPin1Length, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, so2pin, so2pinLength, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/SoftHSMv2/src/lib/test/UserTests.h b/SoftHSMv2/src/lib/test/UserTests.h
new file mode 100644
index 0000000..9104208
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/UserTests.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UserTests.h
+
+ Contains test cases to C_InitPIN, C_SetPIN, C_Login, and C_Logout
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_USERTESTS_H
+#define _SOFTHSM_V2_USERTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class UserTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(UserTests);
+ CPPUNIT_TEST(testInitPIN);
+ CPPUNIT_TEST(testLogin);
+ CPPUNIT_TEST(testLogout);
+ CPPUNIT_TEST(testSetPIN);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInitPIN();
+ void testLogin();
+ void testLogout();
+ void testSetPIN();
+};
+
+#endif // !_SOFTHSM_V2_USERTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/p11test.cpp b/SoftHSMv2/src/lib/test/p11test.cpp
new file mode 100644
index 0000000..1198c91
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/p11test.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ p11test.cpp
+
+ The main test executor for tests on the PKCS#11 interface in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestFailure.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/SourceLine.h>
+#include <cppunit/Message.h>
+#include <cppunit/Exception.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+#include <stdlib.h>
+#include <iostream>
+#ifdef _WIN32
+#include "setenv.h"
+#endif
+
+class MyListener : public CPPUNIT_NS::TestListener {
+ virtual void startTest( CPPUNIT_NS::Test*const pTest ) {
+ std::cout << std::endl << pTest->getName() << ' ' << pTest->countTestCases() << std::endl << std::endl;
+ }
+ virtual void addFailure( const CPPUNIT_NS::TestFailure & failure ) {
+ const CPPUNIT_NS::SourceLine solurceLine( failure.sourceLine() );
+ CPPUNIT_NS::Message message( failure.thrownException()->message() );
+ std::cout << solurceLine.fileName() << ' ' << solurceLine.lineNumber() << ' ' << message.shortDescription() << std::endl;
+ std::cout << message.details() << std::endl << std::endl;
+ }
+};
+int main(int argc, char**const argv)
+{
+#ifndef _WIN32
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+#else
+ setenv("SOFTHSM2_CONF", ".\\softhsm2.conf", 1);
+#endif
+
+ CPPUNIT_NS::TestFactoryRegistry &registry( CPPUNIT_NS::TestFactoryRegistry::getRegistry() );
+
+ CPPUNIT_NS::TextTestRunner runner;
+ runner.addTest(registry.makeTest());
+ if ( argc<2 ) {
+ return runner.run() ? 0 : 1;
+ }
+ if ( std::string("direct").find(*(argv+1))==std::string::npos ) {
+ return runner.run(*(argv+1)) ? 0 : 1;
+ }
+ runner.addTest(registry.makeTest());
+ CPPUNIT_NS::TestResult controller;
+ CPPUNIT_NS::TestResultCollector result;
+ controller.addListener( &result );
+ MyListener progress;
+ controller.addListener( &progress );
+
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/SoftHSMv2/src/lib/test/softhsm2-alt.conf.in b/SoftHSMv2/src/lib/test/softhsm2-alt.conf.in
new file mode 100644
index 0000000..5bdcb1f
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/softhsm2-alt.conf.in
@@ -0,0 +1,6 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = @builddir@/tokens
+objectstore.backend = file
+log.level = INFO
+slots.removable = true
diff --git a/SoftHSMv2/src/lib/test/softhsm2-alt.conf.win32 b/SoftHSMv2/src/lib/test/softhsm2-alt.conf.win32
new file mode 100644
index 0000000..68cb2ec
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/softhsm2-alt.conf.win32
@@ -0,0 +1,6 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = .\tokens
+objectstore.backend = file
+log.level = INFO
+slots.removable = true
diff --git a/SoftHSMv2/src/lib/test/softhsm2.conf.in b/SoftHSMv2/src/lib/test/softhsm2.conf.in
new file mode 100644
index 0000000..6554669
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/softhsm2.conf.in
@@ -0,0 +1,6 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = @builddir@/tokens
+objectstore.backend = file
+log.level = INFO
+slots.removable = false
diff --git a/SoftHSMv2/src/lib/test/softhsm2.conf.win32 b/SoftHSMv2/src/lib/test/softhsm2.conf.win32
new file mode 100644
index 0000000..a877d1f
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/softhsm2.conf.win32
@@ -0,0 +1,6 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = .\tokens
+objectstore.backend = file
+log.level = INFO
+slots.removable = false
diff --git a/SoftHSMv2/src/lib/test/tokens/dummy.in b/SoftHSMv2/src/lib/test/tokens/dummy.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/tokens/dummy.in
diff --git a/SoftHSMv2/src/lib/win32/dllmain.cc b/SoftHSMv2/src/lib/win32/dllmain.cc
new file mode 100644
index 0000000..359227d
--- /dev/null
+++ b/SoftHSMv2/src/lib/win32/dllmain.cc
@@ -0,0 +1,18 @@
+#include <windows.h>
+
+__declspec(dllexport) BOOL WINAPI
+DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpvReserved)
+{
+ hModule = hModule;
+ lpvReserved = lpvReserved;
+
+ switch (ul_reason_for_call) {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ default:
+ break;
+ }
+ return (TRUE);
+}
diff --git a/SoftHSMv2/src/lib/win32/setenv.cpp b/SoftHSMv2/src/lib/win32/setenv.cpp
new file mode 100644
index 0000000..da41a62
--- /dev/null
+++ b/SoftHSMv2/src/lib/win32/setenv.cpp
@@ -0,0 +1,20 @@
+#include <config.h>
+#include <stdlib.h>
+#include <string>
+
+#ifdef _WIN32
+
+int
+setenv(const char *name, const char *value, int overwrite)
+{
+ std::string vv = name;
+ vv += "=";
+ vv += value;
+
+ if (overwrite != 1)
+ return false;
+
+ return _putenv(vv.c_str()) == 0;
+}
+
+#endif
diff --git a/SoftHSMv2/src/lib/win32/setenv.h b/SoftHSMv2/src/lib/win32/setenv.h
new file mode 100644
index 0000000..e199227
--- /dev/null
+++ b/SoftHSMv2/src/lib/win32/setenv.h
@@ -0,0 +1,12 @@
+#include <config.h>
+
+#ifdef _WIN32
+
+#ifndef _SETENV_H
+#define _SETENV_H
+
+int setenv(const char *name, const char *value, int overwrite);
+
+#endif
+
+#endif \ No newline at end of file
diff --git a/SoftHSMv2/src/lib/win32/syslog.cpp b/SoftHSMv2/src/lib/win32/syslog.cpp
new file mode 100644
index 0000000..927592e
--- /dev/null
+++ b/SoftHSMv2/src/lib/win32/syslog.cpp
@@ -0,0 +1,69 @@
+#include <config.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#ifdef _WIN32
+
+static HANDLE hEventLog = NULL;
+
+/*
+ * Close the Handle to the application Event Log
+ */
+void
+closelog() {
+ DeregisterEventSource(hEventLog);
+}
+
+/*
+ * Initialize event logging
+ */
+void
+openlog(const char *ident, int logopt, int facility) {
+ /* Get a handle to the Application event log */
+ hEventLog = RegisterEventSourceA(NULL, ident);
+}
+
+/*
+ * Log to the NT Event Log
+ */
+void
+syslog(int priority, const char *message, ...) {
+ va_list ap;
+ char buf[1024];
+ LPCSTR str[1];
+
+ str[0] = buf;
+
+ va_start(ap, message);
+ vsprintf(buf, message, ap);
+ va_end(ap);
+
+ /* Make sure that the channel is open to write the event */
+ if (hEventLog == NULL) {
+ openlog("SoftHSM", 0, 0);
+ }
+ if (hEventLog != NULL) {
+ switch (priority) {
+ case LOG_INFO:
+ case LOG_NOTICE:
+ case LOG_DEBUG:
+ ReportEventA(hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
+ 0x40000003, NULL, 1, 0, str, NULL);
+ break;
+ case LOG_WARNING:
+ ReportEventA(hEventLog, EVENTLOG_WARNING_TYPE, 0,
+ 0x80000002, NULL, 1, 0, str, NULL);
+ break;
+ default:
+ ReportEventA(hEventLog, EVENTLOG_ERROR_TYPE, 0,
+ 0xc0000001, NULL, 1, 0, str, NULL);
+ break;
+ }
+ }
+}
+
+#endif
diff --git a/SoftHSMv2/src/lib/win32/syslog.h b/SoftHSMv2/src/lib/win32/syslog.h
new file mode 100644
index 0000000..1ed207c
--- /dev/null
+++ b/SoftHSMv2/src/lib/win32/syslog.h
@@ -0,0 +1,46 @@
+#ifndef _SYSLOG_H
+#define _SYSLOG_H
+
+#include <stdio.h>
+
+/* priorities */
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but signification condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+/* NT event log does not support facility level */
+#define LOG_KERN 0
+#define LOG_USER 0
+#define LOG_MAIL 0
+#define LOG_DAEMON 0
+#define LOG_AUTH 0
+#define LOG_SYSLOG 0
+#define LOG_LPR 0
+#define LOG_LOCAL0 0
+#define LOG_LOCAL1 0
+#define LOG_LOCAL2 0
+#define LOG_LOCAL3 0
+#define LOG_LOCAL4 0
+#define LOG_LOCAL5 0
+#define LOG_LOCAL6 0
+#define LOG_LOCAL7 0
+
+/* Constant definitions for openlog() */
+#define LOG_PID 1
+#define LOG_CONS 2
+
+void
+closelog(void);
+
+void
+openlog(const char *ident, int logopt, int facility);
+
+void
+syslog(int priority, const char *message, ...);
+
+#endif
diff --git a/SoftHSMv2/testing/appveyor/APPVEYOR-NOTES.MD b/SoftHSMv2/testing/appveyor/APPVEYOR-NOTES.MD
new file mode 100644
index 0000000..b2347b0
--- /dev/null
+++ b/SoftHSMv2/testing/appveyor/APPVEYOR-NOTES.MD
@@ -0,0 +1,27 @@
+# AppVeyor integration with SoftHSMv2 on GitHub
+
+This document describes the process of integrating AppVeyor with SoftHSMv2 on GitHub.
+
+## Integration
+
+### Add project
+
+To add the project, click on the following:
+
+1. New Project
+2. GitHub
+3. opendnssec -> SoftHSMv2 -> Add
+
+### Settings
+
+The following settings where changed.
+
+#### General
+
+* Custom configuration .yml file name: .appveyor.yml
+* Skip branches without appveyor.yml: check
+
+## Dependencies
+
+Prebuilt dependencies (OpenSSL and CppUnit) are currently hosted in a dedicated
+repository by [disig/SoftHSM2-AppVeyor](https://github.com/disig/SoftHSM2-AppVeyor/)
diff --git a/SoftHSMv2/testing/appveyor/appveyor_build.bat b/SoftHSMv2/testing/appveyor/appveyor_build.bat
new file mode 100644
index 0000000..4e7f41f
--- /dev/null
+++ b/SoftHSMv2/testing/appveyor/appveyor_build.bat
@@ -0,0 +1,51 @@
+setlocal
+
+echo "Setting visual studio variables"
+
+call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %VCVARS_PLATFORM%
+@echo on
+
+echo "Setting PATH and other variables"
+set cur_dir=%CD%
+set PATH=%PATH%;%PYTHON_PATH%
+
+echo %cur_dir%
+cd win32
+
+python Configure.py %CONFIGURE_OPTIONS% || goto :error
+
+msbuild softhsm2.sln /p:Configuration="Release" /p:Platform="%MSBUILD_PLATFORM%" /p:PlatformToolset=v140 /target:Build || goto :error
+
+cd %cur_dir%
+
+IF "%ENV_PLATFORM%"=="x86" (set from_dir=%CD%\win32\Release) ELSE (set from_dir=%CD%\win32\x64\Release)
+
+echo "Testing build"
+
+cd %from_dir%
+cryptotest.exe || goto :error
+datamgrtest.exe || goto :error
+handlemgrtest.exe || goto :error
+objstoretest.exe || goto :error
+p11test.exe || goto :error
+sessionmgrtest.exe || goto :error
+slotmgrtest.exe || goto :error
+
+echo "Preparing output package"
+copy %from_dir%\softhsm2.dll %RELEASE_DIR% || goto :error
+copy %from_dir%\softhsm2-dump-file.exe %RELEASE_DIR% || goto :error
+copy %from_dir%\softhsm2-keyconv.exe %RELEASE_DIR% || goto :error
+copy %from_dir%\softhsm2-util.exe %RELEASE_DIR% || goto :error
+copy %cur_dir%\src\lib\common\softhsm2.conf.in %RELEASE_DIR%\softhsm2.conf || goto :error
+
+dir %RELEASE_DIR%
+
+@echo *** BUILD SUCCESSFUL ***
+endlocal
+@exit /b 0
+
+
+:error
+@echo *** BUILD FAILED ***
+endlocal
+@exit /b 1
diff --git a/SoftHSMv2/testing/appveyor/appveyor_download_requirements.ps1 b/SoftHSMv2/testing/appveyor/appveyor_download_requirements.ps1
new file mode 100644
index 0000000..cc374f5
--- /dev/null
+++ b/SoftHSMv2/testing/appveyor/appveyor_download_requirements.ps1
@@ -0,0 +1,80 @@
+Add-Type -AssemblyName System.IO.Compression.FileSystem
+function Unzip
+{
+ param([string]$zipfile, [string]$outpath)
+
+ [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
+}
+
+$CURRENT_DIR_PATH = (Get-Item -Path ".\" -Verbose).FullName
+$BUILD_DIR = Join-Path $CURRENT_DIR_PATH build
+
+#prepare directories
+Write-Host "Preparing directories"
+
+$exists = Test-Path build
+if ($exists -eq $false) {
+ mkdir build
+}
+cd build
+
+$exists = Test-Path $env:RELEASE_DIR
+if ($exists -eq $false) {
+ mkdir $env:RELEASE_DIR
+}
+
+$exists = Test-Path python
+if ($exists -eq $true) {
+ Remove-Item python -recurse
+}
+
+$exists = Test-Path "$env:CPPUNIT_PATH"
+if ($exists -eq $true) {
+ Remove-Item "$env:CPPUNIT_PATH" -recurse
+}
+
+$exists = Test-Path "$env:CRYPTO_PACKAGE_PATH"
+if ($exists -eq $true) {
+ Remove-Item "$env:CRYPTO_PACKAGE_PATH" -recurse
+}
+
+mkdir python
+
+Write-Host "Preparing directories - OK"
+
+Write-Host "Downloading needed tools and dependencies"
+
+$exists = Test-Path "$env:CRYPTO_PACKAGE_NAME"
+if ($exists -eq $false) {
+ $source = "https://github.com/disig/SoftHSM2-AppVeyor/raw/master/$env:PACKAGE_VERSION_NAME/$env:CRYPTO_PACKAGE"
+ Invoke-WebRequest $source -OutFile $env:CRYPTO_PACKAGE
+}
+
+$exists = Test-Path "$env:CPPUNIT_PACKAGE"
+if ($exists -eq $false) {
+ $source = "https://github.com/disig/SoftHSM2-AppVeyor/raw/master/$env:CPPUNIT_VERSION_NAME/$env:CPPUNIT_PACKAGE"
+ Invoke-WebRequest $source -OutFile $env:CPPUNIT_PACKAGE
+}
+
+$exists = Test-Path python-3.5.2-embed-win32.zip
+if ($exists -eq $false) {
+ $source = "https://www.python.org/ftp/python/3.5.2/python-3.5.2-embed-win32.zip"
+ Invoke-WebRequest $source -OutFile python-3.5.2-embed-win32.zip
+}
+
+Write-Host "Downloading needed tools and dependencies - OK"
+
+Write-Host "Extracting ..."
+Unzip "$BUILD_DIR/python-3.5.2-embed-win32.zip" "$env:PYTHON_PATH"
+
+Unzip "$BUILD_DIR/$env:CRYPTO_PACKAGE" "$BUILD_DIR"
+
+Unzip "$BUILD_DIR/$env:CPPUNIT_PACKAGE" "$BUILD_DIR"
+
+dir
+
+dir "$env:PYTHON_PATH"
+dir "$env:CRYPTO_PACKAGE_PATH"
+dir "$env:CPPUNIT_PATH"
+
+cd $CURRENT_DIR_PATH \ No newline at end of file
diff --git a/SoftHSMv2/testing/build-botan.sh b/SoftHSMv2/testing/build-botan.sh
new file mode 100644
index 0000000..fc31217
--- /dev/null
+++ b/SoftHSMv2/testing/build-botan.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+source `dirname "$0"`/lib.sh && init || exit 1
+
+BOTAN="Botan-2.4.0"
+BOTAN_URL="https://botan.randombit.net/releases/$BOTAN.tgz"
+BOTAN_FILENAME="$BOTAN.tgz"
+BOTAN_HASH_TYPE="sha1"
+BOTAN_HASH="212587ae2458d51052c496fbcc79dc4162d33349"
+
+check_if_built botan && exit 0
+start_build botan
+
+BOTAN_SRC=`fetch_src "$BOTAN_URL" "$BOTAN_FILENAME" "$BOTAN_HASH_TYPE" "$BOTAN_HASH"`
+
+build_ok=0
+case "$DISTRIBUTION" in
+ centos | \
+ redhat | \
+ fedora | \
+ sl | \
+ slackware | \
+ ubuntu | \
+ debian | \
+ opensuse | \
+ suse )
+ (
+ gunzip -c "$BOTAN_SRC" | tar xf - &&
+ cd "$BOTAN" &&
+ ./configure.py --prefix="$INSTALL_ROOT" &&
+ $MAKE &&
+ $MAKE install
+ ) &&
+ build_ok=1
+ ;;
+ freebsd | \
+ netbsd | \
+ openbsd )
+ opt=""
+ if uname -a 2>/dev/null | grep -q "FreeBSD 10" 2>/dev/null; then
+ opt="--cc=clang"
+ fi
+ (
+ gunzip -c "$BOTAN_SRC" | tar xf - &&
+ cd "$BOTAN" &&
+ python2.7 ./configure.py --prefix="$INSTALL_ROOT" $opt &&
+ $MAKE &&
+ $MAKE install
+ ) &&
+ build_ok=1
+ ;;
+ sunos )
+ platform=`uname -p`
+ opt=""
+ case "$platform" in
+ i386)
+ opt="--cpu=i686"
+ ;;
+
+ sparc)
+ opt="--cpu=sparc64"
+ ;;
+
+ *)
+ exit 1
+ ;;
+ esac
+ (
+ gunzip -c "$BOTAN_SRC" | tar xf - &&
+ cd "$BOTAN" &&
+ ./configure.py --prefix="$INSTALL_ROOT" $opt &&
+ $MAKE &&
+ $MAKE install
+ ) &&
+ build_ok=1
+ ;;
+esac
+
+finish
+
+if [ "$build_ok" -eq 1 ]; then
+ set_build_ok botan || exit 1
+ exit 0
+fi
+
+exit 1
diff --git a/SoftHSMv2/testing/build-softhsm2.sh b/SoftHSMv2/testing/build-softhsm2.sh
new file mode 100644
index 0000000..ec4f43c
--- /dev/null
+++ b/SoftHSMv2/testing/build-softhsm2.sh
@@ -0,0 +1,110 @@
+#!/usr/bin/env bash
+source `dirname "$0"`/lib.sh && init || exit 1
+
+require botan
+
+check_if_built softhsm2 && exit 0
+start_build softhsm2
+
+build_ok=0
+case "$DISTRIBUTION" in
+ openbsd )
+ export AUTOCONF_VERSION="2.68"
+ export AUTOMAKE_VERSION="1.11"
+ append_ldflags "-L/usr/local/lib"
+ ;;
+esac
+case "$DISTRIBUTION" in
+ centos | \
+ redhat | \
+ fedora | \
+ sl | \
+ slackware | \
+ debian | \
+ ubuntu | \
+ opensuse )
+ (
+ sh autogen.sh &&
+ mkdir -p build &&
+ cd build &&
+ ../configure --prefix="$INSTALL_ROOT" \
+ --disable-non-paged-memory \
+ --with-p11-kit="$INSTALL_ROOT/usr/local/share/p11-kit/modules" \
+ --with-migrate \
+ --with-crypto-backend=botan \
+ --with-botan="$INSTALL_ROOT" &&
+ $MAKE &&
+ $MAKE check &&
+ $MAKE install &&
+ cp "src/lib/common/softhsm2.conf" "$INSTALL_ROOT/etc/softhsm2.conf.build"
+ ) &&
+ build_ok=1
+ ;;
+ netbsd )
+ (
+ sh autogen.sh &&
+ mkdir -p build &&
+ cd build &&
+ ../configure --prefix="$INSTALL_ROOT" \
+ --disable-non-paged-memory \
+ --with-p11-kit="$INSTALL_ROOT/usr/local/share/p11-kit/modules" \
+ --with-migrate \
+ --with-crypto-backend=botan \
+ --with-botan="$INSTALL_ROOT" \
+ --with-sqlite3=/usr/pkg &&
+ $MAKE &&
+ $MAKE check &&
+ $MAKE install &&
+ cp "src/lib/common/softhsm2.conf" "$INSTALL_ROOT/etc/softhsm2.conf.build"
+ ) &&
+ build_ok=1
+ ;;
+ freebsd | \
+ openbsd )
+ (
+ sh autogen.sh &&
+ mkdir -p build &&
+ cd build &&
+ ../configure --prefix="$INSTALL_ROOT" \
+ --disable-non-paged-memory \
+ --with-p11-kit="$INSTALL_ROOT/usr/local/share/p11-kit/modules" \
+ --with-migrate \
+ --with-crypto-backend=botan \
+ --with-botan="$INSTALL_ROOT" \
+ --with-sqlite3=/usr/local &&
+ $MAKE &&
+ $MAKE check &&
+ $MAKE install &&
+ cp "src/lib/common/softhsm2.conf" "$INSTALL_ROOT/etc/softhsm2.conf.build"
+ ) &&
+ build_ok=1
+ ;;
+ sunos | \
+ suse )
+ (
+ sh autogen.sh &&
+ mkdir -p build &&
+ cd build &&
+ ../configure --prefix="$INSTALL_ROOT" \
+ --disable-non-paged-memory \
+ --with-p11-kit="$INSTALL_ROOT/usr/local/share/p11-kit/modules" \
+ --with-migrate \
+ --with-crypto-backend=botan \
+ --with-botan="$INSTALL_ROOT" &&
+ $MAKE &&
+ $MAKE check &&
+ $MAKE install &&
+ cp "src/lib/common/softhsm2.conf" "$INSTALL_ROOT/etc/softhsm2.conf.build"
+ ) &&
+ build_ok=1
+ ;;
+esac
+
+finish
+
+if [ "$build_ok" -eq 1 ]; then
+ set_build_ok softhsm2 || exit 1
+ exit 0
+fi
+
+exit 1
diff --git a/SoftHSMv2/testing/lib.sh b/SoftHSMv2/testing/lib.sh
new file mode 100644
index 0000000..8a03846
--- /dev/null
+++ b/SoftHSMv2/testing/lib.sh
@@ -0,0 +1,2232 @@
+exit ()
+{
+ if [ -n "$_CLEANUP_TEST" ]; then
+ rm -f "$WORKSPACE_ROOT/.testing" 2>/dev/null
+ rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+ fi
+
+ if [ -n "$_SYSLOG_TRACE_PID" ]; then
+ case "$DISTRIBUTION" in
+ debian | \
+ ubuntu | \
+ redhat | \
+ centos | \
+ sl | \
+ slackware | \
+ opensuse | \
+ suse | \
+ freebsd | \
+ netbsd | \
+ openbsd | \
+ sunos )
+ kill -TERM "$_SYSLOG_TRACE_PID" 2>/dev/null &&
+ {
+ wait "$_SYSLOG_TRACE_PID"
+ unset _SYSLOG_TRACE_PID
+ }
+ ;;
+ esac
+ fi
+
+ builtin exit $*
+}
+
+append_path ()
+{
+ if [ -d "$1" ]; then
+ if [ -n "$PATH" ]; then
+ echo "$PATH" | $GREP -q -- "$1:" 2>/dev/null && return;
+ echo "$PATH" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ PATH="$PATH:$1"
+ else
+ PATH="$1"
+ fi
+ export PATH
+ fi
+}
+
+prepend_path ()
+{
+ if [ -d "$1" ]; then
+ if [ -n "$PATH" ]; then
+ echo "$PATH" | $GREP -q -- "$1:" 2>/dev/null && return;
+ echo "$PATH" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ PATH="$1:$PATH"
+ else
+ PATH="$1"
+ fi
+ export PATH
+ fi
+}
+
+append_cflags ()
+{
+ if [ -n "$1" ]; then
+ if [ -n "$CFLAGS" ]; then
+ echo "$CFLAGS" | $GREP -q -- "$1 " 2>/dev/null && return;
+ echo "$CFLAGS" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ CFLAGS="$CFLAGS $1"
+ else
+ CFLAGS="$1"
+ fi
+ export CFLAGS
+ fi
+}
+
+append_cppflags ()
+{
+ if [ -n "$1" ]; then
+ if [ -n "$CPPFLAGS" ]; then
+ echo "$CPPFLAGS" | $GREP -q -- "$1 " 2>/dev/null && return;
+ echo "$CPPFLAGS" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ CPPFLAGS="$CPPFLAGS $1"
+ else
+ CPPFLAGS="$1"
+ fi
+ export CPPFLAGS
+ fi
+}
+
+append_ldflags ()
+{
+ if [ -n "$1" ]; then
+ if [ -n "$LDFLAGS" ]; then
+ echo "$LDFLAGS" | $GREP -q -- "$1 " 2>/dev/null && return;
+ echo "$LDFLAGS" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ LDFLAGS="$LDFLAGS $1"
+ else
+ LDFLAGS="$1"
+ fi
+ export LDFLAGS
+ fi
+}
+
+append_ld_library_path ()
+{
+ if [ -d "$1" ]; then
+ if [ -n "$LD_LIBRARY_PATH" ]; then
+ echo "$LD_LIBRARY_PATH" | $GREP -q -- "$1:" 2>/dev/null && return;
+ echo "$LD_LIBRARY_PATH" | $GREP -q -- "$1\$" 2>/dev/null && return;
+ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$1"
+ else
+ LD_LIBRARY_PATH="$1"
+ fi
+ export LD_LIBRARY_PATH
+ fi
+}
+
+find_jenkins_workspace_root ()
+{
+ if [ -z "$WORKSPACE" -o ! -d "$WORKSPACE" ]; then
+ echo "find_jenkins_workspace_root: Unable to find workspace root since no WORKSPACE has been defined" >&2
+ return 1
+ fi
+
+ local workspace="$WORKSPACE"
+ local max_iter=20
+ local currdir
+
+ while [ "$max_iter" -gt 0 ] 2>/dev/null; do
+ # check if the last dir on the path is workspace
+ currdir=`echo "$workspace" | sed 's%.*/%%' 2>/dev/null`
+ if [ "$currdir" = "workspace" ]; then
+ break
+ fi
+
+ # remove the last dir on the path
+ workspace=`echo "$workspace" | sed 's%/[^/]*$%%' 2>/dev/null`
+
+ max_iter=$(( max_iter - 1))
+ done
+
+ if [ -n "$workspace" -a "$max_iter" -gt 0 ] 2>/dev/null; then
+ WORKSPACE_ROOT="$workspace"
+ return 0
+ fi
+
+ echo "find_jenkins_workspace_root: Failed to find workspace root in WORKSPACE=$WORKSPACE" >&2
+ return 1
+}
+
+find_program ()
+{
+ if [ -n "$1" ]; then
+ local path=`which "$1" 2>/dev/null`
+ if [ -n "$path" -a -x "$path" ]; then
+ echo "$path"
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+find_make ()
+{
+ local make
+ local program
+ local programs="gmake make"
+
+ case "$DISTRIBUTION" in
+ freebsd )
+ programs="gmake"
+ ;;
+ esac
+
+ for program in $programs; do
+ make=`find_program "$program"`
+ if [ -n "$make" ]; then
+ export MAKE="$make"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_m4 ()
+{
+ local m4
+ local program
+
+ for program in gm4 m4; do
+ m4=`find_program "$program"`
+ if [ -n "$m4" ]; then
+ export M4="$m4"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_md5sum ()
+{
+ local md5sum
+ local program
+
+ for program in md5sum gmd5sum md5; do
+ md5sum=`find_program "$program"`
+ if [ -n "$md5sum" ]; then
+ MD5SUM="$md5sum"
+ case "$program" in
+ md5)
+ MD5SUM="$MD5SUM -q"
+ ;;
+ esac
+ export MD5SUM
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_sha1sum ()
+{
+ local shasum
+ local program
+
+ for program in sha1sum gsha1sum shasum sha1; do
+ shasum=`find_program "$program"`
+ if [ -n "$shasum" ]; then
+ SHA1SUM="$shasum"
+ case "$program" in
+ shasum)
+ SHA1SUM="$SHA1SUM -a 1"
+ ;;
+ sha1)
+ SHA1SUM="$SHA1SUM -q"
+ ;;
+ esac
+ export SHA1SUM
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_sha256sum ()
+{
+ local sha256sum
+ local program
+
+ for program in sha256sum gsha256sum shasum sha256; do
+ sha256sum=`find_program "$program"`
+ if [ -n "$sha256sum" ]; then
+ SHA256SUM="$shasum"
+ case "$program" in
+ shasum)
+ SHA256SUM="$SHA256SUM -a 256"
+ ;;
+ sha256)
+ SHA256SUM="$SHA256SUM -q"
+ ;;
+ esac
+ export SHA256SUM
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_wget ()
+{
+ local wget
+ local program
+
+ for program in wget; do
+ wget=`find_program "$program"`
+ if [ -n "$wget" ]; then
+ export WGET="$wget"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_ccache ()
+{
+ local ccache
+ local program
+ local path
+
+ for program in ccache; do
+ ccache=`find_program "$program"`
+ if [ -n "$ccache" ]; then
+ export CCACHE="$ccache"
+ for path in /usr/lib64/ccache /usr/lib/ccache /usr/local/lib64/ccache /usr/local/lib/ccache; do
+ if [ -d "$path" ]; then
+ prepend_path "$path"
+ break
+ fi
+ done
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_cc ()
+{
+ local cc
+ local program
+
+ for program in cc gcc; do
+ cc=`find_program "$program"`
+ if [ -n "$cc" ]; then
+ export CC="$cc"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_cxx ()
+{
+ local cxx
+ local program
+
+ for program in c++ g++; do
+ cxx=`find_program "$program"`
+ if [ -n "$cxx" ]; then
+ export CXX="$cxx"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_tee ()
+{
+ local tee
+ local program
+
+ for program in tee; do
+ tee=`find_program "$program"`
+ if [ -n "$tee" ]; then
+ export TEE="$tee"
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+find_date ()
+{
+ local date
+ local program
+ local time_now
+
+ for program in date; do
+ date=`find_program "$program"`
+ if [ -n "$date" ]; then
+ time_now=`$date '+%s' 2>/dev/null`
+ if [ -n "$time_now" -a "$time_now" -gt 0 ] 2>/dev/null; then
+ export DATE="$date"
+ return 0
+ fi
+ fi
+ done
+
+ return 1
+}
+
+find_tail ()
+{
+ local tail
+ local tail_follow
+ local program
+ local programs="tail"
+
+ case "$DISTRIBUTION" in
+ sunos )
+ programs="gtail"
+ ;;
+ esac
+
+ for program in $programs; do
+ tail=`find_program "$program"`
+ if [ -n "$tail" ]; then
+ break
+ fi
+ done
+
+ if [ -z "$tail" ]; then
+ return 1
+ fi
+
+ case "$DISTRIBUTION" in
+ debian | \
+ ubuntu | \
+ redhat | \
+ centos | \
+ sl | \
+ slackware | \
+ opensuse | \
+ suse | \
+ sunos )
+ tail_follow="$tail --follow=name -n 0"
+ ;;
+ freebsd | \
+ netbsd )
+ tail_follow="$tail -f -F -n 0"
+ ;;
+ openbsd )
+ tail_follow="$tail -f -n 0"
+ ;;
+ esac
+
+ if [ -z "$tail_follow" ]; then
+ return 1
+ fi
+
+ export TAIL="$tail"
+ export TAIL_FOLLOW="$tail_follow"
+
+ return 0
+}
+
+find_grep ()
+{
+ local grep
+ local program
+
+ for program in ggrep grep; do
+ grep=`find_program "$program"`
+ if [ -n "$grep" ]; then
+ export GREP="$grep"
+ return
+ fi
+ done
+
+ return 1
+}
+
+setup_install_root ()
+{
+ if [ -n "$INSTALL_ROOT" ]; then
+ if [ -d "$INSTALL_ROOT" ]; then
+ return 0
+ else
+ return 1
+ fi
+ fi
+
+ if [ ! -d "$WORKSPACE_ROOT/root" ]; then
+ if ! mkdir -p "$WORKSPACE_ROOT/root" 2>/dev/null; then
+ echo "setup_install_root: Unable to create INSTALL_ROOT at $WORKSPACE_ROOT/root" >&2
+ return 1
+ fi
+ fi
+
+ if [ -n "$INSTALL_TAG" ]; then
+ if [ ! -d "$WORKSPACE_ROOT/root/$INSTALL_TAG" ]; then
+ if ! mkdir -p "$WORKSPACE_ROOT/root/$INSTALL_TAG" 2>/dev/null; then
+ echo "setup_install_root: Unable to create INSTALL_ROOT at $WORKSPACE_ROOT/root/$INSTALL_TAG" >&2
+ return 1
+ fi
+ fi
+
+ INSTALL_ROOT="$WORKSPACE_ROOT/root/$INSTALL_TAG"
+
+ if [ -d "$INSTALL_ROOT/bin" ]; then
+ prepend_path "$INSTALL_ROOT/bin"
+ fi
+ if [ -d "$INSTALL_ROOT/sbin" ]; then
+ prepend_path "$INSTALL_ROOT/sbin"
+ fi
+ if [ -d "$INSTALL_ROOT/lib64" ]; then
+ append_ldflags "-L$INSTALL_ROOT/lib64"
+ append_ld_library_path "$INSTALL_ROOT/lib64"
+ fi
+ if [ -d "$INSTALL_ROOT/lib" ]; then
+ append_ldflags "-L$INSTALL_ROOT/lib"
+ append_ld_library_path "$INSTALL_ROOT/lib"
+ fi
+ if [ -d "$INSTALL_ROOT/include" ]; then
+ append_cflags "-I$INSTALL_ROOT/include"
+ append_cppflags "-I$INSTALL_ROOT/include"
+ fi
+
+ return 0
+ fi
+
+ echo "setup_install_root: INSTALL_TAG or INSTALL_ROOT is not set, need to know in where to build/test" >&2
+ return 1
+}
+
+detect_revision ()
+{
+ if [ -z "$REVISION" ]; then
+ if [ -n "$SVN_REVISION" ]; then
+ REVISION="$SVN_REVISION"
+ elif [ -n "$GIT_COMMIT" ]; then
+ REVISION="$GIT_COMMIT"
+ fi
+ fi
+}
+
+detect_distribution ()
+{
+ DISTRIBUTION="UNKNOWN"
+
+ if [ -f "/etc/debian_version" ]; then
+ if uname -a 2>/dev/null | $GREP -q -i ubuntu 2>/dev/null; then
+ DISTRIBUTION="ubuntu"
+ else
+ DISTRIBUTION="debian"
+ fi
+ elif [ -f "/etc/redhat-release" ]; then
+ if $GREP -q -i centos /etc/redhat-release 2>/dev/null; then
+ DISTRIBUTION="centos"
+ elif $GREP -q -i fedora /etc/redhat-release 2>/dev/null; then
+ DISTRIBUTION="fedora"
+ elif $GREP -q -i "scientific linux" /etc/redhat-release 2>/dev/null; then
+ DISTRIBUTION="sl"
+ else
+ DISTRIBUTION="redhat"
+ fi
+ elif [ -f "/etc/slackware-version" ]; then
+ DISTRIBUTION="slackware"
+ elif [ -f "/etc/os-release" ]; then
+ if $GREP -q -i opensuse /etc/os-release 2>/dev/null; then
+ DISTRIBUTION="opensuse"
+ fi
+ elif [ -f "/etc/SuSE-release" ]; then
+ if $GREP -q -i "suse linux enterprise" /etc/SuSE-release 2>/dev/null; then
+ DISTRIBUTION="suse"
+ fi
+ elif uname -a 2>/dev/null | $GREP -q -i freebsd 2>/dev/null; then
+ DISTRIBUTION="freebsd"
+ elif uname -a 2>/dev/null | $GREP -q -i sunos 2>/dev/null; then
+ DISTRIBUTION="sunos"
+ elif uname -a 2>/dev/null | $GREP -q -i openbsd 2>/dev/null; then
+ DISTRIBUTION="openbsd"
+ elif uname -a 2>/dev/null | $GREP -q -i netbsd 2>/dev/null; then
+ DISTRIBUTION="netbsd"
+ fi
+
+ export DISTRIBUTION
+}
+
+init ()
+{
+ unset _CLEANUP_TEST
+ unset _SYSLOG_TRACE_PID
+ unset PRE_TEST
+ unset POST_TEST
+
+ find_grep || exit 1
+ detect_revision
+ detect_distribution
+ find_jenkins_workspace_root || exit 1
+ setup_install_root || exit 1
+ find_make || exit 1
+ find_m4 || exit 1
+ find_wget || exit 1
+ find_md5sum || exit 1
+ find_sha1sum || exit 1
+ find_sha256sum || exit 1
+ find_ccache # ccache needs to be found before cc/cxx
+ find_cc || exit 1
+ find_cxx || exit 1
+ find_tee || exit 1
+ find_date || exit 1
+ find_tail || exit 1
+
+ # prevent CTRL-Z and CTRL-C
+ trap "" SIGINT 2>/dev/null >/dev/null
+ trap "" SIGTSTP 2>/dev/null >/dev/null
+
+ return 0
+}
+
+finish ()
+{
+ local core
+
+ find "$WORKSPACE" "$INSTALL_ROOT" -name '*core' -type f 2>/dev/null | while read core; do
+ chmod a+r "$core" 2>/dev/null
+ done
+}
+
+check_if_built ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: check_if_built <name tag>" >&2
+ exit 1
+ fi
+
+ if [ -z "$REVISION" ]; then
+ echo "check_if_built: No REVISION is set, can't check if build is ok!" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.build" ]; then
+ local build_rev=`cat "$INSTALL_ROOT/.$name_tag.build" 2>/dev/null`
+
+ if [ "$REVISION" = "$build_rev" ]; then
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+start_build ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: start_build <name tag>" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.ok" ]; then
+ if ! rm "$INSTALL_ROOT/.$name_tag.ok" 2>/dev/null; then
+ echo "start_build: can't remove old ok file $INSTALL_ROOT/.$name_tag.ok !" >&2
+ exit 1
+ fi
+ fi
+
+ echo "start_build: Starting build for $name_tag on $DISTRIBUTION"
+ return 0
+}
+
+set_build_ok ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: set_build_ok <name tag>" >&2
+ exit 1
+ fi
+
+ if [ -z "$REVISION" ]; then
+ echo "set_build_ok: No REVISION is set, can't check if build is ok!" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.ok" ]; then
+ echo "set_build_ok: Build already mark ok, this should not happend. Did you forget to start_build?" >&2
+ exit 1
+ fi
+
+ echo "$REVISION" > "$INSTALL_ROOT/.$name_tag.build"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.build" ]; then
+ local build_rev=`cat "$INSTALL_ROOT/.$name_tag.build" 2>/dev/null`
+
+ if [ "$REVISION" = "$build_rev" ]; then
+ if ! touch "$INSTALL_ROOT/.$name_tag.ok" 2>/dev/null; then
+ echo "set_build_ok: Can't tag build ok $INSTALL_ROOT/.$name_tag.ok !" >&2
+ return 1
+ fi
+ return 0
+ fi
+ fi
+
+ echo "set_build_ok: Was not able to tag build ok!" >&2
+ return 1
+}
+
+check_if_tested ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: check_if_tested <name tag>" >&2
+ exit 1
+ fi
+
+ if [ -z "$REVISION" ]; then
+ echo "check_if_tested: No REVISION is set, can't check if test is ok!" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.test" ]; then
+ local build_rev=`cat "$INSTALL_ROOT/.$name_tag.test" 2>/dev/null`
+
+ if [ "$REVISION" = "$build_rev" ]; then
+ if [ "$INSTALL_ROOT/.$name_tag.junit" ]; then
+ if ! cp -- "$INSTALL_ROOT/.$name_tag.junit" "$WORKSPACE/junit.xml" 2>/dev/null; then
+ return 1
+ fi
+ fi
+ if [ -f "$WORKSPACE/junit.xml" ]; then
+ touch "$WORKSPACE/junit.xml"
+ fi
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+start_test ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: start_test <name tag>" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+# local time_start=`$DATE '+%s' 2>/dev/null`
+# local timeout=3600
+# local time_stop=$(( time_start + timeout ))
+# local time_now
+# local build_tag
+#
+# echo "$BUILD_TAG $$" > "$WORKSPACE_ROOT/.testing.$$"
+# build_tag=`cat "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null`
+# if [ "$build_tag" != "$BUILD_TAG $$" ]; then
+# echo "start_test: Unable to add test lock!" >&2
+# rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+# return 1
+# fi
+#
+# while true; do
+# if [ ! -f "$WORKSPACE_ROOT/.testing" ]; then
+# if ln -s "$WORKSPACE_ROOT/.testing.$$" "$WORKSPACE_ROOT/.testing" 2>/dev/null; then
+# build_tag=`cat "$WORKSPACE_ROOT/.testing" 2>/dev/null`
+# if [ "$build_tag" = "$BUILD_TAG $$" ]; then
+# if [ -f "$INSTALL_ROOT/.$name_tag.ok.test" ]; then
+# if ! rm "$INSTALL_ROOT/.$name_tag.ok.test" 2>/dev/null; then
+# echo "start_test: can't remove old ok file $INSTALL_ROOT/.$name_tag.ok.test !" >&2
+# exit 1
+# fi
+# fi
+# export _CLEANUP_TEST=1
+# return 0
+# fi
+# fi
+# fi
+#
+# if [ -z "$time_now" ]; then
+# echo "start_test: waiting for other tests to finish (timeout $timeout)"
+# fi
+#
+# time_now=`$DATE '+%s' 2>/dev/null`
+# if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+# break
+# fi
+# if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+# echo "start_test: Invalid timestamp from date!" >&2
+# exit 1
+# fi
+# sleep 2
+# done
+#
+# echo "start_test: Unable to get test lock, timeout" >&2
+# rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+# exit 1
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.ok.test" ]; then
+ if ! rm "$INSTALL_ROOT/.$name_tag.ok.test" 2>/dev/null; then
+ echo "start_test: can't remove old ok file $INSTALL_ROOT/.$name_tag.ok.test !" >&2
+ exit 1
+ fi
+ fi
+
+ echo "start_test: Starting test for $name_tag on $DISTRIBUTION"
+ return 0
+}
+
+stop_test ()
+{
+# local build_tag
+#
+# if [ ! -f "$WORKSPACE_ROOT/.testing" ]; then
+# echo "stop_test: Called without a test lock file, this should not happen!" >&2
+# return 1
+# fi
+#
+# build_tag=`cat "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null`
+# if [ "$build_tag" != "$BUILD_TAG $$" ]; then
+# echo "stop_test: Our test lock does not exist or is not our own!" >&2
+# return 1
+# fi
+#
+# build_tag=`cat "$WORKSPACE_ROOT/.testing" 2>/dev/null`
+# if [ "$build_tag" != "$BUILD_TAG $$" ]; then
+# echo "stop_test: Content of test lock changed during test!" >&2
+# rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+# return 1
+# fi
+#
+# rm -f "$WORKSPACE_ROOT/.testing" 2>/dev/null
+# rm -f "$WORKSPACE_ROOT/.testing.$$" 2>/dev/null
+# export _CLEANUP_TEST=""
+ return 0
+}
+
+set_test_ok ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: set_test_ok <name tag>" >&2
+ exit 1
+ fi
+
+ if [ -z "$REVISION" ]; then
+ echo "set_test_ok: No REVISION is set, can't check if test is ok!" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.ok.test" ]; then
+ echo "set_test_ok: Test already mark ok, this should not happend. Did you forget to start_test?" >&2
+ exit 1
+ fi
+
+ echo "$REVISION" > "$INSTALL_ROOT/.$name_tag.test"
+
+ if [ -f "$INSTALL_ROOT/.$name_tag.test" ]; then
+ local test_rev=`cat "$INSTALL_ROOT/.$name_tag.test" 2>/dev/null`
+
+ if [ "$REVISION" = "$test_rev" ]; then
+ if ! touch "$INSTALL_ROOT/.$name_tag.ok.test" 2>/dev/null; then
+ echo "set_test_ok: Can't tag test ok $INSTALL_ROOT/.$name_tag.ok.test !" >&2
+ return 1
+ fi
+ if [ -f "$WORKSPACE/junit.xml" ]; then
+ if ! cp -- "$WORKSPACE/junit.xml" "$INSTALL_ROOT/.$name_tag.junit" 2>/dev/null; then
+ echo "set_test_ok: Can't copy $WORKSPACE/junit.xml to $INSTALL_ROOT/.$name_tag.junit !" >&2
+ return 1
+ fi
+ fi
+ return 0
+ fi
+ fi
+
+ echo "set_test_ok: Was not able to tag test ok!" >&2
+ return 1
+}
+
+
+require ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: require <name tag>" >&2
+ exit 1
+ fi
+
+ local name_tag="$1"
+
+ if [ ! -f "$INSTALL_ROOT/.$name_tag.ok" ]; then
+ echo "require: Required program $name_tag not found or not built!" >&2
+ exit 1
+ fi
+
+ if [ ! -f "$INSTALL_ROOT/.$name_tag.build" ]; then
+ echo "require: Required program $name_tag corrupt, can't find build version!" >&2
+ exit 1
+ fi
+
+ local require_rev=`cat "$INSTALL_ROOT/.$name_tag.build" 2>/dev/null`
+
+ if [ -z "$require_rev" ]; then
+ echo "require: There is no build version for $name_tag!" >&2
+ exit 1
+ fi
+
+ export REVISION="$REVISION-$name_tag:$require_rev"
+}
+
+check_hash ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: check_hash <filename> <type> <hash>" >&2
+ exit 1
+ fi
+
+ local filename="$1"
+ local type="$2"
+ local hash="$3"
+ local file_hash
+
+ if [ -f "$filename" ]; then
+ case "$type" in
+ md5)
+ file_hash=`$MD5SUM "$filename" 2>/dev/null | awk '{print $1}'`
+ ;;
+ sha1)
+ file_hash=`$SHA1SUM "$filename" 2>/dev/null | awk '{print $1}'`
+ ;;
+ sha256)
+ file_hash=`$SHA256SUM "$filename" 2>/dev/null | awk '{print $1}'`
+ ;;
+ esac
+ if [ -n "$file_hash" -a "$hash" = "$file_hash" ]; then
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+fetch_src ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$4" ]; then
+ echo "usage: fetch_src <url> <filename> <type> <hash>" >&2
+ exit 1
+ fi
+
+ local url="$1"
+ local filename="$2"
+ local type="$3"
+ local hash="$4"
+ local path_filename
+
+ if [ ! -d "$WORKSPACE_ROOT/cache" ]; then
+ if ! mkdir -p "$WORKSPACE_ROOT/cache" 2>/dev/null; then
+ echo "fetch_src: Unable to create cache directory $WORKSPACE_ROOT/cache!" >&2
+ exit 1
+ fi
+ fi
+
+ path_filename="$WORKSPACE_ROOT/cache/$filename"
+
+ if [ -f "$path_filename" ]; then
+ if check_hash "$path_filename" "$type" "$hash"; then
+ echo "$path_filename"
+ return 0
+ fi
+ if ! rm "$path_filename" 2>/dev/null; then
+ echo "fetch_src: Unable to remove old invalid file $path_filename!" >&2
+ exit 1
+ fi
+ fi
+
+ if ! $WGET -O "$path_filename" "$url" 2>/dev/null; then
+ echo "fetch_src: wget failed!" >&2
+ rm -f "$path_filename" 2>/dev/null
+ exit 1
+ fi
+
+ if [ ! -f "$path_filename" ]; then
+ echo "fetch_src: File at $url not found at $path_filename!" >&2
+ exit 1
+ fi
+
+ if ! check_hash "$path_filename" "$type" "$hash"; then
+ echo "fetch_src: Checksum does not match for $path_filename!" >&2
+ exit 1
+ fi
+
+ echo "$path_filename"
+}
+
+log_init ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: log_this <log name>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+
+ touch "$log_stderr" "$log_stdout"
+}
+
+log_this ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: log_this <log name> <command> [options ...]" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ shift
+
+ touch "$log_stderr" "$log_stdout"
+
+ echo "log_this: logging $name for command: $*"
+ $* 2>>"$log_stderr" >>"$log_stdout"
+}
+
+log_this_timeout ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: log_this_timeout <log name> <timeout in seconds> <command ... >" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local timeout="$2"
+ local pid
+ shift 2
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "log_this_timeout: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "log_this_timeout: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "log_this_timeout: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ touch "$log_stderr" "$log_stdout"
+
+ echo "log_this_timeout: logging $name with timeout $timeout for command: $*"
+ ( $* 2>>"$log_stderr" >>"$log_stdout" ) &
+ pid="$!"
+
+ if [ -z "$pid" -o "$pid" -le 0 ] 2>/dev/null; then
+ echo "log_this_timeout: No pid from backgrounded program?" >&2
+ return 1
+ fi
+
+ while true; do
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "log_this_timeout: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ if ! kill -0 "$pid" 2>/dev/null; then
+ wait "$pid"
+ return "$?"
+ fi
+ sleep 1
+ done
+
+ kill -TERM "$pid"
+ sleep 1
+ if kill -0 "$pid" 2>/dev/null; then
+ kill -KILL "$pid"
+ fi
+ return 1
+}
+
+log_force_stop ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: log_force_stop <log name> [grace period in seconds]" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local grace="$2"
+ local log_stderr_pid="_log_pid.$BUILD_TAG.$name.stderr"
+ local log_stdout_pid="_log_pid.$BUILD_TAG.$name.stdout"
+ local stderr_pid
+ local stdout_pid
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop=$(( time_start + 5 ))
+ local time_now
+
+ if [ -n "$grace" -a "$grace" -gt 0 ] 2>/dev/null; then
+ time_stop=$(( time_start + grace ))
+ fi
+
+ while true; do
+ if [ ! -f "$log_stderr_pid" -a ! -f "$log_stdout_pid" ]; then
+ break
+ fi
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break;
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "log_force_stop: Invalid timestamp from date!" >&2
+ return 1
+ fi
+ sleep 1
+ done
+
+ if [ -f "$log_stderr_pid" ]; then
+ stderr_pid=`cat "$log_stderr_pid"`
+ if [ "$stderr_pid" -gt 0 ] 2>/dev/null; then
+ kill -TERM "$stderr_pid" 2>/dev/null
+ fi
+ rm -f "$log_stderr_pid"
+ fi
+
+ if [ -f "$log_stdout_pid" ]; then
+ stdout_pid=`cat "$log_stdout_pid"`
+ if [ "$stdout_pid" -gt 0 ] 2>/dev/null; then
+ kill -TERM "$stdout_pid" 2>/dev/null
+ fi
+ rm -f "$log_stdout_pid"
+ fi
+
+ return 0
+}
+
+log_grep ()
+{
+ local output=""
+ OPTIND=1
+ while getopts ":o" opt; do
+ case "$opt" in
+ o)
+ output=1
+ ;;
+ \?)
+ echo "log_grep: Invalid option: -$OPTARG" >&2
+ exit 1
+ ;;
+ esac
+ done
+ shift $((OPTIND-1))
+
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: log_grep [-o] <log name> <stdout|stderr|both> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ local type="$2"
+ local grep_string="$3"
+ local log_files
+
+ case "$type" in
+ stdout)
+ if [ ! -f "$log_stdout" ]; then
+ return 1
+ fi
+ log_files="$log_stdout"
+ ;;
+ stderr)
+ if [ ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stderr"
+ ;;
+ both)
+ if [ ! -f "$log_stdout" -a ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stdout $log_stderr"
+ ;;
+ esac
+
+ if [ -z "$log_files" ]; then
+ echo "log_grep: Wrong type of log file specified, should be stdout, stderr or both!" >&2
+ exit 1
+ fi
+
+ if [ -n "$output" ]; then
+ $GREP -- "$grep_string" $log_files 2>/dev/null
+ else
+ echo "log_grep: greping in $name for: $grep_string"
+ $GREP -q -- "$grep_string" $log_files 2>/dev/null
+ fi
+}
+
+log_grep_count ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$3" ]; then
+ echo "usage: log_grep_count <log name> <stdout|stderr|both> <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ local type="$2"
+ local grep_string="$3"
+ local count="$4"
+ local log_files
+ local count_found
+
+ case "$type" in
+ stdout)
+ if [ ! -f "$log_stdout" ]; then
+ return 1
+ fi
+ log_files="$log_stdout"
+ ;;
+ stderr)
+ if [ ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stderr"
+ ;;
+ both)
+ if [ ! -f "$log_stdout" -a ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stdout $log_stderr"
+ ;;
+ esac
+
+ if [ -z "$log_files" ]; then
+ echo "log_grep_count: Wrong type of log file specified, should be stdout, stderr or both!" >&2
+ exit 1
+ fi
+
+ echo "log_grep_count: greping in $name, should find $count of: $grep_string"
+ count_found=`$GREP -- "$grep_string" $log_files 2>/dev/null | wc -l 2>/dev/null`
+
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ return 1
+}
+
+log_waitfor ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$3" ]; then
+ echo "usage: log_waitfor <log name> <stdout|stderr|both> <timeout in seconds> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+ local type="$2"
+ local timeout="$3"
+ local grep_string="$4"
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local log_files
+
+ case "$type" in
+ stdout)
+ if [ ! -f "$log_stdout" ]; then
+ return 1
+ fi
+ log_files="$log_stdout"
+ ;;
+ stderr)
+ if [ ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stderr"
+ ;;
+ both)
+ if [ ! -f "$log_stdout" -a ! -f "$log_stderr" ]; then
+ return 1
+ fi
+ log_files="$log_stdout $log_stderr"
+ ;;
+ esac
+
+ if [ -z "$log_files" ]; then
+ echo "log_waitfor: Wrong type of log file specified, should be stdout, stderr or both!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "log_waitfor: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "log_waitfor: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "log_waitfor: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "log_waitfor: waiting for log $name to contain (timeout $timeout): $grep_string"
+ while true; do
+ if $GREP -q -- "$grep_string" $log_files 2>/dev/null; then
+ return 0
+ fi
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "log_waitfor: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+ return 1
+}
+
+log_cleanup ()
+{
+ local pid_file
+ local pid
+
+ ls _log_pid* 2>/dev/null | while read pid_file; do
+ pid=`cat $pid_file 2>/dev/null`
+
+ if [ -n "$pid" -a "$pid" -gt 0 ] 2>/dev/null; then
+ kill -TERM "$pid" 2>/dev/null
+ rm -f "$pid_file" 2>/dev/null
+ fi
+ done
+
+ rm -f "_log.$BUILD_TAG"* 2>/dev/null
+}
+
+log_remove ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: log_remove <log name>" >&2
+ exit 1
+ fi
+
+ local name="$1"
+ local log_stderr="_log.$BUILD_TAG.$name.stderr"
+ local log_stdout="_log.$BUILD_TAG.$name.stdout"
+
+ rm -f "$log_stderr" "$log_stdout" 2>/dev/null
+}
+
+log_save_try ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: log_save_try <try>" >&2
+ exit 1
+ fi
+
+ local try="$1"
+ local log_file
+
+ ls "_log.$BUILD_TAG"* 2>/dev/null | while read log_file; do
+ if ! mv "$log_file" "$log_file-try-$try" 2>/dev/null; then
+ echo "log_save_try: Unable to save log file $log_file to $log_file-try-$try"
+ return 1
+ fi
+ done
+ return 0
+}
+
+run_tests ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: run_tests <tests directory>" >&2
+ exit 1
+ fi
+
+ local test_dir="$1"
+ local entry
+ local test=()
+ local test_num=0
+ local test_iter=0
+ local test_path
+ local test_status
+ local test_failed=0
+ local test_start
+ local test_stop
+ local test_time
+ local pwd=`pwd`
+ local pwd2
+ local retry
+ local junit="$WORKSPACE/junit.xml"
+ local junit_head="$WORKSPACE/junit.xml.head"
+ local junit_test="$WORKSPACE/junit.xml.test"
+ local junit_foot="$WORKSPACE/junit.xml.foot"
+ local tail_pid
+ local test_name
+ local test_classname
+
+ if [ -n "$PRE_TEST" ]; then
+ if ! declare -F "$PRE_TEST" >/dev/null 2>/dev/null; then
+ unset PRE_TEST
+ fi
+ fi
+
+ if [ -n "$POST_TEST" ]; then
+ if ! declare -F "$POST_TEST" >/dev/null 2>/dev/null; then
+ unset POST_TEST
+ fi
+ fi
+
+ if [ -n "$INTERRUPT_TEST" ]; then
+ if ! declare -F "$INTERRUPT_TEST" >/dev/null 2>/dev/null; then
+ unset INTERRUPT_TEST
+ fi
+ fi
+
+ if [ -n "$RETRY_TEST" ]; then
+ if [ ! "$RETRY_TEST" -gt 0 ] 2>/dev/null; then
+ RETRY_TEST=0
+ fi
+ else
+ RETRY_TEST=0
+ fi
+
+ if [ -n "$RETRY_SLEEP" ]; then
+ if [ ! "$RETRY_SLEEP" -ge 0 ] 2>/dev/null; then
+ RETRY_SLEEP=10
+ fi
+ else
+ RETRY_SLEEP=10
+ fi
+
+ if ! cd "$test_dir" 2>/dev/null; then
+ echo "run_tests: unable to change to test directory $test_dir!" >&2
+ return 1
+ fi
+
+ rm -f "$junit" "$junit_test"
+ echo '<?xml version="1.0" encoding="UTF-8"?>' > "$junit_head"
+ echo '<testsuites>' > "$junit_head"
+
+ ls -1 2>/dev/null | $GREP '^[0-9]*' | $GREP -v '\.off$' 2>/dev/null >"_tests.$BUILD_TAG"
+ while read entry; do
+ if [ -d "$entry" -a -f "$entry/test.sh" ]; then
+ if [ -f "$entry/off" ]; then
+ test_name=`echo "$entry"|sed 's%\.% %g'|awk '{print $3}'`
+ if [ -z "$test_name" ]; then
+ test_name='unknown'
+ fi
+ test_classname=`echo "$entry"|sed 's%\.% %g'|awk '{print $1 "." $2}'`
+ if [ -z "$test_classname" ]; then
+ test_classname='unknown.unknown'
+ fi
+ echo '<testsuite name="'"$entry"'" tests="1" skip="1">' >> "$junit_test"
+ echo '<testcase name="'"$test_name"'" classname="'"$test_classname"'">' >> "$junit_test"
+ echo '<skipped message="Skipped">Test skipped, disabled with off file</skipped>' >> "$junit_test"
+ echo '</testcase>' >> "$junit_test"
+ echo '</testsuite>' >> "$junit_test"
+ else
+ test[test_num]="$entry"
+ test_num=$(( test_num + 1 ))
+ fi
+ fi
+ done <"_tests.$BUILD_TAG"
+ rm -f "_tests.$BUILD_TAG" 2>/dev/null
+
+ if [ "$test_num" -le 0 ] 2>/dev/null; then
+ echo "run_tests: no active tests found!" >&2
+ cd "$pwd"
+ # Do not generate JUnit if there is no tests or all tests skipped because
+ # Jenkins might mark it failed otherwise
+ rm -f "$junit_head" "$junit_test" "$junit_foot"
+ return 1
+ fi
+
+ if [ -n "$INTERRUPT_TEST" ]; then
+ STOP_TEST=0
+ trap "STOP_TEST=1" SIGINT
+ fi
+
+ echo "Running tests ..."
+ while [ "$test_iter" -lt "$test_num" ] 2>/dev/null; do
+ retry=0
+ test_path="${test[test_iter]}"
+ test_iter=$(( test_iter + 1 ))
+ test_start=`date +%s`
+ test_name=`echo "$test_path"|sed 's%\.% %g'|awk '{print $3}'`
+ if [ -z "$test_name" ]; then
+ test_name='unknown'
+ fi
+ test_classname=`echo "$test_path"|sed 's%\.% %g'|awk '{print $1 "." $2}'`
+ if [ -z "$test_classname" ]; then
+ test_classname='unknown.unknown'
+ fi
+ echo "##### `date` $test_iter/$test_num $test_path ... "
+ pwd2=`pwd`
+ cd "$test_path" 2>/dev/null &&
+ rm -f "_test.$BUILD_TAG" &&
+ touch "_test.$BUILD_TAG" &&
+ while [ "$retry" -le "$RETRY_TEST" ] 2>/dev/null; do
+ if [ "$retry" -gt 0 ] 2>/dev/null; then
+ syslog_stop &&
+ log_save_try "$retry" &&
+ syslog_save_try "$retry" ||
+ {
+ echo "##### `date` $test_iter/$test_num $test_path ... Unable to retry"
+ test_status=1
+ break
+ }
+ echo "##### `date` $test_iter/$test_num $test_path ... RETRY $retry in $RETRY_SLEEP seconds"
+ sleep "$RETRY_SLEEP"
+ rm -f "_test.$BUILD_TAG"
+ touch "_test.$BUILD_TAG"
+ fi
+ syslog_trace &&
+ if [ -n "$PRE_TEST" ]; then
+ $PRE_TEST "$test_path"
+ fi &&
+ ( source ./test.sh ) >> "_test.$BUILD_TAG" 2>&1
+ test_status="$?"
+ if [ -n "$INTERRUPT_TEST" -a "$STOP_TEST" = "1" ]; then
+ cat "_test.$BUILD_TAG"
+ echo "##### `date` $test_iter/$test_num $test_path ... INTERRUPTED"
+ break
+ fi
+ if [ "$test_status" -eq 0 ] 2>/dev/null; then
+ break
+ fi
+ retry=$(( retry + 1 ))
+ done
+ test_stop=`date +%s`
+ test_time=0
+ if [ "$test_start" -gt 0 -a "$test_stop" -gt 0 ] 2>/dev/null; then
+ test_time=$(( test_stop - test_start ))
+ fi
+ syslog_stop
+ if [ -n "$INTERRUPT_TEST" -a "$STOP_TEST" = "1" ]; then
+ $INTERRUPT_TEST "$test_path"
+ test_failed=1
+ break
+ elif [ -n "$POST_TEST" ]; then
+ $POST_TEST "$test_path" "$test_status"
+ fi
+ if [ "$test_status" -eq 0 ] 2>/dev/null; then
+ cat "_test.$BUILD_TAG"
+ echo "##### `date` $test_iter/$test_num $test_path ... OK"
+ log_cleanup
+ syslog_cleanup
+
+ echo '<testsuite name="'"$test_path"'" tests="1" time="'"$test_time"'">' >> "$junit_test"
+ echo '<testcase name="'"$test_name"'" classname="'"$test_classname"'" time="'"$test_time"'">' >> "$junit_test"
+ echo '</testcase>' >> "$junit_test"
+ echo '<system-out>' >> "$junit_test"
+ cat "_test.$BUILD_TAG" | sed 's%&%\&amp;%g' | sed 's%<%\&lt;%g' | sed 's%>%\&gt;%g' >> "$junit_test" 2>/dev/null
+ echo '</system-out>' >> "$junit_test"
+ echo '</testsuite>' >> "$junit_test"
+ else
+ test_failed=$(( test_failed + 1 ))
+ cat "_test.$BUILD_TAG"
+ echo "##### `date` $test_iter/$test_num $test_path ... FAILED!"
+
+ echo '<testsuite name="'"$test_path"'" tests="1" time="'"$test_time"'">' >> "$junit_test"
+ echo '<testcase name="'"$test_name"'" classname="'"$test_classname"'" time="'"$test_time"'">' >> "$junit_test"
+ echo '<failure message="Failed">Test failed, exit code '"$test_status"'</failure>' >> "$junit_test"
+ echo '</testcase>' >> "$junit_test"
+ echo '<system-err>' >> "$junit_test"
+ cat "_test.$BUILD_TAG" | sed 's%&%\&amp;%g' | sed 's%<%\&lt;%g' | sed 's%>%\&gt;%g' >> "$junit_test" 2>/dev/null
+ echo '</system-err>' >> "$junit_test"
+ echo '</testsuite>' >> "$junit_test"
+ fi
+ rm -f "_test.$BUILD_TAG"
+
+ if ! cd "$pwd2" 2>/dev/null; then
+ echo "run_tests: unable to change back to test directory $pwd2 after running a test!" >&2
+ test_failed=1
+ break
+ fi
+ done
+
+ if [ -n "$INTERRUPT_TEST" ]; then
+ trap "" SIGINT
+ fi
+
+ echo '</testsuites>' > "$junit_foot"
+ cat "$junit_head" "$junit_test" "$junit_foot" > "$junit" 2>/dev/null
+ rm -f "$junit_head" "$junit_test" "$junit_foot"
+
+ if ! cd "$pwd" 2>/dev/null; then
+ echo "run_tests: unable to change back to directory $pwd after running tests!" >&2
+ return 1
+ fi
+
+ if [ "$test_failed" -gt 0 ] 2>/dev/null; then
+ return 1
+ fi
+}
+
+run_test ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: run_test <test name> <test directory>" >&2
+ exit 1
+ fi
+
+ local test_name="$1"
+ local test_dir="$2"
+ local test_status
+ local pwd=`pwd`
+
+ if [ -n "$PRE_TEST" ]; then
+ if ! declare -F "$PRE_TEST" >/dev/null 2>/dev/null; then
+ unset PRE_TEST
+ fi
+ fi
+
+ if [ -n "$POST_TEST" ]; then
+ if ! declare -F "$POST_TEST" >/dev/null 2>/dev/null; then
+ unset POST_TEST
+ fi
+ fi
+
+ if [ -n "$INTERRUPT_TEST" ]; then
+ if ! declare -F "$INTERRUPT_TEST" >/dev/null 2>/dev/null; then
+ unset INTERRUPT_TEST
+ fi
+ fi
+
+ if [ ! -f "$test_dir/test.sh" ]; then
+ echo "run_test: no test.sh in test $test_name ($test_dir)!" >&2
+ return 1
+ fi
+
+ if ! cd "$test_dir" 2>/dev/null; then
+ echo "run_test: unable to change to test $test_name directory $test_dir!" >&2
+ return 1
+ fi
+
+ if [ -n "$INTERRUPT_TEST" ]; then
+ STOP_TEST=0
+ trap "STOP_TEST=1" SIGINT
+ fi
+
+ echo "##### Running test $test_name ..."
+ if [ -n "$PRE_TEST" ]; then
+ $PRE_TEST "$test_name"
+ fi &&
+ syslog_trace &&
+ ( source ./test.sh )
+ test_status="$?"
+ syslog_stop
+ if [ -n "$INTERRUPT_TEST" -a "$STOP_TEST" = "1" ]; then
+ echo "##### `date` $test_iter/$test_num $test_path ... INTERRUPTED"
+ $INTERRUPT_TEST "$test_path"
+ trap "" SIGINT
+ return 1
+ elif [ -n "$POST_TEST" ]; then
+ $POST_TEST "$test_name" "$test_status"
+ fi
+ if [ "$test_status" -eq 0 ] 2>/dev/null; then
+ echo "##### Test $test_name ... OK"
+ log_cleanup
+ syslog_cleanup
+ else
+ echo "##### Test $test_name ... FAILED!"
+ fi
+
+ if ! cd "$pwd" 2>/dev/null; then
+ echo "run_test: unable to change back to directory $pwd after running test $test_name!" >&2
+ return 1
+ fi
+
+ if [ "$test_status" -ne 0 ] 2>/dev/null; then
+ return 1
+ fi
+}
+
+syslog_trace ()
+{
+ if [ -n "$_SYSLOG_TRACE_PID" ]; then
+ echo "syslog_trace: Syslog trace already running (pid $_SYSLOG_TRACE_PID)!" >&2
+ exit 1
+ fi
+
+ local syslog_file
+
+ case "$DISTRIBUTION" in
+ debian | \
+ ubuntu )
+ syslog_file="/var/log/syslog"
+ ;;
+ redhat | \
+ centos | \
+ sl | \
+ slackware | \
+ opensuse | \
+ suse | \
+ freebsd | \
+ netbsd | \
+ openbsd )
+ syslog_file="/var/log/messages"
+ ;;
+ sunos )
+ syslog_file="/var/adm/messages"
+ ;;
+ esac
+
+ if [ -z "$syslog_file" ]; then
+ echo "syslog_trace: Unable to start trace of syslog: no syslog file set" >&2
+ exit 1
+ fi
+
+ if [ ! -r "$syslog_file" ]; then
+ echo "syslog_trace: Unable to start trace of syslog: no access to $syslog_file" >&2
+ exit 1
+ fi
+
+ $TAIL_FOLLOW "$syslog_file" >"_syslog.$BUILD_TAG" 2>/dev/null &
+ _SYSLOG_TRACE_PID="$!"
+
+ if [ -z "$_SYSLOG_TRACE_PID" -o ! "$_SYSLOG_TRACE_PID" -gt 0 ] 2>/dev/null; then
+ echo "syslog_trace: Unable to start trace of syslog!" >&2
+ exit 1
+ fi
+
+ if ! kill -0 "$_SYSLOG_TRACE_PID" 2>/dev/null >/dev/null; then
+ wait "$_SYSLOG_TRACE_PID"
+ echo "syslog_trace: Unable to start trace of syslog: exited with status $?"
+ exit 1
+ fi
+
+ echo "syslog_trace: trace started (pid $_SYSLOG_TRACE_PID)"
+}
+
+syslog_stop ()
+{
+ if [ -z "$_SYSLOG_TRACE_PID" ]; then
+ echo "syslog_stop: Syslog trace not started!" >&2
+ exit 1
+ fi
+
+ if kill -TERM "$_SYSLOG_TRACE_PID" 2>/dev/null; then
+ wait "$_SYSLOG_TRACE_PID" 2>/dev/null
+ unset _SYSLOG_TRACE_PID
+ fi
+
+ if [ -n "$_SYSLOG_TRACE_PID" ]; then
+ echo "syslog_stop: Unable to stop trace of syslog!" >&2
+ exit 1
+ fi
+
+ echo "syslog_stop: trace stopped"
+}
+
+syslog_waitfor ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: syslog_waitfor <timeout in seconds> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local timeout="$1"
+ local grep_string="$2"
+
+ if [ ! -f "_syslog.$BUILD_TAG" ]; then
+ echo "syslog_waitfor: No syslog file to grep from!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "syslog_waitfor: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "syslog_waitfor: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "syslog_waitfor: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "syslog_waitfor: waiting for syslog to contain (timeout $timeout): $grep_string"
+ while true; do
+ if $GREP -q -- "$grep_string" "_syslog.$BUILD_TAG" 2>/dev/null; then
+ return 0
+ fi
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ -z "$_SYSLOG_TRACE_PID" -o "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "syslog_waitfor: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+
+ return 1
+}
+
+syslog_waitfor_count ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: syslog_waitfor_count <timeout in seconds> <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local timeout="$1"
+ local count="$2"
+ local grep_string="$3"
+ local count_found
+
+ if [ ! -f "_syslog.$BUILD_TAG" ]; then
+ echo "syslog_waitfor_count: No syslog file to grep from!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "syslog_waitfor_count: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "syslog_waitfor_count: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "syslog_waitfor_count: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "syslog_waitfor_count: waiting for syslog to contain $count counts of (timeout $timeout): $grep_string"
+ while true; do
+ count_found=`$GREP -- "$grep_string" "_syslog.$BUILD_TAG" 2>/dev/null | wc -l 2>/dev/null`
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ -z "$_SYSLOG_TRACE_PID" -o "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "syslog_waitfor_count: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+
+ return 1
+}
+
+syslog_grep ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: syslog_grep <grep string ...>" >&2
+ exit 1
+ fi
+
+ local grep_string="$1"
+
+ if [ ! -f "_syslog.$BUILD_TAG" ]; then
+ echo "syslog_grep: No syslog file to grep from!" >&2
+ exit 1
+ fi
+
+ echo "syslog_grep: greping syslog for: $grep_string"
+ $GREP -q -- "$grep_string" "_syslog.$BUILD_TAG" 2>/dev/null
+}
+
+syslog_grep_count ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: syslog_grep_count <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local count="$1"
+ local grep_string="$2"
+ local count_found
+ # create a non-local variable so the caller can get the actually value if they want
+ syslog_grep_count_variable=0
+
+ if [ ! -f "_syslog.$BUILD_TAG" ]; then
+ echo "syslog_grep_count: No syslog file to grep from!" >&2
+ exit 1
+ fi
+
+ echo "syslog_grep_count: greping syslog, should find $count of: $grep_string"
+ count_found=`$GREP -- "$grep_string" "_syslog.$BUILD_TAG" 2>/dev/null | wc -l 2>/dev/null`
+ syslog_grep_count_variable=$count_found
+
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ return 1
+}
+
+syslog_cleanup ()
+{
+ rm -f "_syslog.$BUILD_TAG"* 2>/dev/null
+}
+
+syslog_save_try ()
+{
+ if [ -z "$1" ]; then
+ echo "usage: syslog_save_try <try>" >&2
+ exit 1
+ fi
+
+ local try="$1"
+
+ if ! mv "_syslog.$BUILD_TAG" "_syslog.$BUILD_TAG-try-$try" 2>/dev/null; then
+ echo "syslog_save_try: Unable to save syslog file _syslog.$BUILD_TAG to _syslog.$BUILD_TAG-try-$try"
+ return 1
+ fi
+ return 0
+}
+
+apply_parameter ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: apply_parameter <parameter tag> <parameter value> <files ... >" >&2
+ echo " ex: apply_parameter \"INSTALL_ROOT\" \"\$INSTALL_ROOT\" conf.xml" >&2
+ exit 1
+ fi
+
+ local parameter_tag="$1"
+ local parameter_value="$2"
+ shift 2
+ local files="$*"
+ local file
+
+ if echo "$parameter_tag" | grep -q "@" 2>/dev/null; then
+ echo "apply_parameter: parameter tag contains '@', it must not" >&2
+ return 1
+ fi
+
+ for file in $files; do
+ if [ ! -f "$file" ]; then
+ echo "apply_parameter: File $file not found" >&2
+ return 1
+ fi
+ if [ -f "$file.$$" ]; then
+ echo "apply_parameter: Temporary file $file.$$ exists but it should not" >&2
+ return 1
+ fi
+ done
+
+ for file in $files; do
+ sed 's%@'"$parameter_tag"'@%'"$parameter_value"'%g' "$file" > "$file.$$" 2>/dev/null &&
+ mv "$file.$$" "$file" 2>/dev/null ||
+ {
+ echo "apply_parameter: Unable to apply parameter $parameter_tag value $parameter_value to file $file" >&2
+ return 1
+ }
+ done
+
+ return 0
+}
+
+sed_inplace ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: sed_inplace <expression> <files ... >" >&2
+ exit 1
+ fi
+
+ local expression="$1"
+ shift 1
+ local files="$*"
+ local file
+
+ for file in $files; do
+ if [ ! -f "$file" ]; then
+ echo "sed_inplace: File $file not found" >&2
+ return 1
+ fi
+ if [ -f "$file.$$" ]; then
+ echo "sed_inplace: Temporary file $file.$$ exists but it should not" >&2
+ return 1
+ fi
+ done
+
+ for file in $files; do
+ sed "$expression" "$file" > "$file.$$" 2>/dev/null &&
+ mv "$file.$$" "$file" 2>/dev/null ||
+ {
+ echo "sed_inplace: Unable to sed inplace file $file" >&2
+ return 1
+ }
+ done
+
+ return 0
+}
+
+try_run ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: try_run <timeout in seconds> <command ... >" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local timeout="$1"
+ local pid
+ shift
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "try_run: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "try_run: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "try_run: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ ( $* ) &
+ pid="$!"
+
+ if [ -z "$pid" -o "$pid" -le 0 ] 2>/dev/null; then
+ echo "try_run: No pid from backgrounded program?" >&2
+ return 1
+ fi
+
+ while true; do
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "try_run: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ if ! kill -0 "$pid" 2>/dev/null; then
+ wait "$pid"
+ return "$?"
+ fi
+ sleep 1
+ done
+
+ kill -TERM "$pid"
+ sleep 1
+ if kill -0 "$pid" 2>/dev/null; then
+ kill -KILL "$pid"
+ fi
+ return 1
+}
+
+waitfor_this ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: waitfor_this <file to grep> <timeout in seconds> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local file="$1"
+ local timeout="$2"
+ local grep_string="$3"
+
+ if [ ! -f "$file" ]; then
+ echo "waitfor_this: No file to grep from!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "waitfor_this: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "waitfor_this: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "waitfor_this: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "waitfor_this: waiting for $file to contain (timeout $timeout): $grep_string"
+ while true; do
+ if $GREP -q -- "$grep_string" "$file" 2>/dev/null; then
+ return 0
+ fi
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "waitfor_this: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+
+ return 1
+}
+
+waitfor_count_this ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" -o -z "$4" ]; then
+ echo "usage: waitfor_count_this <file to grep> <timeout in seconds> <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local time_start=`$DATE '+%s' 2>/dev/null`
+ local time_stop
+ local time_now
+ local file="$1"
+ local timeout="$2"
+ local count="$3"
+ local grep_string="$4"
+ local count_found
+
+ if [ ! -f "$file" ]; then
+ echo "waitfor_count_this: No file to grep from!" >&2
+ exit 1
+ fi
+
+ if [ ! "$time_start" -gt 0 ] 2>/dev/null; then
+ echo "waitfor_count_this: Unable to get start time!" >&2
+ exit 1
+ fi
+
+ if [ ! "$timeout" -gt 0 ] 2>/dev/null; then
+ echo "waitfor_count_this: Wrong timeout value or 0!" >&2
+ exit 1
+ fi
+
+ if [ "$timeout" -gt 3600 ] 2>/dev/null; then
+ echo "waitfor_count_this: Too long timeout used, can't be over 3600 seconds!" >&2
+ exit 1
+ fi
+
+ time_stop=$(( time_start + timeout ))
+
+ echo "waitfor_count_this: waiting for $file to contain $count counts of (timeout $timeout): $grep_string"
+ while true; do
+ count_found=`$GREP -- "$grep_string" "$file" 2>/dev/null | wc -l 2>/dev/null`
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ time_now=`$DATE '+%s' 2>/dev/null`
+ if [ "$time_now" -ge "$time_stop" ] 2>/dev/null; then
+ break
+ fi
+ if [ -z "$time_now" -o ! "$time_now" -lt "$time_stop" ] 2>/dev/null; then
+ echo "waitfor_count_this: Invalid timestamp from date!" >&2
+ exit 1
+ fi
+ sleep 2
+ done
+
+ return 1
+}
+
+grep_this ()
+{
+ if [ -z "$1" -o -z "$2" ]; then
+ echo "usage: grep_this <file to grep> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local file="$1"
+ local grep_string="$2"
+
+ if [ ! -f "$file" ]; then
+ echo "grep_this: No file to grep from!" >&2
+ exit 1
+ fi
+
+ echo "grep_this: greping in $file for: $grep_string"
+ $GREP -q -- "$grep_string" "$file" 2>/dev/null
+}
+
+grep_count_this ()
+{
+ if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
+ echo "usage: grep_count_this <file to grep> <count> <grep string ...>" >&2
+ exit 1
+ fi
+
+ local file="$1"
+ local count="$2"
+ local grep_string="$3"
+ local count_found
+
+ if [ ! -f "$file" ]; then
+ echo "grep_count_this: No file to grep from!" >&2
+ exit 1
+ fi
+
+ echo "grep_count_this: greping in $file, should find $count of: $grep_string"
+ count_found=`$GREP -- "$grep_string" "$file" 2>/dev/null | wc -l 2>/dev/null`
+
+ if [ "$count_found" -eq "$count" ] 2>/dev/null; then
+ return 0
+ fi
+
+ return 1
+}
diff --git a/SoftHSMv2/testing/travis/travis.sh b/SoftHSMv2/testing/travis/travis.sh
new file mode 100644
index 0000000..6a1ca1f
--- /dev/null
+++ b/SoftHSMv2/testing/travis/travis.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+CONF_CRYPTO=""
+CONF_OBJSTORE=""
+
+case $CRYPTO in
+botan)
+ CONF_CRYPTO="$CONF_CRYPTO --with-crypto-backend=botan --with-botan=/usr"
+ CONF_CRYPTO="$CONF_CRYPTO --disable-ecc --disable-gost"
+ ;;
+openssl)
+ CONF_CRYPTO="$CONF_CRYPTO --with-crypto-backend=openssl --with-openssl=/usr"
+ CONF_CRYPTO="$CONF_CRYPTO --disable-gost"
+ openssl version -a
+ ;;
+*)
+ echo "Unknown crypto backend"
+ exit 1
+esac
+
+case $OBJSTORE in
+file)
+ CONF_OBJSTORE="$CONF_OBJSTORE"
+ ;;
+sqlite)
+ CONF_OBJSTORE="$CONF_OBJSTORE --with-objectstore-backend-db --with-migrate"
+ ;;
+*)
+ echo "Unknown objectstore backend"
+ exit 1
+esac
+
+sh autogen.sh && \
+./configure $CONF_CRYPTO $CONF_OBJSTORE && \
+make all check
diff --git a/SoftHSMv2/win32/.gitignore b/SoftHSMv2/win32/.gitignore
new file mode 100644
index 0000000..997db95
--- /dev/null
+++ b/SoftHSMv2/win32/.gitignore
@@ -0,0 +1,35 @@
+# get back config.h.in
+!config.h.in
+
+# Visual Studio
+*.opensdf
+*.sdf
+*.suo
+.vs/
+
+# Object files
+*.obj
+*.exe
+
+# Generated project files
+convarch.vcxproj
+convarch.vcxproj.filters
+cryptotest.vcxproj
+datamgrtest.vcxproj
+dump.vcxproj
+handlemgrtest.vcxproj
+keyconv.vcxproj
+keyconv.vcxproj.filters
+objstoretest.vcxproj
+p11test.vcxproj
+sessionmgrtest.vcxproj
+slotmgrtest.vcxproj
+softhsm2.vcxproj
+softhsm2.sln
+util.vcxproj
+util.vcxproj.filters
+
+# Build files
+Debug/
+Release/
+x64/ \ No newline at end of file
diff --git a/SoftHSMv2/win32/Configure.py b/SoftHSMv2/win32/Configure.py
new file mode 100644
index 0000000..a39a046
--- /dev/null
+++ b/SoftHSMv2/win32/Configure.py
@@ -0,0 +1,1167 @@
+#!python
+
+# Configure -- python version
+#
+# this script builds Visual Studio files
+
+from __future__ import print_function
+
+import sys
+import os
+import os.path
+import re
+import subprocess
+
+# files to configure
+
+filelist = ["config.h",
+ "softhsm2.sln",
+ "convarch\\convarch.vcxproj.filters",
+ "convarch\\convarch.vcxproj",
+ "cryptotest\\cryptotest.vcxproj",
+ "datamgrtest\\datamgrtest.vcxproj",
+ "dump\\dump.vcxproj",
+ "handlemgrtest\\handlemgrtest.vcxproj",
+ "keyconv\\keyconv.vcxproj.filters",
+ "keyconv\\keyconv.vcxproj",
+ "objstoretest\\objstoretest.vcxproj",
+ "p11test\\p11test.vcxproj",
+ "sessionmgrtest\\sessionmgrtest.vcxproj",
+ "slotmgrtest\\slotmgrtest.vcxproj",
+ "softhsm2\\softhsm2.vcxproj",
+ "util\\util.vcxproj.filters",
+ "util\\util.vcxproj"]
+
+# test files
+testlist = ["botan",
+ "ecc",
+ "gnump",
+ "gost",
+ "ossl",
+ "osslv",
+ "rawpss",
+ "rfc3394",
+ "rfc5649"]
+
+# variables to expand
+
+varvals = {}
+
+varnames = ["CUINCPATH",
+ "CULIBPATH",
+ "DEBUGDLLPATH",
+ "DEBUGINCPATH",
+ "DEBUGLIBPATH",
+ "DLLPATH",
+ "EXTRALIBS",
+ "INCLUDEPATH",
+ "LIBNAME",
+ "LIBPATH",
+ "PLATFORM",
+ "PLATFORMDIR",
+ "PLATFORMTOOLSET",
+ "RUNTIMELIBRARY"]
+
+# conditions to stack
+
+condvals = {}
+
+condnames = ["AESGCM",
+ "BOTAN",
+ "ECC",
+ "GOST",
+ "NONPAGE",
+ "OPENSSL",
+ "RAWPSS",
+ "RFC3394",
+ "RFC5649",
+ "TESTS"]
+
+# enable-xxx/disable-xxx arguments
+
+enablelist = ["64bit",
+ "debug",
+ "ecc",
+ "gost",
+ "keep",
+ "non-paged-memory",
+ "static-runtime",
+ "verbose"]
+
+# with-xxx/without-xxx arguments
+
+withlist = ["botan",
+ "cppunit",
+ "crypto-backend",
+ "debug-botan",
+ "debug-openssl",
+ "openssl",
+ "toolset"]
+
+# general commands
+
+commandlist = ["help", "clean"] # verbose, keep
+
+# usage
+
+usage = ["Usage: python Configure.py help",
+ " python Configure.py options*",
+ " python Configure.py clean"]
+
+# help
+
+myhelp = ["'python Configure.py' configures SoftHSMv2 build files.\n"] +\
+usage + [\
+"\nGeneral Commands:",
+" help print this help",
+" clean clean up generated files",
+" <none> print a summary of the configuration",
+"\nOptional Features:",
+" enable-verbose print messages [default=no]",
+" enable-keep keep test files after config [default=no]",
+" enable-64bit enable 64-bit compiling [default=no]",
+" enable-debug enable build of Debug config [default=yes]",
+" enable-ecc enable support for ECC [default=yes]",
+" enable-gost enable support for GOST [default=yes]",
+" enable-static-runtime enable build with static CRT (/MT) [default=no]",
+" enable-non-paged-memory enable non-paged memory [default=yes]",
+"\nOptional Packages:",
+" with-crypto-backend select the crypto backend [openssl|botan]",
+" with-botan=PATH speficy prefix of path of Botan (Release)",
+" with-debug-botan=PATH speficy prefix of path of Botan (Debug)",
+" with-openssl=PATH speficy prefix of path of OpenSSL (Release)",
+" with-debug-openssl=PATH speficy prefix of path of OpenSSL (Debug)",
+" with-cppunit=PATH specify prefix of path of CppUnit",
+" with-toolset=VALUE set Visual Studio platform toolset version (eg v110 for vs2012)",
+]
+
+# variables for parsing
+
+verbose = False
+configargs = None
+want_help = False
+want_clean = False
+want_unknown = False
+unknown_value = None
+enable_keep = False
+enable_debug = True
+enable_ecc = True
+enable_gost = True
+enable_static_runtime = False
+enable_non_paged = True
+platform = 32
+crypto_backend = "openssl"
+botan_path = "..\\..\\btn"
+debug_botan_path = None
+openssl_path = "..\\..\\ssl"
+debug_openssl_path = None
+want_tests = True
+cppunit_path = "..\\..\\cu"
+toolset = ""
+
+def dodetectplatform(visualstudio):
+ # detect platform tool set >= VS2010
+ global toolset
+
+ if "Microsoft Visual Studio 10.0" in visualstudio:
+ toolset="v100"
+ elif "Microsoft Visual Studio 11.0" in visualstudio:
+ toolset="v110"
+ elif "Microsoft Visual Studio 12.0" in visualstudio:
+ toolset="v120"
+ elif "Microsoft Visual Studio 14.0" in visualstudio:
+ toolset="v140"
+ else:
+ print("PlatformToolset for \""+visualstudio+"\" not supported")
+ toolset=""
+
+def dodetectvisualstudio():
+ """detect visual studio version"""
+ if os.environ.get('VSINSTALLDIR'):
+ dodetectplatform(os.environ.get('VSINSTALLDIR'))
+
+def parseargs(args):
+ """parse arguments"""
+ global verbose
+ global enable_keep
+ global want_help
+ global want_clean
+ global want_unknown
+ global unknown_value
+ global debug_botan_path
+ global debug_openssl_path
+ for arg in args:
+ if arg.lower() == "verbose":
+ verbose = True
+ continue
+ if arg.lower() == "keep":
+ enable_keep = True
+ continue
+ if arg.lower() == "help":
+ want_help = True
+ continue
+ di = re.match(r'disable-(.*)', arg, re.I)
+ if di:
+ appargs(arg)
+ myenable(di.group(1), False)
+ continue
+ en = re.match(r'enable-(.*)', arg, re.I)
+ if en:
+ appargs(arg)
+ myenable(en.group(1), True)
+ continue
+ wo = re.match(r'without-(.*)', arg, re.I)
+ if wo:
+ appargs(arg)
+ mywith(wo.group(1), False)
+ continue
+ wv = re.match(r'with-(.*)=(.*)', arg, re.I)
+ if wv:
+ appargs(arg)
+ if wv.group(2).lower() == "no":
+ mywith(wv.group(1), False)
+ continue
+ mywith(wv.group(1), True, wv.group(2))
+ continue
+ wi = re.match(r'with-(.*)', arg, re.I)
+ if wi:
+ appargs(arg)
+ mywith(wi.group(1), True)
+ continue
+ if arg.lower() == "clean":
+ want_clean = True
+ continue
+ want_unknown = True
+ unknown_value = arg
+ break
+
+ # debug
+ if enable_debug:
+ if debug_botan_path is None:
+ debug_botan_path = botan_path + "_d"
+ if debug_openssl_path is None:
+ debug_openssl_path = openssl_path + "_d"
+
+def appargs(arg):
+ """append seen arguments to configargs"""
+ global configargs
+ # escape backslashes, spaces and double quotes
+ escaped = ""
+
+ for x in arg:
+ if (x == "\\") or (x == " ") or (x == "\""):
+ escaped += "\\"
+ escaped += x
+ if configargs:
+ configargs += " " + escaped
+ else:
+ configargs = escaped
+
+def myenable(key, val):
+ """parse enable/disable"""
+ global platform
+ global enable_debug
+ global enable_ecc
+ global enable_gost
+ global enable_static_runtime
+ global enable_non_paged
+ global enable_keep
+ global verbose
+ global want_unknown
+ global unknown_value
+ if key.lower() == "64bit":
+ if val:
+ platform = 64
+ return
+ if key.lower() == "debug":
+ if not val:
+ enable_debug = False
+ return
+ if key.lower() == "ecc":
+ if not val:
+ enable_ecc = False
+ return
+ if key.lower() == "gost":
+ if not val:
+ enable_gost = False
+ return
+ if key.lower() == "static-runtime":
+ if val:
+ enable_static_runtime = True
+ return
+ if key.lower() == "non-paged-memory":
+ if not val:
+ enable_non_paged = False
+ return
+ if key.lower() == "keep":
+ if val:
+ enable_keep = True
+ return
+ if key.lower() == "verbose":
+ if val:
+ verbose = True
+ return
+ want_unknown = True
+ if not val:
+ unknown_value = "disable-" + key
+ else:
+ unknown_value = "enable-" + key
+
+def mywith(key, val, detail=None):
+ """parse with/without"""
+ global crypto_backend
+ global botan_path
+ global debug_botan_path
+ global openssl_path
+ global debug_openssl_path
+ global want_tests
+ global cppunit_path
+ global want_unknown
+ global unknown_value
+ global toolset
+
+ if key.lower() == "crypto-backend":
+ if val and (detail.lower() == "openssl"):
+ crypto_backend = "openssl"
+ return
+ if val and (detail.lower() == "botan"):
+ crypto_backend = "botan"
+ return
+ want_unknown = True
+ unknown_value = "with-crypto-backend=" + detail
+ return
+ if key.lower() == "botan":
+ if not val:
+ want_unknown = True
+ unknown_value = "without-botan doesn't make sense"
+ return
+ if detail.lower() != "yes":
+ botan_path = detail
+ return
+ if key.lower() == "debug-botan":
+ if not val:
+ want_unknown = True
+ unknown_value = "without-debug-botan doesn't make sense"
+ return
+ if detail.lower() != "yes":
+ debug_botan_path = detail
+ return
+ if key.lower() == "openssl":
+ if not val:
+ want_unknown = True
+ unknown_value = "without-openssl doesn't make sense"
+ return
+ if detail.lower() != "yes":
+ openssl_path = detail
+ return
+ if key.lower() == "debug-openssl":
+ if not val:
+ want_unknown = True
+ unknown_value = "without-debug-openssl doesn't make sense"
+ return
+ if detail.lower() != "yes":
+ debug_openssl_path = detail
+ return
+ if key.lower() == "cppunit":
+ if not val:
+ want_tests = False
+ return
+ if detail.lower() != "yes":
+ cppunit_path = detail
+ return
+ if key.lower() == "toolset":
+ if not val:
+ want_tests = False
+ return
+ if detail:
+ toolset=detail.lower()
+ return
+ want_unknown = True
+ if not val:
+ unknown_value = "without-" + key
+ else:
+ unknown_value = "with-" + key
+
+def dohelp():
+ """help"""
+ for line in myhelp:
+ print(line)
+ sys.exit(1)
+
+def docleantest():
+ """clean test files"""
+ for basename in testlist:
+ filename = "test" + basename + ".c"
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ filename = "test" + basename + ".cpp"
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ filename = "test" + basename + ".obj"
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ filename = "test" + basename + ".exe"
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ if os.path.isfile("botan.dll"):
+ os.unlink("botan.dll")
+ if os.path.isfile("libeay32.dll"):
+ os.unlink("libeay32.dll")
+ if os.path.isfile("libeaycompat32.dll"):
+ os.unlink("libeaycompat32.dll")
+ if os.path.isfile("libcrypto-1_1.dll"):
+ os.unlink("libcrypto-1_1.dll")
+ if os.path.isfile("libcrypto-1_1-x64.dll"):
+ os.unlink("libcrypto-1_1-x64.dll")
+
+def doclean():
+ """clean"""
+ docleantest()
+ for filename in filelist:
+ if os.path.isfile(filename):
+ os.unlink(filename)
+ sys.exit(0)
+
+def dounknown():
+ """parsing error"""
+ print("can't parse " + unknown_value + "", file=sys.stderr)
+ sys.exit(1)
+
+def doconfig():
+ """config itself"""
+ global botan_path
+ global debug_botan_path
+ global openssl_path
+ global debug_openssl_path
+ global cppunit_path
+
+ # configure the platform
+ if platform == 32:
+ varvals["PLATFORM"] = "Win32"
+ else:
+ varvals["PLATFORM"] = "x64"
+ varvals["PLATFORMDIR"] = "x64\\"
+
+ # configure the runtime library
+ if enable_static_runtime:
+ varvals["RUNTIMELIBRARY"] = "MultiThreaded"
+ else:
+ varvals["RUNTIMELIBRARY"] = "MultiThreadedDLL"
+
+ # configure ECC and GOST
+ if enable_ecc:
+ condvals["ECC"] = True
+ if enable_gost:
+ condvals["GOST"] = True
+
+ # configure the crypto
+ if crypto_backend == "botan":
+ condvals["BOTAN"] = True
+ varvals["LIBNAME"] = "botan.lib"
+ botan_path = os.path.abspath(botan_path)
+ botan_inc = os.path.join(botan_path, "include")
+ botan_dll = ""
+ if os.path.exists(os.path.join(botan_inc, "botan-2\\botan\\init.h")):
+ varvals["INCLUDEPATH"] = os.path.join(botan_inc, "botan-2")
+ elif os.path.exists(os.path.join(botan_inc, "botan-1.11\\botan\\init.h")):
+ varvals["INCLUDEPATH"] = os.path.join(botan_inc, "botan-1.11")
+ elif os.path.exists(os.path.join(botan_inc, "botan\\init.h")):
+ varvals["INCLUDEPATH"] = botan_inc
+ else:
+ print("can't find Botan includes", file=sys.stderr)
+ sys.exit(1)
+ if os.path.exists(os.path.join(botan_path, "lib\\botan.lib")):
+ varvals["LIBPATH"] = os.path.join(botan_path, "lib")
+ botan_dll = os.path.join(botan_path, "lib\\botan.dll")
+ elif os.path.exists(os.path.join(botan_path, "botan.lib")):
+ varvals["LIBPATH"] = botan_path
+ botan_dll = os.path.join(botan_path, "botan.dll")
+ else:
+ print("can't find Botan library", file=sys.stderr)
+ sys.exit(1)
+ varvals["DLLPATH"] = botan_dll
+ if enable_debug:
+ debug_botan_path = os.path.abspath(debug_botan_path)
+ debug_botan_inc = os.path.join(debug_botan_path, "include")
+ debug_botan_dll = ""
+ if os.path.exists(os.path.join(debug_botan_inc, "botan-2\\botan\\init.h")):
+ varvals["DEBUGINCPATH"] = os.path.join(debug_botan_inc, "botan-2")
+ elif os.path.exists(os.path.join(debug_botan_inc, "botan-1.11\\botan\\init.h")):
+ varvals["DEBUGINCPATH"] = os.path.join(debug_botan_inc, "botan-1.11")
+ elif os.path.exists(os.path.join(debug_botan_inc, "botan\\init.h")):
+ varvals["DEBUGINCPATH"] = debug_botan_inc
+ else:
+ print("can't find debug Botan includes", file=sys.stderr)
+ sys.exit(1)
+ if os.path.exists(os.path.join(debug_botan_path, "lib\\botan.lib")):
+ varvals["DEBUGLIBPATH"] = os.path.join(debug_botan_path, "lib")
+ debug_botan_dll = os.path.join(debug_botan_path, "lib\\botan.dll")
+ if os.path.exists(os.path.join(debug_botan_path, "botan.lib")):
+ varvals["DEBUGLIBPATH"] = debug_botan_path
+ debug_botan_dll = os.path.join(debug_botan_path, "botan.dll")
+ else:
+ print("can't find debug Botan library", file=sys.stderr)
+ sys.exit(1)
+ varvals["DEBUGDLLPATH"] = debug_botan_dll
+ else:
+ varvals["DEBUGDLLPATH"] = varvals["DLLPATH"]
+ varvals["DEBUGINCPATH"] = varvals["INCLUDEPATH"]
+ varvals["DEBUGLIBPATH"] = varvals["LIBPATH"]
+
+ # Botan version
+ if verbose:
+ print("checking Botan version")
+ botan_version_major = 0
+ botan_version_minor = 0
+ system_libs = []
+ if os.path.exists(botan_dll):
+ subprocess.call(["copy", botan_dll, "."], shell=True)
+ else:
+ system_libs = ["user32.lib", "advapi32.lib"]
+ inc = varvals["INCLUDEPATH"]
+ lib = os.path.join(varvals["LIBPATH"], "botan.lib")
+ testfile = open("testbotan.cpp", "w")
+ print('\
+#include <botan/version.h>\n\
+int main() {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0)\n\
+ return 3;\n\
+#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)\n\
+ return 2;\n\
+#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)\n\
+ return 1;\n\
+#else\n\
+ return 0;\n\
+#endif\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testbotan.cpp", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testbotan.exe"):
+ print("can't create .\\testbotan.exe", file=sys.stderr)
+ sys.exit(1)
+ ret = subprocess.call(".\\testbotan.exe")
+ if ret == 0:
+ print("Botan version too old", file=sys.stderr)
+ sys.exit(1)
+ elif ret == 1:
+ botan_version_major = 1
+ botan_version_minor = 10
+ elif ret == 2:
+ botan_version_major = 1
+ botan_version_minor = 11
+ print("Botan version 1.11 not yet supported", file=sys.stderr)
+ sys.exit(1)
+ elif ret == 3:
+ botan_version_major = 2
+ botan_version_minor = 0
+ print("Botan version 2.0 not yet supported", file=sys.stderr)
+ sys.exit(1)
+ else:
+ print("Botan test failed", file=sys.stderr)
+ sys.exit(1)
+
+ # Botan ECC support
+ if enable_ecc:
+ if verbose:
+ print("checking Botan ECC support")
+ testfile = open("testecc.cpp", "w")
+ print('\
+#include <botan/init.h>\n\
+#include <botan/ec_group.h>\n\
+#include <botan/oids.h>\n\
+#include <botan/version.h>\n\
+int main() {\n\
+ Botan::LibraryInitializer::initialize();\n\
+ const std::string name("secp256r1");\n\
+ const Botan::OID oid(Botan::OIDS::lookup(name));\n\
+ const Botan::EC_Group ecg(oid);\n\
+ try {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)\n\
+ const std::vector<Botan::byte> der =\n\
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);\n\
+#else\n\
+ const Botan::SecureVector<Botan::byte> der =\n\
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);\n\
+#endif\n\
+ } catch(...) {\n\
+ return 1;\n\
+ }\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testecc.cpp", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testecc.exe"):
+ print("can't create .\\testecc.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testecc.exe") != 0:
+ print("can't find P256: upgrade to Botan >= 1.10.6", file=sys.stderr)
+ sys.exit(1)
+
+ # Botan GOST support
+ if enable_gost:
+ if verbose:
+ print("checking Botan GOST support")
+ testfile = open("testgost.cpp", "w")
+ print('\
+#include <botan/init.h>\n\
+#include <botan/gost_3410.h>\n\
+#include <botan/oids.h>\n\
+#include <botan/version.h>\n\
+int main() {\n\
+ Botan::LibraryInitializer::initialize();\n\
+ const std::string name("gost_256A");\n\
+ const Botan::OID oid(Botan::OIDS::lookup(name));\n\
+ const Botan::EC_Group ecg(oid);\n\
+ try {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)\n\
+ const std::vector<Botan::byte> der =\n\
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);\n\
+#else\n\
+ const Botan::SecureVector<Botan::byte> der =\n\
+ ecg.DER_encode(Botan::EC_DOMPAR_ENC_OID);\n\
+#endif\n\
+ } catch(...) {\n\
+ return 1;\n\
+ }\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testgost.cpp", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testgost.exe"):
+ print("can't create .\\testgost.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testgost.exe") != 0:
+ print("can't find GOST: upgrade to Botan >= 1.10.6", file=sys.stderr)
+ sys.exit(1)
+
+ # no check for Botan RFC3394 support
+ condvals["RFC3394"] = True
+
+ # Botan RFC5649 support
+ if verbose:
+ print("checking Botan RFC5649 support")
+ testfile = open("testrfc5649.cpp", "w")
+ print('\
+#include <botan/botan.h>\n\
+#include <botan/rfc3394.h>\n\
+#include <botan/version.h>\n\
+using namespace Botan;\n\
+int main() {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)\n\
+ secure_vector<byte> key(10);\n\
+ SymmetricKey kek("AABB");\n\
+ secure_vector<byte> x = rfc5649_keywrap(key, kek);\n\
+#else\n\
+ SecureVector<byte> key(10);\n\
+ SymmetricKey kek("AABB");\n\
+ Algorithm_Factory& af = global_state().algorithm_factory();\n\
+ SecureVector<byte> x = rfc5649_keywrap(key, kek, af);\n\
+#endif\n\
+ return 1;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/EHsc","/I", inc, "testrfc5649.cpp", lib]
+ command.extend(system_libs)
+ subprocess.call(command)
+ if os.path.exists(".\\testrfc5649.exe"):
+ if verbose:
+ print("Found AES key wrap with pad")
+ condvals["RFC5649"] = True
+ else:
+ if verbose:
+ print("can't compile Botan AES key wrap with pad")
+
+ # Botan GNU MP support
+ if botan_version_major == 1 and botan_version_minor == 10:
+ if verbose:
+ print("checking Botan GNU MP support")
+ testfile = open("testgnump.cpp", "w")
+ print('\
+#include <botan/build.h>\n\
+int main() {\n\
+#ifndef BOTAN_HAS_ENGINE_GNU_MP\n\
+#error "No GNU MP support";\n\
+#endif\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testgnump.cpp", lib]
+ command.extend(system_libs)
+ subprocess.call(command)
+ if os.path.exists(".\\testgnump.exe"):
+ if verbose:
+ print("Botan GNU MP is supported")
+ else:
+ if verbose:
+ print("Botan GNU MP is not supported")
+
+ # Botan raw PSS support
+ if verbose:
+ print("checking Botan raw PSS support")
+ testfile = open("testrawpss.cpp", "w")
+ print('\
+#include <botan/botan.h>\n\
+#include <botan/version.h>\n\
+int main() {\n\
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,3,0)\n\
+ return 0;\n\
+#endif\n\
+ return 1;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testrawpss.cpp", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testrawpss.exe"):
+ if verbose:
+ print("can't create .\\testrawpss.exe", file=sys.stderr)
+ else:
+ if subprocess.call(".\\testrawpss.exe") != 0:
+ if verbose:
+ print("can't find raw PSS: upgrade to Botan >= 2.3.0", file=sys.stderr)
+ else:
+ condvals["RAWPSS"] = True
+
+ else:
+
+ condvals["OPENSSL"] = True
+ varvals["EXTRALIBS"] = "crypt32.lib;ws2_32.lib;"
+ openssl_path = os.path.abspath(openssl_path)
+ openssl_inc = os.path.join(openssl_path, "include")
+ if not os.path.exists(os.path.join(openssl_inc, "openssl\\ssl.h")):
+ print("can't find OpenSSL headers", file=sys.stderr)
+ sys.exit(1)
+ varvals["INCLUDEPATH"] = openssl_inc
+ openssl_lib = os.path.join(openssl_path, "lib")
+ openssl_lib_name = ""
+ openssl_lib_dll = ""
+ if os.path.exists(os.path.join(openssl_lib, "libeay32.lib")):
+ openssl_lib_name = "libeay32.lib"
+ openssl_lib_dll = "bin\\libeay32.dll"
+ elif os.path.exists(os.path.join(openssl_lib, "libeaycompat32.lib")):
+ openssl_lib_name = "libeaycompat32.lib"
+ openssl_lib_dll = "bin\\libeaycompat32.dll"
+ elif os.path.exists(os.path.join(openssl_lib, "libcrypto.lib")):
+ openssl_lib_name = "libcrypto.lib"
+ if platform == 32:
+ openssl_lib_dll = "bin\\libcrypto-1_1.dll"
+ else:
+ openssl_lib_dll = "bin\\libcrypto-1_1-x64.dll"
+
+ else:
+ print("can't find OpenSSL library", file=sys.stderr)
+ sys.exit(1)
+ openssl_dll = os.path.join(openssl_path,openssl_lib_dll)
+ varvals["LIBPATH"] = openssl_lib
+ varvals["LIBNAME"] = openssl_lib_name
+ varvals["DLLPATH"] = openssl_dll
+ if enable_debug:
+ debug_openssl_path = os.path.abspath(debug_openssl_path)
+ varvals["DEBUGDLLPATH"] = \
+ os.path.join(debug_openssl_path, openssl_lib_dll)
+ debug_openssl_inc = os.path.join(debug_openssl_path, "include")
+ if not os.path.exists(os.path.join(debug_openssl_inc,
+ "openssl\\ssl.h")):
+ print("can't find debug OpenSSL headers", file=sys.stderr)
+ sys.exit(1)
+ varvals["DEBUGINCPATH"] = debug_openssl_inc
+ debug_openssl_lib = os.path.join(debug_openssl_path, "lib")
+ if not os.path.exists(os.path.join(debug_openssl_lib,
+ openssl_lib_name)):
+ print("can't find debug OpenSSL library", file=sys.stderr)
+ sys.exit(1)
+ varvals["DEBUGLIBPATH"] = debug_openssl_lib
+ else:
+ varvals["DEBUGDLLPATH"] = varvals["DLLPATH"]
+ varvals["DEBUGINCPATH"] = varvals["INCLUDEPATH"]
+ varvals["DEBUGLIBPATH"] = varvals["LIBPATH"]
+
+ # OpenSSL support
+ if verbose:
+ print("checking OpenSSL")
+ system_libs = []
+ if os.path.exists(openssl_dll):
+ subprocess.call(["copy", openssl_dll, "."], shell=True)
+ else:
+ system_libs = ["user32.lib", "advapi32.lib", "gdi32.lib", "crypt32.lib", "ws2_32.lib"]
+ inc = openssl_inc
+ lib = os.path.join(openssl_lib, openssl_lib_name)
+ testfile = open("testossl.c", "w")
+ print('\
+#include <openssl/err.h>\n\
+int main() {\n\
+ ERR_clear_error();\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testossl.c", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testossl.exe"):
+ print("can't create .\\testossl.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testossl.exe") != 0:
+ print("OpenSSL test failed", file=sys.stderr)
+ sys.exit(1)
+
+ # OpenSSL version
+ if verbose:
+ print("checking OpenSSL version")
+ testfile = open("testosslv.c", "w")
+ print('\
+#include <openssl/ssl.h>\n\
+#include <openssl/opensslv.h>\n\
+int main() {\n\
+#ifndef OPENSSL_VERSION_NUMBER\n\
+ return -1;\n\
+#endif\n\
+#if OPENSSL_VERSION_NUMBER >= 0x010000000L\n\
+ return 0;\n\
+#else\n\
+ return 1;\n\
+#endif\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testosslv.c", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testosslv.exe"):
+ print("can't create .\\testosslv.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testosslv.exe") != 0:
+ print("OpenSLL version too old (1.0.0 or later required)", file=sys.stderr)
+ sys.exit(1)
+
+ # OpenSSL ECC support
+ if enable_ecc:
+ if verbose:
+ print("checking OpenSSL ECC support")
+ testfile = open("testecc.c", "w")
+ print('\
+#include <openssl/ecdsa.h>\n\
+#include <openssl/objects.h>\n\
+int main() {\n\
+ EC_KEY *ec256, *ec384, *ec521;\n\
+ ec256 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);\n\
+ ec384 = EC_KEY_new_by_curve_name(NID_secp384r1);\n\
+ ec521 = EC_KEY_new_by_curve_name(NID_secp521r1);\n\
+ if (ec256 == NULL || ec384 == NULL || ec521 == NULL)\n\
+ return 1;\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testecc.c", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testecc.exe"):
+ print("can't create .\\testecc.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testecc.exe") != 0:
+ print("can't find P256, P384, or P521: no ECC support", file=sys.stderr)
+ sys.exit(1)
+
+ # OpenSSL GOST support
+ if enable_gost:
+ if verbose:
+ print("checking OpenSSL GOST support")
+ testfile = open("testgost.c", "w")
+ print('\
+#include <openssl/conf.h>\n\
+#include <openssl/engine.h>\n\
+#include <openssl/crypto.h>\n\
+#include <openssl/opensslv.h>\n\
+int main() {\n\
+ ENGINE *eg;\n\
+ const EVP_MD* EVP_GOST_34_11;\n\
+ OpenSSL_add_all_algorithms();\n\
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)\n\
+ ENGINE_load_builtin_engines();\n\
+#else\n\
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN | OPENSSL_INIT_LOAD_CONFIG, NULL);\n\
+#endif\n\
+ eg = ENGINE_by_id("gost");\n\
+ if (eg == NULL)\n\
+ return 1;\n\
+ if (ENGINE_init(eg) <= 0)\n\
+ return 1;\n\
+ EVP_GOST_34_11 = ENGINE_get_digest(eg, NID_id_GostR3411_94);\n\
+ if (EVP_GOST_34_11 == NULL)\n\
+ return 1;\n\
+ if (ENGINE_register_pkey_asn1_meths(eg) <= 0)\n\
+ return 1;\n\
+ if (ENGINE_ctrl_cmd_string(eg, "CRYPT_PARAMS",\n\
+ "id-Gost28147-89-CryptoPro-A-ParamSet", 0) <= 0)\n\
+ return 1;\n\
+ return 0;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testgost.c", lib]
+ command.extend(system_libs)
+ subprocess.check_output(command, stderr=subprocess.STDOUT)
+ if not os.path.exists(".\\testgost.exe"):
+ print("can't create .\\testgost.exe", file=sys.stderr)
+ sys.exit(1)
+ if subprocess.call(".\\testgost.exe") != 0:
+ print("can't find GOST: no GOST support", file=sys.stderr)
+ sys.exit(1)
+
+ # OpenSSL EVP interface for AES key wrapping (aka RFC 3394)
+ if verbose:
+ print("checking OpenSSL EVP interface for AES key wrapping")
+ testfile = open("testrfc3394.c", "w")
+ print('\
+#include <openssl/evp.h>\n\
+int main() {\n\
+ EVP_aes_128_wrap();\n\
+ return 1;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testrfc3394.c", lib]
+ command.extend(system_libs)
+ subprocess.call(command)
+ if os.path.exists(".\\testrfc3394.exe"):
+ if verbose:
+ print("RFC 3394 is supported")
+ condvals["RFC3394"] = True
+ else:
+ if verbose:
+ print("can't compile OpenSSL RFC 3394")
+
+ # OpenSSL EVP interface for AES key wrap with pad (aka RFC 5649)
+ if verbose:
+ print("checking OpenSSL EVP interface for AES key wrapping with pad")
+ testfile = open("testrfc5649.c", "w")
+ print('\
+#include <openssl/evp.h>\n\
+int main() {\n\
+ EVP_aes_128_wrap_pad();\n\
+ return 1;\n\
+}', file=testfile)
+ testfile.close()
+ command = ["cl", "/nologo", "/MD", "/I", inc, "testrfc5649.c", lib]
+ command.extend(system_libs)
+ subprocess.call(command)
+ if os.path.exists(".\\testrfc5649.exe"):
+ if verbose:
+ print("RFC 5649 is supported")
+ condvals["RFC5649"] = True
+ else:
+ if verbose:
+ print("can't compile OpenSSL RFC 5649")
+
+ # no check for OpenSSL raw PSS support
+ condvals["RAWPSS"] = True
+ # no check for OpenSSL AES GCM
+ condvals["AESGCM"] = True
+
+ # configure CppUnit
+ if want_tests:
+ condvals["TESTS"] = True
+ cppunit_path = os.path.abspath(cppunit_path)
+ cppunit_inc = os.path.join(cppunit_path, "include")
+ if not os.path.exists(os.path.join(cppunit_inc, "cppunit\\Test.h")):
+ print("can't find CppUnit headers", file=sys.stderr)
+ sys.exit(1)
+ varvals["CUINCPATH"] = cppunit_inc
+ cppunit_lib = os.path.join(cppunit_path, "lib")
+ if not os.path.exists(os.path.join(cppunit_lib, "cppunit.lib")):
+ cppunit_lib = cppunit_path
+ if not os.path.exists(os.path.join(cppunit_lib, "cppunit.lib")):
+ print("can't find CppUnit library", file=sys.stderr)
+ sys.exit(1)
+ if enable_debug:
+ if not os.path.exists(os.path.join(cppunit_lib, "cppunitd.lib")):
+ print("can't find debug CppUnit library", file=sys.stderr)
+ sys.exit(1)
+ varvals["CULIBPATH"] = cppunit_lib
+
+ # misc
+ if enable_non_paged:
+ condvals["NONPAGE"] = True
+
+def kw(path):
+ """escape spaces"""
+ if re.search(r' ', path):
+ return '"' + path + '"'
+ else:
+ return path
+
+def setupfile(filename):
+ """setup files with condition stacks and variable expansions"""
+ cond = "@@@"
+ conds = []
+ passing = True
+ passes = []
+ filein = open(filename + ".in", "r")
+ fileout = open(filename, "w")
+
+ for line in filein:
+ line = line.rstrip("\r\n")
+ cif = re.match(r'@IF (.*)', line)
+ if cif:
+ conds.append(cond)
+ passes.append(passing)
+ cond = cif.group(1)
+ if condvals.get(cond):
+ # do nothing
+ pass
+ else:
+ passing = False
+ continue
+ celse = re.match(r'@ELSE (.*)', line)
+ if celse:
+ if cond != celse.group(1):
+ raise SyntaxError("@ELSE " + celse.group(1) +
+ " mismatch in " + filename)
+ if condvals.get(cond):
+ passing = False
+ else:
+ if len(passes) > 0:
+ passing = passes[-1]
+ else:
+ passing = True
+ continue
+ cend = re.match(r'@END (.*)', line)
+ if cend:
+ if cond != cend.group(1):
+ raise SyntaxError("@END " + cend.group(1) +
+ " mismatch in " + filename)
+ cond = conds.pop()
+ if len(passes) > 0:
+ passing = passes.pop()
+ else:
+ passing = True
+ continue
+ if not passing:
+ continue
+ while True:
+ vm = re.match(r'([^@]*)@([^@ ]*)@(.*)', line)
+ if vm:
+ if vm.group(2) in varnames:
+ if varvals.get(vm.group(2)):
+ val = kw(varvals[vm.group(2)])
+ else:
+ val = ""
+ line = vm.group(1) + val + vm.group(3)
+ continue
+ else:
+ raise SyntaxError("unknown control @" + vm.group(2) +
+ "@ in " + filename)
+ break
+ print(line, file=fileout)
+ if verbose:
+ print("Setting up " + filename)
+ filein.close()
+ fileout.close()
+
+def main(args):
+ """run it"""
+
+ # no arguments -> usage
+ if len(args) <= 1:
+ for line in usage:
+ print(line)
+ sys.exit(1)
+
+ parseargs(args[1:])
+
+ if want_help:
+ dohelp()
+ if want_clean:
+ doclean()
+ if want_unknown:
+ dounknown()
+ if not toolset:
+ dodetectvisualstudio()
+ if not toolset:
+ print("Build skipped. To build, this file needs to run from VS command prompt.")
+ sys.exit(1)
+
+ varvals["PLATFORMTOOLSET"] = toolset
+
+ # status before config
+ if verbose:
+ if enable_keep:
+ print("keep: enabled")
+ else:
+ print("keep: disabled")
+ if platform == 64:
+ print("64bit: enabled")
+ else:
+ print("64bit: disabled")
+ if enable_debug:
+ print("debug: enabled")
+ else:
+ print("debug: disabled")
+ if enable_ecc:
+ print("ecc: enabled")
+ else:
+ print("ecc: disabled")
+ if enable_gost:
+ print("gost: enabled")
+ else:
+ print("gost: disabled")
+ if enable_non_paged:
+ print("non-paged-memory: enabled")
+ else:
+ print("non-paged-memory: disabled")
+ print("crypto-backend: " + crypto_backend)
+ if crypto_backend == "botan":
+ print("botan-path: " + botan_path)
+ if enable_debug:
+ print("debug-botan-path: " + debug_botan_path)
+ else:
+ print("openssl-path: " + openssl_path)
+ if enable_debug:
+ print("debug-openssl-path: " + debug_openssl_path)
+ if want_tests:
+ print("cppunit-path: " + cppunit_path)
+ print("toolset: "+toolset)
+
+
+ doconfig()
+
+ # status after config
+ if verbose:
+ print("Configuration Status")
+ print("\tconditions:")
+ for name in condnames:
+ if condvals.get(name):
+ print("\t\t" + name + " is true")
+ else:
+ print("\t\t" + name + " is false")
+ print("\tsubstitutions:")
+ for name in varnames:
+ if varvals.get(name):
+ print("\t\t" + name + '-> "' + varvals[name] + '"')
+ print()
+
+ for filename in filelist:
+ setupfile(filename)
+
+ # clean test file
+ if not enable_keep:
+ docleantest()
+
+ print("Configured.")
+ sys.exit(0)
+
+main(sys.argv)
+
+# Notes: Unix configure.ac options
+# --enable-64bit supported
+# --enable-ecc supported
+# --enable-gost supported
+# --enable-non-paged-memory supported
+# --enable-visibility (enforced by DLLs)
+# --with-crypto-backend supported
+# --with-botan supported (Release and Debug)
+# --with-openssl supported (Release and Debug)
+# --with-migrate (useless as SoftHSMv1 is not supported)
+# --with-objectstore-backend-db (TODO)
+# --with-sqlite3 (useless until objectstore backend can be chosen)
diff --git a/SoftHSMv2/win32/config.h.in b/SoftHSMv2/win32/config.h.in
new file mode 100644
index 0000000..f2b56ba
--- /dev/null
+++ b/SoftHSMv2/win32/config.h.in
@@ -0,0 +1,185 @@
+/* config.h for WIN32 */
+
+/* The default log level */
+#define DEFAULT_LOG_LEVEL "INFO"
+
+/* Default storage backend for token objects */
+#define DEFAULT_OBJECTSTORE_BACKEND "file"
+
+/* The default PKCS#11 library */
+#define DEFAULT_PKCS11_LIB "softhsm2.dll"
+
+/* The default location of softhsm2.conf */
+#define DEFAULT_SOFTHSM2_CONF "softhsm2.conf"
+
+/* The default location of the token directory */
+#define DEFAULT_TOKENDIR "tokens"
+
+/* Define if advanced AES key wrap without pad is supported */
+@IF RFC3394
+#define HAVE_AES_KEY_WRAP 1
+@ELSE RFC3394
+#undef HAVE_AES_KEY_WRAP
+@END RFC3394
+
+/* Define if advanced AES key wrap with pad is supported */
+@IF RFC5649
+#define HAVE_AES_KEY_WRAP_PAD 1
+@ELSE RFC5649
+#undef HAVE_AES_KEY_WRAP_PAD
+@END RFC5649
+
+/* Whether LoadLibrary is available */
+#define HAVE_LOADLIBRARY 1
+
+/* Define to 1 if you have the <sqlite3.h> header file. */
+#undef HAVE_SQLITE3_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Maximum PIN length */
+#define MAX_PIN_LEN 255
+
+/* Minimum PIN length */
+#define MIN_PIN_LEN 4
+
+/* Name of package */
+#define PACKAGE "softhsm"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "SoftHSM"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "SoftHSM 2.3.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "softhsm"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.3.0"
+
+/* Non-paged memory for secure storage */
+@IF NONPAGE
+#define SENSITIVE_NON_PAGE 1
+@ELSE NONPAGE
+#undef SENSITIVE_NON_PAGE
+@END NONPAGE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#define VERSION "2.3.0"
+
+/* SoftHSM major version number via PKCS#11 */
+#define VERSION_MAJOR 2
+
+/* SoftHSM minor version number via PKCS#11 */
+#define VERSION_MINOR 3
+
+/* Compile with Botan support */
+@IF BOTAN
+#define WITH_BOTAN 1
+@ELSE BOTAN
+#undef WITH_BOTAN
+@END BOTAN
+
+/* Compile with ECC support */
+@IF ECC
+#define WITH_ECC 1
+@ELSE ECC
+#undef WITH_ECC
+@END ECC
+
+/* Compile with GOST support */
+@IF GOST
+#define WITH_GOST 1
+@ELSE GOST
+#undef WITH_GOST
+@END GOST
+
+/* Compile with OpenSSL support */
+@IF OPENSSL
+#define WITH_OPENSSL 1
+@ELSE OPENSSL
+#undef WITH_OPENSSL
+@END OPENSSL
+
+/* Compile with raw PSS support */
+@IF RAWPSS
+#define WITH_RAW_PSS 1
+@ELSE RAWPSS
+#undef WITH_RAW_PSS
+@END RAWPSS
+
+/* Compile with AES GCM support */
+@IF AESGCM
+#define WITH_AES_GCM 1
+@ELSE AESGCM
+#undef WITH_AES_GCM
+@END AESGCM
+
+/* Define to 1 if you have getpassphrase(). */
+#define HAVE_GETPASSPHRASE
+
+/* Addition things */
+
+char *getpassphrase(const char *prompt);
+int setenv(const char *name, const char *value, int overwrite);
+
+/* At least Vista */
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
+
+#if _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+
+/* Prevent inclusion of winsock.h in windows.h */
+
+#define WIN32_LEAN_AND_MEAN 1
+
+#include <windows.h>
+
+/* avoid collision from min and max macros */
+
+#undef min
+#undef max
+
+@IF BOTAN
+/* For Botan */
+
+#pragma warning(disable: 4275 4267)
+@END BOTAN
+
+/* Temporary for debug */
+
+#undef DEBUG_LOG_STDERR
+// #define DEBUG_LOG_STDERR 1
+
+/* To avoid unsafe warnings (off) */
+
+// #pragma warning(disable: 4996)
diff --git a/SoftHSMv2/win32/convarch/convarch.vcxproj.filters.in b/SoftHSMv2/win32/convarch/convarch.vcxproj.filters.in
new file mode 100644
index 0000000..d3c84f1
--- /dev/null
+++ b/SoftHSMv2/win32/convarch/convarch.vcxproj.filters.in
@@ -0,0 +1,928 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Common Header Files">
+ <UniqueIdentifier>{b657b1af-4cc4-4d97-ba6a-0a7231c5f243}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Common Source Files">
+ <UniqueIdentifier>{aacfc93a-d2e0-4935-aa15-ea0d3690fbcd}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Crypto Header Files">
+ <UniqueIdentifier>{6337c51f-53e3-440a-9ab9-40f0b9a4f26e}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Crypto Source Files">
+ <UniqueIdentifier>{8566a5d1-d688-41da-bbc3-3d860f2db764}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Data Mgr Header Files">
+ <UniqueIdentifier>{b427db7b-49c3-47b0-982a-7da01cf39c8e}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Data Mgr Source Files">
+ <UniqueIdentifier>{04a46825-a433-4b5c-9c3f-8c489978cb8a}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Handle Mgr Header Files">
+ <UniqueIdentifier>{9e67afe5-3252-4c46-a24f-096e4a35e174}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Handle Mgr Source Files">
+ <UniqueIdentifier>{b8a7e894-ebbe-43de-ad66-3c45d91aac8e}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Object Store Header Files">
+ <UniqueIdentifier>{0c47956d-aa5e-4c26-bee4-63ec89c0ab64}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Object Store Source Files">
+ <UniqueIdentifier>{45c69303-5073-4bde-8b63-2f2e2a688362}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Session Mgr Header Files">
+ <UniqueIdentifier>{d1a8b25d-8ebb-4a79-ae8c-70ef3c0bed5f}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Session Mgr Source Files">
+ <UniqueIdentifier>{cb379241-3d4b-4f7c-b7d1-c6c83d3a1b62}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Slot Mgr Header Files">
+ <UniqueIdentifier>{5420eba7-6b85-4daf-a916-c85421362984}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Slot Mgr Source Files">
+ <UniqueIdentifier>{3c9f55a5-d1a8-4716-a416-ec172a676e63}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Win32 Source Files">
+ <UniqueIdentifier>{63e3d8a2-0853-4f98-bcaa-de05da380d37}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Win32 Header Files">
+ <UniqueIdentifier>{59b2221a-36a3-4f2c-9883-6173599baf5a}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\common\Configuration.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\common\fatal.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\common\HandleFactory.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\common\log.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\common\MutexFactory.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\common\osmutex.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\common\Serialisable.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\common\SimpleConfigLoader.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\AESKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\AsymmetricAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\AsymmetricKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\AsymmetricParameters.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+@IF BOTAN
+ <ClInclude Include="..\..\src\lib\crypto\BotanAES.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanCryptoFactory.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDES.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDH.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDHKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDHPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDHPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDSA.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDSAKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDSAPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDH.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDHKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDHPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDHPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDSA.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDSAKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDSAPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDSAPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOST.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOSTKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOSTPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOSTPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOSTR3411.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanHashAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanMAC.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanMacAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanMD5.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanRNG.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanDSAPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanRSA.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanRSAKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanRSAPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanRSAPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA1.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA224.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA256.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA384.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA512.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanSymmetricAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\BotanUtil.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\Botan_ecb.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\Botan_rounding.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+@END BOTAN
+ <ClInclude Include="..\..\src\lib\crypto\CryptoFactory.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\DESKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\DHParameters.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\DHPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\DHPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\DSAParameters.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\DSAPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\DSAPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\ECParameters.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\ECPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\ECPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\GOSTPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\GOSTPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\HashAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\MacAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\odd.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+@IF OPENSSL
+ <ClInclude Include="..\..\src\lib\crypto\OSSLAES.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLComp.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLCryptoFactory.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDES.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDH.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDHKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDHPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDSAPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDHPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDSA.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDSAKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDSAPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECDH.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECDSA.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLEVPHashAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLEVPCMacAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLEVPMacAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLEVPSymmetricAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOST.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOSTKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOSTPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOSTPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOSTR3411.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLCMAC.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLHMAC.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLMD5.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRNG.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRSA.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRSAKeyPair.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRSAPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRSAPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA1.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA224.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA256.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA384.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA512.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLUtil.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+@END OPENSSL
+ <ClInclude Include="..\..\src\lib\crypto\PrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\PublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\RNG.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\RSAParameters.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\RSAPrivateKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\RSAPublicKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\SymmetricAlgorithm.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\SymmetricKey.h">
+ <Filter>Crypto Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\ByteString.h">
+ <Filter>Data Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\RFC4880.h">
+ <Filter>Data Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\salloc.h">
+ <Filter>Data Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\SecureAllocator.h">
+ <Filter>Data Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\SecureMemoryRegistry.h">
+ <Filter>Data Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\SecureDataManager.h">
+ <Filter>Data Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\handle_mgr\Handle.h">
+ <Filter>Handle Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\handle_mgr\HandleManager.h">
+ <Filter>Handle Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\Directory.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\File.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\FindOperation.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\Generation.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\ObjectFile.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\ObjectStore.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\ObjectStoreToken.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\OSAttribute.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\OSAttributes.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\OSObject.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\OSPathSep.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\OSToken.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\SessionObject.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\SessionObjectStore.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\UUID.h">
+ <Filter>Object Store Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\session_mgr\Session.h">
+ <Filter>Session Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\session_mgr\SessionManager.h">
+ <Filter>Session Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\slot_mgr\Slot.h">
+ <Filter>Slot Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\slot_mgr\SlotManager.h">
+ <Filter>Slot Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\slot_mgr\Token.h">
+ <Filter>Slot Mgr Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\win32\syslog.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\common\Configuration.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\common\fatal.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\common\log.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\common\MutexFactory.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\common\osmutex.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\common\SimpleConfigLoader.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\AsymmetricAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\AsymmetricKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+@IF BOTAN
+ <ClCompile Include="..\..\src\lib\crypto\BotanAES.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanCryptoFactory.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDES.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDH.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDHKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDHPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDHPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDSA.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDSAKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDSAPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanDSAPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDH.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDHKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDHPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDHPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDSA.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDSAKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDSAPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDSAPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOST.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOSTKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOSTPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOSTPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOSTR3411.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanHashAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanMAC.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanMacAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanMD5.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanRNG.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanRSA.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanRSAKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanRSAPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanRSAPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA1.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA224.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA256.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA384.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA512.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanSymmetricAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\BotanUtil.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\Botan_ecb.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+@END BOTAN
+ <ClCompile Include="..\..\src\lib\crypto\CryptoFactory.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\DESKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\DHParameters.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\DHPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\DHPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\DSAParameters.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\DSAPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\DSAPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\ECParameters.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\ECPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\ECPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\GOSTPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\GOSTPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\HashAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\MacAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+@IF OPENSSL
+ <ClCompile Include="..\..\src\lib\crypto\OSSLAES.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLComp.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLCryptoFactory.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDES.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDH.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDHKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDHPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDHPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDSA.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDSAKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDSAPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDSAPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECDH.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECDSA.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLEVPHashAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLEVPCMacAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLEVPMacAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLEVPSymmetricAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOST.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOSTKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOSTPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOSTPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOSTR3411.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLCMAC.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLHMAC.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLMD5.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRNG.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRSA.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRSAKeyPair.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRSAPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRSAPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA1.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA224.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA256.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA384.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA512.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLUtil.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+@END OPENSSL
+ <ClCompile Include="..\..\src\lib\crypto\RSAParameters.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\RSAPrivateKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\RSAPublicKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\SymmetricAlgorithm.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\SymmetricKey.cpp">
+ <Filter>Crypto Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\data_mgr\ByteString.cpp">
+ <Filter>Data Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\data_mgr\RFC4880.cpp">
+ <Filter>Data Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\data_mgr\salloc.cpp">
+ <Filter>Data Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\data_mgr\SecureDataManager.cpp">
+ <Filter>Data Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\data_mgr\SecureMemoryRegistry.cpp">
+ <Filter>Data Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\handle_mgr\Handle.cpp">
+ <Filter>Handle Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\handle_mgr\HandleManager.cpp">
+ <Filter>Handle Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\Directory.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\File.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\FindOperation.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\Generation.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\ObjectFile.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\ObjectStore.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\ObjectStoreToken.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\OSAttribute.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\OSToken.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\SessionObject.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\SessionObjectStore.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\UUID.cpp">
+ <Filter>Object Store Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\session_mgr\Session.cpp">
+ <Filter>Session Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\session_mgr\SessionManager.cpp">
+ <Filter>Session Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\slot_mgr\Slot.cpp">
+ <Filter>Slot Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\slot_mgr\SlotManager.cpp">
+ <Filter>Slot Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\slot_mgr\Token.cpp">
+ <Filter>Slot Mgr Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\win32\syslog.cpp">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/convarch/convarch.vcxproj.in b/SoftHSMv2/win32/convarch/convarch.vcxproj.in
new file mode 100644
index 0000000..b711f35
--- /dev/null
+++ b/SoftHSMv2/win32/convarch/convarch.vcxproj.in
@@ -0,0 +1,374 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\common\Configuration.h" />
+ <ClInclude Include="..\..\src\lib\common\fatal.h" />
+ <ClInclude Include="..\..\src\lib\common\HandleFactory.h" />
+ <ClInclude Include="..\..\src\lib\common\log.h" />
+ <ClInclude Include="..\..\src\lib\common\MutexFactory.h" />
+ <ClInclude Include="..\..\src\lib\common\osmutex.h" />
+ <ClInclude Include="..\..\src\lib\common\Serialisable.h" />
+ <ClInclude Include="..\..\src\lib\common\SimpleConfigLoader.h" />
+ <ClInclude Include="..\..\src\lib\crypto\AESKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\AsymmetricAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\AsymmetricKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\AsymmetricParameters.h" />
+@IF BOTAN
+ <ClInclude Include="..\..\src\lib\crypto\BotanAES.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanCryptoFactory.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDES.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDH.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDHKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDHPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDHPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDSA.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDSAKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDSAPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanDSAPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDH.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDHKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDHPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDHPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDSA.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDSAKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDSAPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanECDSAPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOST.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOSTKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOSTPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOSTPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanGOSTR3411.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanHashAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanMAC.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanMacAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanMD5.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanRNG.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanRSA.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanRSAKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanRSAPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanRSAPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA1.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA224.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA256.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA384.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanSHA512.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanSymmetricAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\BotanUtil.h" />
+ <ClInclude Include="..\..\src\lib\crypto\Botan_ecb.h" />
+ <ClInclude Include="..\..\src\lib\crypto\Botan_rounding.h" />
+@END BOTAN
+ <ClInclude Include="..\..\src\lib\crypto\CryptoFactory.h" />
+ <ClInclude Include="..\..\src\lib\crypto\DESKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\DHParameters.h" />
+ <ClInclude Include="..\..\src\lib\crypto\DHPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\DHPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\DSAParameters.h" />
+ <ClInclude Include="..\..\src\lib\crypto\DSAPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\DSAPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\ECParameters.h" />
+ <ClInclude Include="..\..\src\lib\crypto\ECPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\ECPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\GOSTPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\GOSTPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\HashAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\MacAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\odd.h" />
+@IF OPENSSL
+ <ClInclude Include="..\..\src\lib\crypto\OSSLAES.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLComp.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLCryptoFactory.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDES.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDH.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDHKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDHPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDHPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDSA.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDSAKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDSAPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLDSAPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECDH.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECDSA.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLECPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLEVPHashAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLEVPCMacAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLEVPMacAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLEVPSymmetricAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOST.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOSTKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOSTPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOSTPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLGOSTR3411.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLCMAC.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLHMAC.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLMD5.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRNG.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRSA.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRSAKeyPair.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRSAPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLRSAPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA1.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA224.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA256.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA384.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLSHA512.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLUtil.h" />
+@END OPENSSL
+ <ClInclude Include="..\..\src\lib\crypto\PrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\PublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\RNG.h" />
+ <ClInclude Include="..\..\src\lib\crypto\RSAParameters.h" />
+ <ClInclude Include="..\..\src\lib\crypto\RSAPrivateKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\RSAPublicKey.h" />
+ <ClInclude Include="..\..\src\lib\crypto\SymmetricAlgorithm.h" />
+ <ClInclude Include="..\..\src\lib\crypto\SymmetricKey.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\ByteString.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\RFC4880.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\salloc.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\SecureAllocator.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\SecureDataManager.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\SecureMemoryRegistry.h" />
+ <ClInclude Include="..\..\src\lib\handle_mgr\Handle.h" />
+ <ClInclude Include="..\..\src\lib\handle_mgr\HandleManager.h" />
+ <ClInclude Include="..\..\src\lib\object_store\Directory.h" />
+ <ClInclude Include="..\..\src\lib\object_store\File.h" />
+ <ClInclude Include="..\..\src\lib\object_store\FindOperation.h" />
+ <ClInclude Include="..\..\src\lib\object_store\Generation.h" />
+ <ClInclude Include="..\..\src\lib\object_store\ObjectFile.h" />
+ <ClInclude Include="..\..\src\lib\object_store\ObjectStore.h" />
+ <ClInclude Include="..\..\src\lib\object_store\ObjectStoreToken.h" />
+ <ClInclude Include="..\..\src\lib\object_store\OSAttribute.h" />
+ <ClInclude Include="..\..\src\lib\object_store\OSAttributes.h" />
+ <ClInclude Include="..\..\src\lib\object_store\OSObject.h" />
+ <ClInclude Include="..\..\src\lib\object_store\OSPathSep.h" />
+ <ClInclude Include="..\..\src\lib\object_store\OSToken.h" />
+ <ClInclude Include="..\..\src\lib\object_store\SessionObject.h" />
+ <ClInclude Include="..\..\src\lib\object_store\SessionObjectStore.h" />
+ <ClInclude Include="..\..\src\lib\object_store\UUID.h" />
+ <ClInclude Include="..\..\src\lib\session_mgr\Session.h" />
+ <ClInclude Include="..\..\src\lib\session_mgr\SessionManager.h" />
+ <ClInclude Include="..\..\src\lib\slot_mgr\Slot.h" />
+ <ClInclude Include="..\..\src\lib\slot_mgr\SlotManager.h" />
+ <ClInclude Include="..\..\src\lib\slot_mgr\Token.h" />
+ <ClInclude Include="..\..\src\lib\win32\syslog.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\common\Configuration.cpp" />
+ <ClCompile Include="..\..\src\lib\common\fatal.cpp" />
+ <ClCompile Include="..\..\src\lib\common\log.cpp" />
+ <ClCompile Include="..\..\src\lib\common\MutexFactory.cpp" />
+ <ClCompile Include="..\..\src\lib\common\osmutex.cpp" />
+ <ClCompile Include="..\..\src\lib\common\SimpleConfigLoader.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\AESKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\AsymmetricAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\AsymmetricKeyPair.cpp" />
+@IF BOTAN
+ <ClCompile Include="..\..\src\lib\crypto\BotanAES.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanCryptoFactory.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDES.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDH.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDHKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDHPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDHPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDSA.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDSAKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDSAPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanDSAPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDH.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDHKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDHPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDHPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDSA.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDSAKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDSAPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanECDSAPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOST.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOSTKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOSTPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOSTPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanGOSTR3411.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanHashAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanMAC.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanMacAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanMD5.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanRNG.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanRSA.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanRSAKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanRSAPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanRSAPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA1.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA224.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA256.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA384.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanSHA512.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanSymmetricAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\BotanUtil.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\Botan_ecb.cpp" />
+@END BOTAN
+ <ClCompile Include="..\..\src\lib\crypto\CryptoFactory.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\DESKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\DHParameters.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\DHPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\DHPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\DSAParameters.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\DSAPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\DSAPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\ECParameters.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\ECPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\ECPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\GOSTPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\GOSTPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\HashAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\MacAlgorithm.cpp" />
+@IF OPENSSL
+ <ClCompile Include="..\..\src\lib\crypto\OSSLAES.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLComp.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLCryptoFactory.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDES.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDH.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDHKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDHPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDHPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDSA.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDSAKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDSAPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLDSAPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECDH.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECDSA.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLECPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLEVPHashAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLEVPCMacAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLEVPMacAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLEVPSymmetricAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOST.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOSTKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOSTPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOSTPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLGOSTR3411.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLCMAC.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLHMAC.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLMD5.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRNG.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRSA.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRSAKeyPair.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRSAPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLRSAPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA1.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA224.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA256.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA384.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLSHA512.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLUtil.cpp" />
+@END OPENSSL
+ <ClCompile Include="..\..\src\lib\crypto\RSAParameters.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\RSAPrivateKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\RSAPublicKey.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\SymmetricAlgorithm.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\SymmetricKey.cpp" />
+ <ClCompile Include="..\..\src\lib\data_mgr\ByteString.cpp" />
+ <ClCompile Include="..\..\src\lib\data_mgr\RFC4880.cpp" />
+ <ClCompile Include="..\..\src\lib\data_mgr\salloc.cpp" />
+ <ClCompile Include="..\..\src\lib\data_mgr\SecureDataManager.cpp" />
+ <ClCompile Include="..\..\src\lib\data_mgr\SecureMemoryRegistry.cpp" />
+ <ClCompile Include="..\..\src\lib\handle_mgr\Handle.cpp" />
+ <ClCompile Include="..\..\src\lib\handle_mgr\HandleManager.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\Directory.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\File.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\FindOperation.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\Generation.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\ObjectFile.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\ObjectStore.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\ObjectStoreToken.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\OSAttribute.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\OSToken.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\SessionObject.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\SessionObjectStore.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\UUID.cpp" />
+ <ClCompile Include="..\..\src\lib\session_mgr\Session.cpp" />
+ <ClCompile Include="..\..\src\lib\session_mgr\SessionManager.cpp" />
+ <ClCompile Include="..\..\src\lib\slot_mgr\Slot.cpp" />
+ <ClCompile Include="..\..\src\lib\slot_mgr\SlotManager.cpp" />
+ <ClCompile Include="..\..\src\lib\slot_mgr\Token.cpp" />
+ <ClCompile Include="..\..\src\lib\win32\syslog.cpp" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F64541B6-FFBF-4368-B93A-A5CA8ADAD795}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>convarch</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\pkcs11;..\..\src\lib\common;..\..\src\lib\object_store;..\..\src\lib\slot_mgr;..\..\src\lib\session_mgr;..\..\src\lib\handle_mgr;..\..\src\lib\crypto;..\..\src\lib\win32;..\..\src\lib\data_mgr;@DEBUGINCPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\pkcs11;..\..\src\lib\common;..\..\src\lib\object_store;..\..\src\lib\slot_mgr;..\..\src\lib\session_mgr;..\..\src\lib\handle_mgr;..\..\src\lib\crypto;..\..\src\lib\win32;..\..\src\lib\data_mgr;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/convarch/convarch.vcxproj.user b/SoftHSMv2/win32/convarch/convarch.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/convarch/convarch.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.filters b/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.filters
new file mode 100644
index 0000000..9aee71d
--- /dev/null
+++ b/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.filters
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\crypto\test\DHTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\DSATests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\ECDHTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\ECDSATests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\ent.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\GOSTTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\iso8859.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\randtest.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\RNGTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\RSATests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\AESTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\DESTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\HashTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\test\MacTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\crypto\test\chisq.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\cryptotest.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\DHTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\DSATests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\ECDHTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\ECDSATests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\ent.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\GOSTTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\iso8859.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\randtest.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\RNGTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\RSATests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\AESTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\DESTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\HashTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\test\MacTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.in b/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.in
new file mode 100644
index 0000000..010b890
--- /dev/null
+++ b/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.in
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{07E03E0B-C525-4A72-88C6-2238896A4D8C}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>cryptotest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\crypto;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\data_mgr;..\..\src\lib\object_store;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\win32;@CUINCPATH@;@DEBUGINCPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunitd.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\crypto;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\data_mgr;..\..\src\lib\object_store;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunit.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\AESTests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\DESTests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\DHTests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\DSATests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\ECDHTests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\ECDSATests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\ent.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\GOSTTests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\HashTests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\iso8859.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\MacTests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\randtest.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\RNGTests.h" />
+ <ClInclude Include="..\..\src\lib\crypto\test\RSATests.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\crypto\test\AESTests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\chisq.c" />
+ <ClCompile Include="..\..\src\lib\crypto\test\cryptotest.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\DESTests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\DHTests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\DSATests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\ECDHTests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\ECDSATests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\ent.c" />
+ <ClCompile Include="..\..\src\lib\crypto\test\GOSTTests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\HashTests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\iso8859.c" />
+ <ClCompile Include="..\..\src\lib\crypto\test\MacTests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\randtest.c" />
+ <ClCompile Include="..\..\src\lib\crypto\test\RNGTests.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\test\RSATests.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.user b/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/cryptotest/cryptotest.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.filters b/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.filters
new file mode 100644
index 0000000..645ba69
--- /dev/null
+++ b/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.filters
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\test\ByteStringTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\test\RFC4880Tests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\data_mgr\test\SecureDataMgrTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\data_mgr\test\ByteStringTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\data_mgr\test\datamgrtest.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\data_mgr\test\RFC4880Tests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\data_mgr\test\SecureDataMgrTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.in b/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.in
new file mode 100644
index 0000000..0251af3
--- /dev/null
+++ b/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.in
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E20315B5-B49E-46D7-B7EC-1A439F347C95}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>datamgrtest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\data_mgr;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\object_store;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunitd.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\data_mgr;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\object_store;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunit.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\test\ByteStringTests.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\test\RFC4880Tests.h" />
+ <ClInclude Include="..\..\src\lib\data_mgr\test\SecureDataMgrTests.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\data_mgr\test\ByteStringTests.cpp" />
+ <ClCompile Include="..\..\src\lib\data_mgr\test\datamgrtest.cpp" />
+ <ClCompile Include="..\..\src\lib\data_mgr\test\RFC4880Tests.cpp" />
+ <ClCompile Include="..\..\src\lib\data_mgr\test\SecureDataMgrTests.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.user b/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/datamgrtest/datamgrtest.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/dump/dump.vcxproj.filters b/SoftHSMv2/win32/dump/dump.vcxproj.filters
new file mode 100644
index 0000000..c4546a6
--- /dev/null
+++ b/SoftHSMv2/win32/dump/dump.vcxproj.filters
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\bin\dump\common.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\bin\dump\tables.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\bin\dump\softhsm2-dump-file.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/dump/dump.vcxproj.in b/SoftHSMv2/win32/dump/dump.vcxproj.in
new file mode 100644
index 0000000..2521562
--- /dev/null
+++ b/SoftHSMv2/win32/dump/dump.vcxproj.in
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F60ACB12-7D05-4A89-B2D1-DD16E1F3566B}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>dump</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <TargetName>softhsm2-dump-file</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <TargetName>softhsm2-dump-file</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib\pkcs11;..\..\src\lib\object_store;..\..\src\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib\pkcs11;..\..\src\lib\object_store;..\..\src\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\bin\dump\common.h" />
+ <ClInclude Include="..\..\src\bin\dump\tables.h" />
+ <ClInclude Include="..\config.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\bin\dump\softhsm2-dump-file.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/dump/dump.vcxproj.user b/SoftHSMv2/win32/dump/dump.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/dump/dump.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.filters b/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.filters
new file mode 100644
index 0000000..38ddc83
--- /dev/null
+++ b/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.filters
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\handle_mgr\test\HandleManagerTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\handle_mgr\test\HandleManagerTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\handle_mgr\test\handlemgrtest.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.in b/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.in
new file mode 100644
index 0000000..ddc9add
--- /dev/null
+++ b/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.in
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{014B1E10-EC68-4BEC-B992-F92CA2B6816F}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>handlemgrtest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\handle_mgr;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\object_store;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\data_mgr;..\..\src\lib\win32;@CUINCPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunitd.lib;@LIBNAME@;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\handle_mgr;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\object_store;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\data_mgr;..\..\src\lib\win32;@CUINCPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunit.lib;@LIBNAME@;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ <ClInclude Include="..\..\src\lib\handle_mgr\test\HandleManagerTests.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\handle_mgr\test\HandleManagerTests.cpp" />
+ <ClCompile Include="..\..\src\lib\handle_mgr\test\handlemgrtest.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.user b/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/handlemgrtest/handlemgrtest.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/keyconv/keyconv.vcxproj.filters.in b/SoftHSMv2/win32/keyconv/keyconv.vcxproj.filters.in
new file mode 100644
index 0000000..bd6ce41
--- /dev/null
+++ b/SoftHSMv2/win32/keyconv/keyconv.vcxproj.filters.in
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Common Header Files">
+ <UniqueIdentifier>{6f8944db-01c2-47c3-a4b4-265d91e99ba0}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Common Source Files">
+ <UniqueIdentifier>{b6a2e68c-2518-456b-8592-561c011e0390}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Win32 Source Files">
+ <UniqueIdentifier>{14914ba7-3ec3-4f58-a83a-4596a7f52075}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Win32 Header Files">
+ <UniqueIdentifier>{3253c2c0-ca7a-4902-8b31-87ab6c4c754f}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\bin\common\getpw.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\bin\common\library.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\bin\keyconv\softhsm2-keyconv.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+@IF OPENSSL
+ <ClInclude Include="..\..\src\lib\crypto\OSSLComp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+@END OPENSSL
+ <ClInclude Include="..\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\bin\win32\getopt.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\bin\keyconv\softhsm2-keyconv.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+@IF BOTAN
+ <ClCompile Include="..\..\src\bin\keyconv\softhsm2-keyconv-botan.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+@END BOTAN
+@IF OPENSSL
+ <ClCompile Include="..\..\src\bin\keyconv\softhsm2-keyconv-ossl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLComp.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+@END OPENSSL
+ <ClCompile Include="..\..\src\bin\common\getpw.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\common\library.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\keyconv\base64.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\win32\getopt.cpp">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\win32\getpassphase.cpp">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/keyconv/keyconv.vcxproj.in b/SoftHSMv2/win32/keyconv/keyconv.vcxproj.in
new file mode 100644
index 0000000..87c1b5e
--- /dev/null
+++ b/SoftHSMv2/win32/keyconv/keyconv.vcxproj.in
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9B003E52-F02A-47EA-9942-2D9AE8738161}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>keyconv</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <TargetName>softhsm2-keyconv</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <TargetName>softhsm2-keyconv</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\bin\common;..\..\src\bin\win32;..\..\src\lib\pkcs11;..\..\src\lib\crypto;@DEBUGINCPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\bin\common;..\..\src\bin\win32;..\..\src\lib\pkcs11;..\..\src\lib\crypto;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\bin\common\getpw.h" />
+ <ClInclude Include="..\..\src\bin\common\library.h" />
+ <ClInclude Include="..\..\src\bin\keyconv\softhsm2-keyconv.h" />
+@IF OPENSSL
+ <ClInclude Include="..\..\src\lib\crypto\OSSLComp.h" />
+@END OPENSSL
+ <ClInclude Include="..\..\src\bin\win32\getopt.h" />
+ <ClInclude Include="..\config.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\bin\common\getpw.cpp" />
+ <ClCompile Include="..\..\src\bin\common\library.cpp" />
+ <ClCompile Include="..\..\src\bin\keyconv\base64.c" />
+@IF BOTAN
+ <ClCompile Include="..\..\src\bin\keyconv\softhsm2-keyconv-botan.cpp" />
+@END BOTAN
+@IF OPENSSL
+ <ClCompile Include="..\..\src\bin\keyconv\softhsm2-keyconv-ossl.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLComp.cpp" />
+@END OPENSSL
+ <ClCompile Include="..\..\src\bin\keyconv\softhsm2-keyconv.cpp" />
+ <ClCompile Include="..\..\src\bin\win32\getopt.cpp" />
+ <ClCompile Include="..\..\src\bin\win32\getpassphase.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/keyconv/keyconv.vcxproj.user b/SoftHSMv2/win32/keyconv/keyconv.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/keyconv/keyconv.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.filters b/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.filters
new file mode 100644
index 0000000..11d8d84
--- /dev/null
+++ b/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.filters
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\test\DirectoryTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\test\FileTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\test\ObjectFileTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\test\ObjectStoreTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\test\OSTokenTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\test\SessionObjectStoreTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\test\SessionObjectTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\object_store\test\UUIDTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\object_store\test\DirectoryTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\test\FileTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\test\ObjectFileTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\test\ObjectStoreTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\test\OSTokenTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\test\objstoretest.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\test\SessionObjectStoreTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\test\SessionObjectTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\object_store\test\UUIDTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.in b/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.in
new file mode 100644
index 0000000..d26e7cb
--- /dev/null
+++ b/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.in
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{44F77533-A4A1-4175-8C4C-07106B3F9C08}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>objstoretest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\object_store;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\data_mgr;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunitd.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\object_store;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\data_mgr;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunit.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ <ClInclude Include="..\..\src\lib\object_store\test\DirectoryTests.h" />
+ <ClInclude Include="..\..\src\lib\object_store\test\FileTests.h" />
+ <ClInclude Include="..\..\src\lib\object_store\test\ObjectFileTests.h" />
+ <ClInclude Include="..\..\src\lib\object_store\test\ObjectStoreTests.h" />
+ <ClInclude Include="..\..\src\lib\object_store\test\OSTokenTests.h" />
+ <ClInclude Include="..\..\src\lib\object_store\test\SessionObjectStoreTests.h" />
+ <ClInclude Include="..\..\src\lib\object_store\test\SessionObjectTests.h" />
+ <ClInclude Include="..\..\src\lib\object_store\test\UUIDTests.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\object_store\test\DirectoryTests.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\test\FileTests.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\test\ObjectFileTests.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\test\ObjectStoreTests.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\test\objstoretest.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\test\OSTokenTests.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\test\SessionObjectStoreTests.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\test\SessionObjectTests.cpp" />
+ <ClCompile Include="..\..\src\lib\object_store\test\UUIDTests.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.user b/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/objstoretest/objstoretest.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/p11test/p11test.vcxproj.filters b/SoftHSMv2/win32/p11test/p11test.vcxproj.filters
new file mode 100644
index 0000000..fa7e86f
--- /dev/null
+++ b/SoftHSMv2/win32/p11test/p11test.vcxproj.filters
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Lib Header Files">
+ <UniqueIdentifier>{8440d7eb-5530-4f5e-a355-a43435742c60}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Lib Source Files">
+ <UniqueIdentifier>{3c33d54e-4bd1-43e0-bcc7-0d6adcfd5dc7}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Other Header Files">
+ <UniqueIdentifier>{ff435d2e-c67a-4f47-9731-28d88617e559}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Other Source Files">
+ <UniqueIdentifier>{5df8b0a3-ecc7-4876-aea2-8421c0846535}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\test\AsymEncryptDecryptTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\AsymWrapUnwrapTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\DeriveTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\DigestTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\InfoTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\InitTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\ObjectTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\RandomTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\SessionTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\SignVerifyTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\SymmetricAlgorithmTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\TestsBase.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\TestsNoPINInitBase.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\TokenTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\test\UserTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\common\osmutex.h">
+ <Filter>Other Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\win32\setenv.h">
+ <Filter>Other Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\access.h">
+ <Filter>Lib Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Lib Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Other Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Other Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Other Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\P11Attributes.h">
+ <Filter>Lib Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\P11Objects.h">
+ <Filter>Lib Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\SoftHSM.h">
+ <Filter>Lib Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\test\AsymEncryptDecryptTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\AsymWrapUnwrapTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\DeriveTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\DigestTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\InfoTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\InitTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\ObjectTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\RandomTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\SessionTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\SignVerifyTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\SymmetricAlgorithmTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\TestsBase.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\TestsNoPINInitBase.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\TokenTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\UserTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\common\osmutex.cpp">
+ <Filter>Other Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\win32\setenv.cpp">
+ <Filter>Other Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\access.cpp">
+ <Filter>Lib Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\main.cpp">
+ <Filter>Lib Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\P11Attributes.cpp">
+ <Filter>Lib Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\P11Objects.cpp">
+ <Filter>Lib Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\SoftHSM.cpp">
+ <Filter>Lib Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\test\p11test.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/p11test/p11test.vcxproj.in b/SoftHSMv2/win32/p11test/p11test.vcxproj.in
new file mode 100644
index 0000000..c8a493c
--- /dev/null
+++ b/SoftHSMv2/win32/p11test/p11test.vcxproj.in
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{7C5EE7FC-B5FC-47BF-8164-A452FE689472}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>p11test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\test;..\..\src\lib\pkcs11;..\..\src\lib\common;..\..\src\lib\crypto;..\..\src\lib\object_store;..\..\src\lib\data_mgr;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\handle_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunitd.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+copy ..\..\src\lib\test\softhsm2.conf.win32 "$(TargetDir)\softhsm2.conf"
+copy ..\..\src\lib\test\softhsm2-alt.conf.win32 "$(TargetDir)\softhsm2-alt.conf"
+mkdir "$(TargetDir)\tokens" 2&gt; nul
+copy ..\..\src\lib\test\tokens\dummy.in "$(TargetDir)\tokens\dummy"
+ </Command>
+ <Message>Copying dummy test files to Debug folder</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\test;..\..\src\lib\pkcs11;..\..\src\lib\common;..\..\src\lib\crypto;..\..\src\lib\object_store;..\..\src\lib\data_mgr;..\..\src\lib\session_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\handle_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunit.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+copy ..\..\src\lib\test\softhsm2.conf.win32 "$(TargetDir)\softhsm2.conf"
+copy ..\..\src\lib\test\softhsm2-alt.conf.win32 "$(TargetDir)\softhsm2-alt.conf"
+mkdir "$(TargetDir)\tokens" 2&gt; nul
+copy ..\..\src\lib\test\tokens\dummy.in "$(TargetDir)\tokens\dummy"
+ </Command>
+ <Message>Copying dummy test files to Release folder</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\access.h" />
+ <ClInclude Include="..\..\src\lib\common\osmutex.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ <ClInclude Include="..\..\src\lib\P11Attributes.h" />
+ <ClInclude Include="..\..\src\lib\P11Objects.h" />
+ <ClInclude Include="..\..\src\lib\SoftHSM.h" />
+ <ClInclude Include="..\..\src\lib\test\AsymEncryptDecryptTests.h" />
+ <ClInclude Include="..\..\src\lib\test\AsymWrapUnwrapTests.h" />
+ <ClInclude Include="..\..\src\lib\test\DeriveTests.h" />
+ <ClInclude Include="..\..\src\lib\test\DigestTests.h" />
+ <ClInclude Include="..\..\src\lib\test\InfoTests.h" />
+ <ClInclude Include="..\..\src\lib\test\InitTests.h" />
+ <ClInclude Include="..\..\src\lib\test\ObjectTests.h" />
+ <ClInclude Include="..\..\src\lib\test\RandomTests.h" />
+ <ClInclude Include="..\..\src\lib\test\SessionTests.h" />
+ <ClInclude Include="..\..\src\lib\test\SignVerifyTests.h" />
+ <ClInclude Include="..\..\src\lib\test\SymmetricAlgorithmTests.h" />
+ <ClInclude Include="..\..\src\lib\test\TestsBase.h" />
+ <ClInclude Include="..\..\src\lib\test\TestsNoPINInitBase.h" />
+ <ClInclude Include="..\..\src\lib\test\TokenTests.h" />
+ <ClInclude Include="..\..\src\lib\test\UserTests.h" />
+ <ClInclude Include="..\..\src\lib\win32\setenv.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\access.cpp" />
+ <ClCompile Include="..\..\src\lib\common\osmutex.cpp" />
+ <ClCompile Include="..\..\src\lib\main.cpp" />
+ <ClCompile Include="..\..\src\lib\P11Attributes.cpp" />
+ <ClCompile Include="..\..\src\lib\P11Objects.cpp" />
+ <ClCompile Include="..\..\src\lib\SoftHSM.cpp" />
+ <ClCompile Include="..\..\src\lib\test\AsymEncryptDecryptTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\AsymWrapUnwrapTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\DeriveTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\DigestTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\InfoTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\InitTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\ObjectTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\p11test.cpp" />
+ <ClCompile Include="..\..\src\lib\test\RandomTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\SessionTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\SignVerifyTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\SymmetricAlgorithmTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\TestsBase.cpp" />
+ <ClCompile Include="..\..\src\lib\test\TestsNoPINInitBase.cpp" />
+ <ClCompile Include="..\..\src\lib\test\TokenTests.cpp" />
+ <ClCompile Include="..\..\src\lib\test\UserTests.cpp" />
+ <ClCompile Include="..\..\src\lib\win32\setenv.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/p11test/p11test.vcxproj.user b/SoftHSMv2/win32/p11test/p11test.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/p11test/p11test.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.filters b/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.filters
new file mode 100644
index 0000000..dbfb705
--- /dev/null
+++ b/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.filters
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\session_mgr\test\SessionManagerTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\session_mgr\test\SessionManagerTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\session_mgr\test\sessionmgrtest.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.in b/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.in
new file mode 100644
index 0000000..572c9c3
--- /dev/null
+++ b/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.in
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{45E2ABF6-91A7-4AA5-A82B-0C8E54BCCCB9}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>sessionmgrtest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\session_mgr;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\data_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\object_store;..\..\src\lib\win32;@CUINCPATH@;@DEBUGINCPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunitd.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\session_mgr;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\data_mgr;..\..\src\lib\slot_mgr;..\..\src\lib\object_store;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunit.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ <ClInclude Include="..\..\src\lib\session_mgr\test\SessionManagerTests.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\session_mgr\test\SessionManagerTests.cpp" />
+ <ClCompile Include="..\..\src\lib\session_mgr\test\sessionmgrtest.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.user b/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/sessionmgrtest/sessionmgrtest.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.filters b/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.filters
new file mode 100644
index 0000000..7ddbae5
--- /dev/null
+++ b/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.filters
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\slot_mgr\test\SlotManagerTests.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\slot_mgr\test\SlotManagerTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\slot_mgr\test\slotmgrtest.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.in b/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.in
new file mode 100644
index 0000000..ea52e3b
--- /dev/null
+++ b/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.in
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F62E31E5-0F8D-4B70-8F26-44AFA1A9E645}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>slotmgrtest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\slot_mgr;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\object_store;..\..\src\lib\session_mgr;..\..\src\lib\data_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunitd.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\slot_mgr;..\..\src\lib\common;..\..\src\lib\pkcs11;..\..\src\lib\crypto;..\..\src\lib\object_store;..\..\src\lib\session_mgr;..\..\src\lib\data_mgr;..\..\src\lib\win32;@CUINCPATH@;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@CULIBPATH@;@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;cppunit.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ <ClInclude Include="..\..\src\lib\slot_mgr\test\SlotManagerTests.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\slot_mgr\test\SlotManagerTests.cpp" />
+ <ClCompile Include="..\..\src\lib\slot_mgr\test\slotmgrtest.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.user b/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/slotmgrtest/slotmgrtest.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/softhsm2.sln.in b/SoftHSMv2/win32/softhsm2.sln.in
new file mode 100644
index 0000000..4d98c0d
--- /dev/null
+++ b/SoftHSMv2/win32/softhsm2.sln.in
@@ -0,0 +1,117 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "softhsm2", "softhsm2\softhsm2.vcxproj", "{801F5AB2-7A62-4085-B129-D15E2D717219}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795} = {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "convarch", "convarch\convarch.vcxproj", "{F64541B6-FFBF-4368-B93A-A5CA8ADAD795}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "keyconv", "keyconv\keyconv.vcxproj", "{9B003E52-F02A-47EA-9942-2D9AE8738161}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "util", "util\util.vcxproj", "{05901466-4184-47C8-9D6C-3BB99BBF5378}"
+ ProjectSection(ProjectDependencies) = postProject
+ {801F5AB2-7A62-4085-B129-D15E2D717219} = {801F5AB2-7A62-4085-B129-D15E2D717219}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dump", "dump\dump.vcxproj", "{F60ACB12-7D05-4A89-B2D1-DD16E1F3566B}"
+EndProject
+@IF TESTS
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "p11test", "p11test\p11test.vcxproj", "{7C5EE7FC-B5FC-47BF-8164-A452FE689472}"
+ ProjectSection(ProjectDependencies) = postProject
+ {801F5AB2-7A62-4085-B129-D15E2D717219} = {801F5AB2-7A62-4085-B129-D15E2D717219}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryptotest", "cryptotest\cryptotest.vcxproj", "{07E03E0B-C525-4A72-88C6-2238896A4D8C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795} = {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "datamgrtest", "datamgrtest\datamgrtest.vcxproj", "{E20315B5-B49E-46D7-B7EC-1A439F347C95}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795} = {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "handlemgrtest", "handlemgrtest\handlemgrtest.vcxproj", "{014B1E10-EC68-4BEC-B992-F92CA2B6816F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795} = {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "objstoretest", "objstoretest\objstoretest.vcxproj", "{44F77533-A4A1-4175-8C4C-07106B3F9C08}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795} = {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sessionmgrtest", "sessionmgrtest\sessionmgrtest.vcxproj", "{45E2ABF6-91A7-4AA5-A82B-0C8E54BCCCB9}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795} = {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slotmgrtest", "slotmgrtest\slotmgrtest.vcxproj", "{F62E31E5-0F8D-4B70-8F26-44AFA1A9E645}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795} = {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}
+ EndProjectSection
+EndProject
+@END TESTS
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|@PLATFORM@ = Debug|@PLATFORM@
+ Release|@PLATFORM@ = Release|@PLATFORM@
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {801F5AB2-7A62-4085-B129-D15E2D717219}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {801F5AB2-7A62-4085-B129-D15E2D717219}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {801F5AB2-7A62-4085-B129-D15E2D717219}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {801F5AB2-7A62-4085-B129-D15E2D717219}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {F64541B6-FFBF-4368-B93A-A5CA8ADAD795}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {9B003E52-F02A-47EA-9942-2D9AE8738161}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {9B003E52-F02A-47EA-9942-2D9AE8738161}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {9B003E52-F02A-47EA-9942-2D9AE8738161}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {9B003E52-F02A-47EA-9942-2D9AE8738161}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {05901466-4184-47C8-9D6C-3BB99BBF5378}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {05901466-4184-47C8-9D6C-3BB99BBF5378}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {05901466-4184-47C8-9D6C-3BB99BBF5378}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {05901466-4184-47C8-9D6C-3BB99BBF5378}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {F60ACB12-7D05-4A89-B2D1-DD16E1F3566B}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {F60ACB12-7D05-4A89-B2D1-DD16E1F3566B}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {F60ACB12-7D05-4A89-B2D1-DD16E1F3566B}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {F60ACB12-7D05-4A89-B2D1-DD16E1F3566B}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+@IF TESTS
+ {7C5EE7FC-B5FC-47BF-8164-A452FE689472}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {7C5EE7FC-B5FC-47BF-8164-A452FE689472}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {7C5EE7FC-B5FC-47BF-8164-A452FE689472}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {7C5EE7FC-B5FC-47BF-8164-A452FE689472}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {07E03E0B-C525-4A72-88C6-2238896A4D8C}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {07E03E0B-C525-4A72-88C6-2238896A4D8C}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {07E03E0B-C525-4A72-88C6-2238896A4D8C}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {07E03E0B-C525-4A72-88C6-2238896A4D8C}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {E20315B5-B49E-46D7-B7EC-1A439F347C95}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {E20315B5-B49E-46D7-B7EC-1A439F347C95}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {E20315B5-B49E-46D7-B7EC-1A439F347C95}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {E20315B5-B49E-46D7-B7EC-1A439F347C95}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {014B1E10-EC68-4BEC-B992-F92CA2B6816F}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {014B1E10-EC68-4BEC-B992-F92CA2B6816F}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {014B1E10-EC68-4BEC-B992-F92CA2B6816F}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {014B1E10-EC68-4BEC-B992-F92CA2B6816F}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {44F77533-A4A1-4175-8C4C-07106B3F9C08}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {44F77533-A4A1-4175-8C4C-07106B3F9C08}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {44F77533-A4A1-4175-8C4C-07106B3F9C08}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {44F77533-A4A1-4175-8C4C-07106B3F9C08}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {45E2ABF6-91A7-4AA5-A82B-0C8E54BCCCB9}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {45E2ABF6-91A7-4AA5-A82B-0C8E54BCCCB9}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {45E2ABF6-91A7-4AA5-A82B-0C8E54BCCCB9}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {45E2ABF6-91A7-4AA5-A82B-0C8E54BCCCB9}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+ {F62E31E5-0F8D-4B70-8F26-44AFA1A9E645}.Debug|@PLATFORM@.ActiveCfg = Debug|@PLATFORM@
+ {F62E31E5-0F8D-4B70-8F26-44AFA1A9E645}.Debug|@PLATFORM@.Build.0 = Debug|@PLATFORM@
+ {F62E31E5-0F8D-4B70-8F26-44AFA1A9E645}.Release|@PLATFORM@.ActiveCfg = Release|@PLATFORM@
+ {F62E31E5-0F8D-4B70-8F26-44AFA1A9E645}.Release|@PLATFORM@.Build.0 = Release|@PLATFORM@
+@END TESTS
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.filters b/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.filters
new file mode 100644
index 0000000..1f7b8b2
--- /dev/null
+++ b/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.filters
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\access.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\P11Attributes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\P11Objects.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\SoftHSM.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\access.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\P11Attributes.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\P11Objects.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\SoftHSM.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\win32\dllmain.cc">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.in b/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.in
new file mode 100644
index 0000000..efa808e
--- /dev/null
+++ b/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.in
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{801F5AB2-7A62-4085-B129-D15E2D717219}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>softhsm2</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;SOFTHSM2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\pkcs11;..\..\src\lib\common;..\..\src\lib\object_store;..\..\src\lib\slot_mgr;..\..\src\lib\session_mgr;..\..\src\lib\data_mgr;..\..\src\lib\handle_mgr;..\..\src\lib\crypto;..\..\src\lib\win32;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_USRDLL;SOFTHSM2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\lib;..\..\src\lib\pkcs11;..\..\src\lib\common;..\..\src\lib\object_store;..\..\src\lib\slot_mgr;..\..\src\lib\session_mgr;..\..\src\lib\data_mgr;..\..\src\lib\handle_mgr;..\..\src\lib\crypto;..\..\src\lib\win32;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\lib\access.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ <ClInclude Include="..\..\src\lib\P11Attributes.h" />
+ <ClInclude Include="..\..\src\lib\P11Objects.h" />
+ <ClInclude Include="..\..\src\lib\SoftHSM.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\lib\access.cpp" />
+ <ClCompile Include="..\..\src\lib\main.cpp" />
+ <ClCompile Include="..\..\src\lib\P11Attributes.cpp" />
+ <ClCompile Include="..\..\src\lib\P11Objects.cpp" />
+ <ClCompile Include="..\..\src\lib\SoftHSM.cpp" />
+ <ClCompile Include="..\..\src\lib\win32\dllmain.cc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.user b/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/softhsm2/softhsm2.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/SoftHSMv2/win32/util/util.vcxproj.filters.in b/SoftHSMv2/win32/util/util.vcxproj.filters.in
new file mode 100644
index 0000000..2c4171b
--- /dev/null
+++ b/SoftHSMv2/win32/util/util.vcxproj.filters.in
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Common Header Files">
+ <UniqueIdentifier>{21eda3a1-8da0-4a99-967c-f218e4eecd08}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Common Source Files">
+ <UniqueIdentifier>{fd946626-7e24-4f78-834b-a4c0ac6dc2f5}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Win32 Header Files">
+ <UniqueIdentifier>{f3a7acce-323d-4465-95bf-a326189dcdd5}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Win32 Source Files">
+ <UniqueIdentifier>{2b77905a-99da-49cf-9cac-aa72e7e3182b}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\bin\common\findslot.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\bin\common\getpw.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\bin\common\library.h">
+ <Filter>Common Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\bin\util\softhsm2-util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+@IF BOTAN
+ <ClInclude Include="..\..\src\bin\util\softhsm2-util-botan.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+@END BOTAN
+@IF OPENSSL
+ <ClInclude Include="..\..\src\bin\util\softhsm2-util-ossl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\crypto\OSSLComp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+@END OPENSSL
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\bin\win32\getopt.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\bin\common\findslot.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\common\getpw.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\common\library.cpp">
+ <Filter>Common Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\util\softhsm2-util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+@IF BOTAN
+ <ClCompile Include="..\..\src\bin\util\softhsm2-util-botan.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+@END BOTAN
+@IF OPENSSL
+ <ClCompile Include="..\..\src\bin\util\softhsm2-util-ossl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\lib\crypto\OSSLComp.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+@END OPENSSL
+ <ClCompile Include="..\..\src\bin\win32\getopt.cpp">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\bin\win32\getpassphase.cpp">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/SoftHSMv2/win32/util/util.vcxproj.in b/SoftHSMv2/win32/util/util.vcxproj.in
new file mode 100644
index 0000000..28bdcd0
--- /dev/null
+++ b/SoftHSMv2/win32/util/util.vcxproj.in
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{05901466-4184-47C8-9D6C-3BB99BBF5378}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>util</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>@PLATFORMTOOLSET@</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <TargetName>softhsm2-util</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <TargetName>softhsm2-util</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\bin\common;..\..\src\bin\win32;..\..\src\lib\pkcs11;..\..\src\lib;..\..\src\lib\common;..\..\src\lib\crypto;..\..\src\lib\data_mgr;..\..\src\lib\object_store;..\..\src\lib\win32\;@DEBUGINCPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@DEBUGLIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PostBuildEvent>
+ <Command>if exist @DEBUGDLLPATH@ copy @DEBUGDLLPATH@ ..\@PLATFORMDIR@$(Configuration)</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..;..\..\src\bin\common;..\..\src\bin\win32;..\..\src\lib\pkcs11;..\..\src\lib;..\..\src\lib\common;..\..\src\lib\crypto;..\..\src\lib\data_mgr;..\..\src\lib\object_store;..\..\src\lib\win32\;@INCLUDEPATH@;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <RuntimeLibrary>@RUNTIMELIBRARY@</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\@PLATFORMDIR@$(Configuration);@LIBPATH@;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>convarch.lib;@LIBNAME@;@EXTRALIBS@%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PostBuildEvent>
+ <Command>if exist @DLLPATH@ copy @DLLPATH@ ..\@PLATFORMDIR@$(Configuration)</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\src\bin\common\findslot.h" />
+ <ClInclude Include="..\..\src\bin\common\getpw.h" />
+ <ClInclude Include="..\..\src\bin\common\library.h" />
+@IF BOTAN
+ <ClInclude Include="..\..\src\bin\util\softhsm2-util-botan.h" />
+@END BOTAN
+@IF OPENSSL
+ <ClInclude Include="..\..\src\bin\util\softhsm2-util-ossl.h" />
+ <ClInclude Include="..\..\src\lib\crypto\OSSLComp.h" />
+@END OPENSSL
+ <ClInclude Include="..\..\src\bin\util\softhsm2-util.h" />
+ <ClInclude Include="..\..\src\bin\win32\getopt.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\cryptoki.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\..\src\lib\pkcs11\pkcs11t.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\src\bin\common\findslot.cpp" />
+ <ClCompile Include="..\..\src\bin\common\getpw.cpp" />
+ <ClCompile Include="..\..\src\bin\common\library.cpp" />
+@IF BOTAN
+ <ClCompile Include="..\..\src\bin\util\softhsm2-util-botan.cpp" />
+@END BOTAN
+@IF OPENSSL
+ <ClCompile Include="..\..\src\bin\util\softhsm2-util-ossl.cpp" />
+ <ClCompile Include="..\..\src\lib\crypto\OSSLComp.cpp" />
+@END OPENSSL
+ <ClCompile Include="..\..\src\bin\util\softhsm2-util.cpp" />
+ <ClCompile Include="..\..\src\bin\win32\getopt.cpp" />
+ <ClCompile Include="..\..\src\bin\win32\getpassphase.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/SoftHSMv2/win32/util/util.vcxproj.user b/SoftHSMv2/win32/util/util.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/SoftHSMv2/win32/util/util.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/TPM2-Plugin/README b/TPM2-Plugin/README
new file mode 100644
index 0000000..e6ed31a
--- /dev/null
+++ b/TPM2-Plugin/README
@@ -0,0 +1,5 @@
+## Introduction
+
+This is TPM2-Plugin to gererate asymetric key pairs from TPM2.0 module
+and save them in SoftHSM Token object folder in encryped fasion.
+The private part of keys can only be used for signing when it is loaded in TPM module.