- /* hw_pkcs11.c (replace hw_trustway.c) */
- /*
- * PKCS#11 engine for the OpenSSL project 2002
- * Developped by Bull Trustway R&D Networking & Security
- * Introduced and tested with Bull TrustWay CC2000 crypto hardware
- * Afchine.Madjlessi@bull.net Bull S.A. France
- * http://www.servers.bull.com/trustway
- *
- * ChangLog:
- * * 6/30/2010 Updates to compile stand-alone and against openssl 1.0
- * * 8/15/2005 Fixes suggested by opencryptoki-engines list
- * * 1/1/2004 Modified to support digests, ciphers and openCryptoki
- * http://www.sf.net/projects/opencryptoki
- * - Serge Hallyn <serue@us.ibm.com>
- * - Kent Yoder <yoder1@us.ibm.com>
- * - Peter Waltenberg <pwalten@au1.ibm.com>
- * (C) International Business Machines Corporation 2004, 2005, 2010
- */
-
- #include <assert.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <dlfcn.h>
-
- #include <sys/types.h>
- #include <unistd.h>
-
- #include <openssl/e_os2.h>
- #include <openssl/engine.h>
- #include <openssl/err.h>
- #include <openssl/bn.h>
- #include <openssl/pem.h>
- #include <openssl/rsa.h>
- #include <openssl/rand.h>
- #include <openssl/objects.h>
- #include <openssl/x509.h>
- #include <openssl/md5.h>
- #include <openssl/ripemd.h>
-
- #ifndef OPENSSL_NO_HW
- #ifndef OPENSSL_NO_HW_PKCS11
-
- #include "cryptoki.h"
- #include "e_pkcs11_err.h"
- #include "e_pkcs11.h"
- /* SHA224, CAMELLIA */
- #include "pkcs-11v2-20a3.h"
-
- #if OPENSSL_VERSION_NUMBER < 0x10100000L
- #define OLDER_OPENSSL
- #endif
-
- /* Constants used when creating the ENGINE */
- static const char *engine_pkcs11_id = "ibmpkcs11";
- static const char *engine_pkcs11_name = "PKCS#11 hardware engine support";
-
- static int bind_pkcs11(ENGINE *e);
-
- /* ENGINE level stuff */
- static int pkcs11_init(ENGINE *e);
- static int pkcs11_finish(ENGINE *e);
- static int pkcs11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
- static int pkcs11_destroy(ENGINE *e);
-
- #ifndef OPENSSL_NO_RSA
- /* RSA stuff */
- static int pkcs11_RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
- RSA *rsa, int padding);
- static int pkcs11_RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
- RSA *rsa, int padding);
- static int pkcs11_RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
- RSA *rsa, int padding);
- static int pkcs11_RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
- RSA *rsa, int padding);
- static int pkcs11_RSA_init(RSA *rsa);
- static int pkcs11_RSA_finish(RSA *rsa);
-
- #ifdef OLDER_OPENSSL
- static int pkcs11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
- unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
-
- /* this API changed in OpenSSL version 1.0.0 */
- #if (OPENSSL_VERSION_NUMBER < 0x10000000L)
- static int pkcs11_RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
- unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
- #else
- static int pkcs11_RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
- const unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
- #endif
- #endif
-
- static int pkcs11_RSA_generate_key(RSA *rsa, int bits, BIGNUM *bn_e, BN_GENCB *cb);
-
- static EVP_PKEY *pkcs11_load_privkey(ENGINE*, const char* pubkey_file,
- UI_METHOD *ui_method, void *callback_data);
- static EVP_PKEY *pkcs11_load_pubkey(ENGINE*, const char* pubkey_file,
- UI_METHOD *ui_method, void *callback_data);
-
- CK_OBJECT_HANDLE pkcs11_FindOrCreateKey(CK_SESSION_HANDLE h, RSA* rsa, CK_OBJECT_CLASS oKey, CK_BBOOL fKeyCreate);
- /* exported functions (not member of ENGINE inteface) */
- RSA* pkcs11_RSA_generate_tmp_key(int bits,unsigned long e_value,void (*callback)(int,int,void *),void *cb_arg);
- #endif
-
- /* RAND stuff */
- static void pkcs11_rand_seed(const void *buf, int num);
- static void pkcs11_rand_add(const void *buf, int num, double add_entropy);
- static void pkcs11_rand_cleanup(void);
- static int pkcs11_rand_bytes(unsigned char *buf, int num);
- static int pkcs11_rand_status(void);
-
- /* cipher function prototypes */
- static inline int pkcs11_init_key(EVP_CIPHER_CTX * ctx, const unsigned char *key,
- const unsigned char *iv, int enc, int alg);
- static inline int pkcs11_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out,
- const unsigned char *in, size_t inlen);
- static int pkcs11_cipher_cleanup(EVP_CIPHER_CTX *ctx);
-
- static int pkcs11_des_init_key(EVP_CIPHER_CTX * ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
- static int pkcs11_tdes_init_key(EVP_CIPHER_CTX * ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
- static int pkcs11_aes_init_key(EVP_CIPHER_CTX * ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
- /* End cipher function prototypes */
-
- /* Digest function prototypes */
- static inline int pkcs11_digest_init(EVP_MD_CTX *ctx, int alg);
- static int pkcs11_digest_update(EVP_MD_CTX *ctx, const void *in, size_t len);
- static int pkcs11_digest_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in);
- static int pkcs11_digest_finish(EVP_MD_CTX *ctx, unsigned char *md);
- static inline int pkcs11_digest_cleanup(EVP_MD_CTX *ctx);
-
- static inline int pkcs11_sha1_init(EVP_MD_CTX *ctx);
- static inline int pkcs11_sha224_init(EVP_MD_CTX *ctx);
- static inline int pkcs11_sha256_init(EVP_MD_CTX *ctx);
- static inline int pkcs11_sha384_init(EVP_MD_CTX *ctx);
- static inline int pkcs11_sha512_init(EVP_MD_CTX *ctx);
- static inline int pkcs11_md5_init(EVP_MD_CTX *ctx);
- static inline int pkcs11_ripemd160_init(EVP_MD_CTX *ctx);
- /* End digest function prototypes */
-
- static int pre_init_pkcs11(ENGINE *e);
- static int pkcs11_engine_ciphers(ENGINE * e, const EVP_CIPHER ** cipher,
- const int **nids, int nid);
- static int pkcs11_engine_digests(ENGINE * e, const EVP_MD ** digest,
- const int **nids, int nid);
-
- /* The definitions for control commands specific to this engine */
- #define PKCS11_CMD_SO_PATH ENGINE_CMD_BASE
- #define PKCS11_CMD_SLOT_ID (ENGINE_CMD_BASE + 1)
- static const ENGINE_CMD_DEFN pkcs11_cmd_defns[] =
- {
- { PKCS11_CMD_SO_PATH,
- "SO_PATH",
- "Specifies the path to the 'pkcs#11' shared library",
- ENGINE_CMD_FLAG_STRING
- },
- { PKCS11_CMD_SLOT_ID,
- "SLOT_ID",
- "Specifies the slot containing the token to use",
- ENGINE_CMD_FLAG_NUMERIC
- },
- {0, NULL, NULL, 0}
- };
-
- #ifdef OPENSSL_NO_DYNAMIC_ENGINE
- static ENGINE *engine_pkcs11(void)
- {
- ENGINE *ret = ENGINE_new();
- if(!ret) {
- return NULL;
- }
- if(!bind_helper(ret)) {
- ENGINE_free(ret);
- return NULL;
- }
- return ret;
- }
-
- void ENGINE_load_pkcs11(void)
- {
- ENGINE *toadd = engine_pkcs11();
- if(!toadd) return;
- ENGINE_add(toadd);
- ENGINE_free(toadd);
- ERR_clear_error();
- }
- #else
- static int bind_helper(ENGINE *e, const char *id)
- {
- if((NULL != id) && (strcmp(id, engine_pkcs11_id) != 0))
- return 0;
- return(bind_pkcs11(e));
- }
- IMPLEMENT_DYNAMIC_CHECK_FN()
- IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
- #endif
-
- /*
- * Comments on approaches:
- * At the moment, ciphers and digests are treated differently.
- *
- * For ciphers, we use cipher_init to initialize the cryptoki
- * cipher action, and update to encrypt. There is no finalize
- * or cleanup.
- *
- * For digests, we use digest_init to initialize a context
- * struct, digest_update to call C_DigestUpdate on the data that
- * we are receiving, digest_finish to call C_DigestFinal(), and
- * cleanup() to free the context struct.
- */
-
- /*
- * Each cipher action requires a new session. We store the
- * session and its token in the context->cipher_data void* using
- * this struct
- */
- struct token_session {
- struct _token *token;
- CK_SESSION_HANDLE session;
- };
-
- /*
- * For digests:
- * We call digest_init to start the context, digest_update
- * to start computing the digest on the data that is being
- * received and digest_finish to finish the digest operation.
- */
- struct pkcs11_digest_ctx {
- int alg;
- int len;
- struct _token *token;
- CK_SESSION_HANDLE session;
- };
-
- /********/
-
- #ifdef OLDER_OPENSSL
- #define CIPHER_DATA(ctx) ((struct token_session *)(ctx->cipher_data))
- #define MD_DATA(ctx) ((struct pkcs11_digest_ctx *)(ctx->md_data))
- #else
- #define CIPHER_DATA(ctx) ((struct token_session *)(EVP_CIPHER_CTX_get_cipher_data(ctx)))
- #define MD_DATA(ctx) ((struct pkcs11_digest_ctx *)(EVP_MD_CTX_md_data(ctx)))
- #endif
-
- static int num_cipher_nids = 0;
- static int num_digest_nids = 0;
-
- #ifdef OLDER_OPENSSL
- const EVP_CIPHER pkcs11_des_ecb = {
- NID_des_ecb, /* NID */
- 8, /* Block size */
- 8, /* Key len */
- 8, /* IV len */
- EVP_CIPH_ECB_MODE, /* flags */
- pkcs11_des_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session),
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
-
- const EVP_CIPHER pkcs11_des_cbc = {
- NID_des_cbc, /* NID */
- 8, /* Block size */
- 8, /* Key len */
- 8, /* IV len */
- EVP_CIPH_CBC_MODE, /* flags */
- pkcs11_des_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
- #else
-
- #define DECLARE_DES_EVP(lmode, umode) \
- static EVP_CIPHER *des_##lmode = NULL; \
- static const EVP_CIPHER *pkcs11_des_##lmode(void) \
- { \
- if (des_##lmode == NULL) { \
- EVP_CIPHER *cipher; \
- if (( cipher = EVP_CIPHER_meth_new(NID_des_##lmode, \
- 8, 8)) == NULL \
- || !EVP_CIPHER_meth_set_iv_length(cipher, 8) \
- || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_##umode##_MODE)\
- || !EVP_CIPHER_meth_set_init(cipher, pkcs11_des_init_key) \
- || !EVP_CIPHER_meth_set_do_cipher(cipher, pkcs11_cipher) \
- || !EVP_CIPHER_meth_set_cleanup(cipher, pkcs11_cipher_cleanup)\
- || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof( \
- struct token_session))\
- || !EVP_CIPHER_meth_set_set_asn1_params(cipher, \
- EVP_CIPHER_set_asn1_iv) \
- || !EVP_CIPHER_meth_set_get_asn1_params(cipher, \
- EVP_CIPHER_get_asn1_iv)) { \
- EVP_CIPHER_meth_free(cipher); \
- cipher = NULL; \
- } \
- des_##lmode = cipher; \
- } \
- return des_##lmode; \
- } \
- \
- static void pkcs11_des_##lmode##_destroy(void) \
- { \
- EVP_CIPHER_meth_free(des_##lmode); \
- des_##lmode = NULL; \
- }
-
- DECLARE_DES_EVP(ecb, ECB)
- DECLARE_DES_EVP(cbc, CBC)
- #endif
-
- #ifdef OLDER_OPENSSL
- const EVP_CIPHER pkcs11_tdes_ecb = {
- NID_des_ede3_ecb, /* NID */
- 8, /* Block size */
- 24, /* Key len */
- 8, /* IV len */
- EVP_CIPH_ECB_MODE, /* flags */
- pkcs11_tdes_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
-
- const EVP_CIPHER pkcs11_tdes_cbc = {
- NID_des_ede3_cbc, /* NID */
- 8, /* Block size */
- 24, /* Key len */
- 8, /* IV len */
- EVP_CIPH_CBC_MODE, /* flags */
- pkcs11_tdes_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
- #else
-
- #define DECLARE_TDES_EVP(lmode, umode) \
- static EVP_CIPHER *tdes_##lmode = NULL; \
- static const EVP_CIPHER *pkcs11_tdes_##lmode(void) \
- { \
- if (tdes_##lmode == NULL) { \
- EVP_CIPHER *cipher; \
- if (( cipher = EVP_CIPHER_meth_new(NID_des_ede3_##lmode, \
- 8, 24)) == NULL \
- || !EVP_CIPHER_meth_set_iv_length(cipher, 8) \
- || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_##umode##_MODE)\
- || !EVP_CIPHER_meth_set_init(cipher, pkcs11_tdes_init_key) \
- || !EVP_CIPHER_meth_set_do_cipher(cipher, pkcs11_cipher) \
- || !EVP_CIPHER_meth_set_cleanup(cipher, pkcs11_cipher_cleanup)\
- || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof( \
- struct token_session))\
- || !EVP_CIPHER_meth_set_set_asn1_params(cipher, \
- EVP_CIPHER_set_asn1_iv) \
- || !EVP_CIPHER_meth_set_get_asn1_params(cipher, \
- EVP_CIPHER_get_asn1_iv)) { \
- EVP_CIPHER_meth_free(cipher); \
- cipher = NULL; \
- } \
- tdes_##lmode = cipher; \
- } \
- return tdes_##lmode; \
- } \
- \
- static void pkcs11_tdes_##lmode##_destroy(void) \
- { \
- EVP_CIPHER_meth_free(tdes_##lmode); \
- tdes_##lmode = NULL; \
- }
-
- DECLARE_TDES_EVP(ecb, ECB)
- DECLARE_TDES_EVP(cbc, CBC)
- #endif
-
- #ifdef OLDER_OPENSSL
- /* AES ECB */
- const EVP_CIPHER pkcs11_aes_128_ecb = {
- NID_aes_128_cbc, /* NID */
- 16, /* Block size */
- 16, /* Key len */
- 16, /* IV len */
- EVP_CIPH_ECB_MODE, /* flags */
- pkcs11_aes_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
-
- const EVP_CIPHER pkcs11_aes_192_ecb = {
- NID_aes_192_ecb, /* NID */
- 16, /* Block size */
- 24, /* Key len */
- 16, /* IV len */
- EVP_CIPH_ECB_MODE, /* flags */
- pkcs11_aes_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
-
- const EVP_CIPHER pkcs11_aes_256_ecb = {
- NID_aes_256_ecb, /* NID */
- 16, /* Block size */
- 32, /* Key len */
- 16, /* IV len */
- EVP_CIPH_ECB_MODE, /* flags */
- pkcs11_aes_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
-
- /* AES CBC */
- const EVP_CIPHER pkcs11_aes_128_cbc = {
- NID_aes_128_cbc, /* NID */
- 16, /* Block size */
- 16, /* Key len */
- 16, /* IV len */
- EVP_CIPH_CBC_MODE, /* flags */
- pkcs11_aes_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
-
- const EVP_CIPHER pkcs11_aes_192_cbc = {
- NID_aes_192_cbc, /* NID */
- 16, /* Block size */
- 24, /* Key len */
- 16, /* IV len */
- EVP_CIPH_CBC_MODE, /* flags */
- pkcs11_aes_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
-
- const EVP_CIPHER pkcs11_aes_256_cbc = {
- NID_aes_256_cbc, /* NID */
- 16, /* Block size */
- 32, /* Key len */
- 16, /* IV len */
- EVP_CIPH_CBC_MODE, /* flags */
- pkcs11_aes_init_key, /* init */
- pkcs11_cipher, /* do_cipher */
- pkcs11_cipher_cleanup, /* cleanup */
- sizeof(struct token_session), /* sizeof(ctx->cipher_data) */
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL, /* misc ctrl ops */
- NULL /* app data (ctx->cipher_data) */
- };
- #else
-
- #define EVP_CIPHER_keylen_AES_128 16
- #define EVP_CIPHER_keylen_AES_192 24
- #define EVP_CIPHER_keylen_AES_256 32
-
- #define DECLARE_AES_EVP(ksize, lmode, umode) \
- static EVP_CIPHER *aes_##ksize##_##lmode = NULL; \
- static const EVP_CIPHER *pkcs11_aes_##ksize##_##lmode(void) \
- { \
- if (aes_##ksize##_##lmode == NULL) { \
- EVP_CIPHER *cipher; \
- if (( cipher = EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \
- 8, \
- EVP_CIPHER_keylen_AES_##ksize)) == NULL \
- || !EVP_CIPHER_meth_set_iv_length(cipher, 16) \
- || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_##umode##_MODE)\
- || !EVP_CIPHER_meth_set_init(cipher, pkcs11_aes_init_key) \
- || !EVP_CIPHER_meth_set_do_cipher(cipher, pkcs11_cipher) \
- || !EVP_CIPHER_meth_set_cleanup(cipher, pkcs11_cipher_cleanup)\
- || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof( \
- struct token_session))\
- || !EVP_CIPHER_meth_set_set_asn1_params(cipher, \
- EVP_CIPHER_set_asn1_iv) \
- || !EVP_CIPHER_meth_set_get_asn1_params(cipher, \
- EVP_CIPHER_get_asn1_iv)) { \
- EVP_CIPHER_meth_free(cipher); \
- cipher = NULL; \
- } \
- aes_##ksize##_##lmode = cipher; \
- } \
- return aes_##ksize##_##lmode; \
- } \
- \
- static void pkcs11_aes_##ksize##_##lmode##_destroy(void) \
- { \
- EVP_CIPHER_meth_free(aes_##ksize##_##lmode); \
- aes_##ksize##_##lmode = NULL; \
- }
-
- DECLARE_AES_EVP(128, cbc, CBC)
- DECLARE_AES_EVP(192, cbc, CBC)
- DECLARE_AES_EVP(256, cbc, CBC)
- DECLARE_AES_EVP(128, ecb, ECB)
- DECLARE_AES_EVP(192, ecb, ECB)
- DECLARE_AES_EVP(256, ecb, ECB)
- #endif
-
- #ifdef OLDER_OPENSSL
- /* Message Digests */
- const EVP_MD pkcs11_sha1 = {
- NID_sha1,
- NID_sha1WithRSAEncryption,
- SHA_DIGEST_LENGTH,
- EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
- pkcs11_sha1_init,
- pkcs11_digest_update,
- pkcs11_digest_finish, /* final */
- pkcs11_digest_copy,
- pkcs11_digest_cleanup, /* cleanup */
- EVP_PKEY_RSA_method,
- SHA_CBLOCK,
- sizeof(struct pkcs11_digest_ctx)
- };
-
- const EVP_MD pkcs11_sha224 = {
- NID_sha224,
- NID_sha224WithRSAEncryption,
- SHA224_DIGEST_LENGTH,
- EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
- pkcs11_sha224_init,
- pkcs11_digest_update,
- pkcs11_digest_finish, /* final */
- pkcs11_digest_copy,
- pkcs11_digest_cleanup, /* cleanup */
- EVP_PKEY_RSA_method,
- SHA256_CBLOCK,
- sizeof(struct pkcs11_digest_ctx)
- };
-
- const EVP_MD pkcs11_sha256 = {
- NID_sha256,
- NID_sha256WithRSAEncryption,
- SHA256_DIGEST_LENGTH,
- EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
- pkcs11_sha256_init,
- pkcs11_digest_update,
- pkcs11_digest_finish, /* final */
- pkcs11_digest_copy,
- pkcs11_digest_cleanup, /* cleanup */
- EVP_PKEY_RSA_method,
- SHA256_CBLOCK,
- sizeof(struct pkcs11_digest_ctx)
- };
-
- const EVP_MD pkcs11_sha384 = {
- NID_sha384,
- NID_sha384WithRSAEncryption,
- SHA384_DIGEST_LENGTH,
- EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
- pkcs11_sha384_init,
- pkcs11_digest_update,
- pkcs11_digest_finish, /* final */
- pkcs11_digest_copy,
- pkcs11_digest_cleanup, /* cleanup */
- EVP_PKEY_RSA_method,
- SHA512_CBLOCK,
- sizeof(struct pkcs11_digest_ctx)
- };
-
- const EVP_MD pkcs11_sha512 = {
- NID_sha512,
- NID_sha512WithRSAEncryption,
- SHA512_DIGEST_LENGTH,
- EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
- pkcs11_sha512_init,
- pkcs11_digest_update,
- pkcs11_digest_finish, /* final */
- pkcs11_digest_copy,
- pkcs11_digest_cleanup, /* cleanup */
- EVP_PKEY_RSA_method,
- SHA512_CBLOCK,
- sizeof(struct pkcs11_digest_ctx)
- };
-
- const EVP_MD pkcs11_md5 = {
- NID_md5,
- NID_md5WithRSAEncryption,
- MD5_DIGEST_LENGTH,
- 0,
- pkcs11_md5_init,
- pkcs11_digest_update,
- pkcs11_digest_finish, /* final */
- pkcs11_digest_copy,
- pkcs11_digest_cleanup, /* cleanup */
- EVP_PKEY_RSA_method,
- MD5_CBLOCK,
- sizeof(struct pkcs11_digest_ctx)
- };
-
- const EVP_MD pkcs11_ripemd160 = {
- NID_ripemd160,
- NID_ripemd160WithRSA,
- RIPEMD160_DIGEST_LENGTH,
- 0, /* flags */
- pkcs11_ripemd160_init,
- pkcs11_digest_update,
- pkcs11_digest_finish, /* final */
- pkcs11_digest_copy,
- pkcs11_digest_cleanup, /* cleanup */
- EVP_PKEY_RSA_method,
- RIPEMD160_CBLOCK,
- sizeof(struct pkcs11_digest_ctx)
- };
- #else
-
- #define DECLARE_DIGEST_EVP(dig, len, enc) \
- static EVP_MD *dig##_md = NULL; \
- static const EVP_MD *pkcs11_##dig(void) \
- { \
- if (dig##_md == NULL) { \
- EVP_MD *md; \
- if (( md = EVP_MD_meth_new(NID_##dig, \
- NID_##dig##WithRSA##enc)) == NULL \
- || !EVP_MD_meth_set_result_size(md, len##_DIGEST_LENGTH) \
- || !EVP_MD_meth_set_input_blocksize(md, len##_CBLOCK) \
- || !EVP_MD_meth_set_app_datasize(md, \
- sizeof(struct pkcs11_digest_ctx)) \
- || !EVP_MD_meth_set_flags(md, 0) \
- || !EVP_MD_meth_set_init(md, pkcs11_##dig##_init) \
- || !EVP_MD_meth_set_update(md, pkcs11_digest_update) \
- || !EVP_MD_meth_set_final(md, pkcs11_digest_finish) \
- || !EVP_MD_meth_set_copy(md, pkcs11_digest_copy) \
- || !EVP_MD_meth_set_cleanup(md, pkcs11_digest_cleanup)) { \
- EVP_MD_meth_free(md); \
- md = NULL; \
- } \
- dig##_md = md; \
- } \
- return dig##_md; \
- } \
- \
- static void pkcs11_##dig##_destroy(void) \
- { \
- EVP_MD_meth_free(dig##_md); \
- dig##_md = NULL; \
- }
-
- DECLARE_DIGEST_EVP(sha1, SHA, Encryption)
- DECLARE_DIGEST_EVP(sha224, SHA256, Encryption)
- DECLARE_DIGEST_EVP(sha256, SHA256, Encryption)
- DECLARE_DIGEST_EVP(sha384, SHA512, Encryption)
- DECLARE_DIGEST_EVP(sha512, SHA512, Encryption)
- DECLARE_DIGEST_EVP(md5, MD5, Encryption)
- DECLARE_DIGEST_EVP(ripemd160, RIPEMD160,)
- #endif
-
- /********/
- #ifndef OPENSSL_NO_RSA
- #ifdef OLDER_OPENSSL
- static RSA_METHOD pkcs11_rsa =
- {
- "PKCS#11 RSA",
- pkcs11_RSA_public_encrypt, /* rsa_pub_encrypt */
- pkcs11_RSA_public_decrypt, /* rsa_pub_decrypt */
- pkcs11_RSA_private_encrypt, /* rsa_priv_encrypt */
- pkcs11_RSA_private_decrypt, /* rsa_priv_decrypt */
- NULL, /* rsa_mod_exp */
- NULL, /* bn_mod_exp */
- pkcs11_RSA_init, /* init */
- pkcs11_RSA_finish, /* finish */
- RSA_FLAG_SIGN_VER, /* flags */
- NULL, /* app_data */
- pkcs11_RSA_sign, /* rsa_sign */
- pkcs11_RSA_verify, /* rsa_verify */
- pkcs11_RSA_generate_key /* rsa_generate_key */
- };
- #else
- static RSA_METHOD *pkcs11_rsa = NULL;
- #endif
-
- /*RSA_METHOD *PKCS11_RSA(void)
- {
- return(&pkcs11_rsa);
- }*/
- #endif
-
- extern const char *RAND_version;
-
- static RAND_METHOD pkcs11_random =
- {
- /* "PKCS11 RAND method", */
- pkcs11_rand_seed,
- pkcs11_rand_bytes,
- pkcs11_rand_cleanup,
- pkcs11_rand_add,
- pkcs11_rand_bytes,
- pkcs11_rand_status
- };
-
-
- RAND_METHOD *PKCS11_RAND(void)
- {
- return(&pkcs11_random);
- }
-
- static CK_FUNCTION_LIST_PTR pFunctionList = NULL;
-
- /* These are the static string constants for the DSO file name and the function
- * symbol names to bind to.
- */
- static unsigned char PKCS11_KEY_ID[] = "OpenSSL PKCS#11";
-
- /* String used to detect a CC2000 Bull TrustWay crypto card */
- #define BULL_TRUSTWAY_LIBRARY_DESCRIPTION "Bull CC2000 PKCS#11 Library "
- static CK_BBOOL Bull_TrustWay = FALSE;
- #undef BULL_CC2000 /* use Bull CC2000 hardware crypto */
-
- #undef BULL_CRYPTOBOX /* use Bull CryptoBox remote hardware crypto */
-
- #undef GPKCS11 /* use GPKCS11 software crypto */
-
- #if defined(BULL_CC2000)
- static const char def_PKCS11_LIBNAME[] = "gpkcs11cc2000";
- #elif defined(BULL_CRYPTOBOX)
- static const char def_PKCS11_LIBNAME[] = "cryptobox_clnt";
- extern CK_RV C_InitializeRpc (CK_CHAR_PTR, CK_CHAR_PTR, CK_ULONG_PTR);
- #elif defined(GPKCS11)
- static const char def_PKCS11_LIBNAME[] = "gpkcs11";
- #elif defined(OPENCRYPTOKI)
- static char *def_PKCS11_LIBNAME = "libopencryptoki.so";
- #else
- static const char def_PKCS11_LIBNAME[] = "pkcs11";
- #endif
- static const char PKCS11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
-
- /* Size of an SSL signature: MD5+SHA1. up to allow SHA512 */
- //#define SSL_SIG_LENGTH 64
- #define SSL_SIG_LENGTH 36
- #define KEY_STORE 1
- static CK_BBOOL true = TRUE;
- static CK_BBOOL false = FALSE;
- static CK_SLOT_ID SLOTID = 0XFFFFFFFF;
-
- #ifndef OPENSSL_NO_RSA
- /* Where in the CRYPTO_EX_DATA stack we stick our per-key contexts */
- static int rsaPubKey = -1;
- static int rsaPrivKey = -1;
- static int deletePubKeyOnFree = -1;
- static int deletePrivKeyOnFree = -1;
- static int pkcs11Session = -1;
- #endif
-
- static int PKCS11_Initialized = 0;
-
- #ifdef PKCS11_DEBUG
- #define DBG_fprintf(args...) do { fprintf(stderr, args); fflush(stderr); } while (0)
- #else
- #define DBG_fprintf(args...)
- #endif
-
- void pkcs11_atfork_init(void)
- {
- DBG_fprintf("pkcs11_atfork_init: called (pid %d)\n", getpid());
- PKCS11_Initialized = 0;
- }
-
- #define pkcs11_die(func, reason, rv) \
- { \
- char tmpbuf[20]; \
- PKCS11err(func, reason); \
- sprintf(tmpbuf, "%lx", rv); \
- ERR_add_error_data(2, "PKCS11 CK_RV=0X", tmpbuf); \
- }
-
- struct token_session *pkcs11_getSession(void)
- {
- CK_RV rv;
- struct token_session *wrapper;
-
- if (!pkcs11_token) {
- PKCS11err(PKCS11_F_GETSESSION, PKCS11_R_NO_SLOT_SELECTED);
- return NULL;
- }
-
- wrapper = OPENSSL_malloc(sizeof (struct token_session));
- if (!wrapper) {
- PKCS11err(PKCS11_F_GETSESSION, PKCS11_R_MALLOC_FAILURE);
- return NULL;
- }
- wrapper->token = pkcs11_token;
-
- if (!PKCS11_Initialized) {
- rv = pFunctionList->C_Initialize(NULL);
- if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
- pkcs11_die(PKCS11_F_GETSESSION, PKCS11_R_INITIALIZE, rv);
- return NULL;
- }
- PKCS11_Initialized = 1;
- }
-
- rv = pFunctionList->C_OpenSession(wrapper->token->slot_id,
- CKF_SERIAL_SESSION | CKF_RW_SESSION,
- NULL_PTR,
- NULL_PTR,
- &wrapper->session);
- if (rv != CKR_OK) {
- pkcs11_die(PKCS11_F_GETSESSION, PKCS11_R_OPENSESSION, rv);
- return NULL;
- }
-
- return wrapper;
- }
-
- char *alg_to_string(int alg_type)
- {
- switch (alg_type) {
- case alg_des:
- return "des";
- case alg_tdes:
- return "tdes";
- case alg_aes:
- return "aes";
- case alg_rsa:
- return "rsa";
- case alg_sha:
- return "sha";
- case alg_md5:
- return "md5";
- case alg_ripemd:
- return "ripemd";
- default:
- return "invalid algorithm";
- }
- }
-
- /* This internal function is used by ENGINE_pkcs11() and possibly by the
- * "dynamic" ENGINE support too */
- static int bind_pkcs11(ENGINE *e)
- {
- DBG_fprintf("%s\n", __FUNCTION__);
-
- if (!ENGINE_set_id(e, engine_pkcs11_id) ||
- !ENGINE_set_name(e, engine_pkcs11_name) ||
- !ENGINE_set_RAND(e, &pkcs11_random) ||
- !ENGINE_set_init_function(e, pkcs11_init) ||
- !ENGINE_set_ciphers(e, pkcs11_engine_ciphers) ||
- !ENGINE_set_digests(e, pkcs11_engine_digests) ||
- !ENGINE_set_destroy_function(e, pkcs11_destroy) ||
- !ENGINE_set_finish_function(e, pkcs11_finish) ||
- !ENGINE_set_ctrl_function(e, pkcs11_ctrl) ||
- !ENGINE_set_cmd_defns(e, pkcs11_cmd_defns))
- return 0;
-
- /* Ensure the pkcs11 error handling is set up */
- ERR_load_pkcs11_strings();
-
- pre_init_pkcs11(e);
-
- return 1;
- }
-
- #ifdef ENGINE_DYNAMIC_SUPPORT
- static int bind_helper(ENGINE *e, const char *id)
- {
- DBG_fprintf("%s\n", __FUNCTION__);
-
- if(id && (strcmp(id, engine_pkcs11_id) != 0))
- return 0;
- if(!bind_pkcs11(e))
- return 0;
- return 1;
- }
- IMPLEMENT_DYNAMIC_CHECK_FN()
- IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
- #else
- static ENGINE *engine_pkcs11(void)
- {
- DBG_fprintf("%s\n", __FUNCTION__);
-
- ENGINE *ret = ENGINE_new();
- if(!ret)
- return NULL;
- if(!bind_pkcs11(ret))
- {
- ENGINE_free(ret);
- return NULL;
- }
-
- pre_init_pkcs11(ret);
-
- return ret;
- }
-
- void ENGINE_load_pkcs11(void)
- {
- DBG_fprintf("%s\n", __FUNCTION__);
-
- ENGINE *e_pkcs11 = engine_pkcs11();
- if(!e_pkcs11) return;
- ENGINE_add(e_pkcs11);
- ENGINE_free(e_pkcs11);
- ERR_clear_error();
- }
- #endif
-
- #define PKCS11_MAX_ALGS 20
-
- static int
- get_pkcs11_ciphers(const int **retnids)
- {
- static int nids[PKCS11_MAX_ALGS];
- int i, count = 0, *pkcs11_implemented_ciphers;
-
- if (pkcs11_token)
- pkcs11_implemented_ciphers = pkcs11_token->pkcs11_implemented_ciphers;
- else {
- PKCS11err(PKCS11_F_GET_PKCS11_CIPHERS, PKCS11_R_NO_SLOT_SELECTED);
- return 0;
- }
-
- memset(nids, 0, sizeof(nids));
- *retnids = NULL;
-
- for (i=0; i<NUM_NID; i++) {
- if (pkcs11_implemented_ciphers[i])
- nids[count++] = i;
- }
-
- if (count)
- *retnids = nids;
- return count;
- }
-
- static int
- get_pkcs11_digests(const int **retnids)
- {
- static int nids[PKCS11_MAX_ALGS];
- int i, count = 0, *pkcs11_implemented_digests;
-
- if (pkcs11_token)
- pkcs11_implemented_digests = pkcs11_token->pkcs11_implemented_digests;
- else {
- PKCS11err(PKCS11_F_GET_PKCS11_DIGESTS, PKCS11_R_NO_SLOT_SELECTED);
- return 0;
- }
-
- memset(nids, 0, sizeof(nids));
- *retnids = NULL;
-
- for (i=0; i<NUM_NID; i++) {
- if (pkcs11_implemented_digests[i])
- nids[count++] = i;
- }
-
- if (count)
- *retnids = nids;
- return count;
- }
-
- /*
- * ENGINE calls this to find out how to deal with
- * a particular NID in the ENGINE.
- */
- static int pkcs11_engine_ciphers(ENGINE * e, const EVP_CIPHER ** cipher,
- const int **nids, int nid)
- {
- if (!cipher)
- return get_pkcs11_ciphers(nids);
-
- if (!pkcs11_token) {
- PKCS11err(PKCS11_F_ENGINE_CIPHERS, PKCS11_R_NO_SLOT_SELECTED);
- return 0;
- }
-
- /* If the algorithm requested was not added to the list at
- * engine init time, don't return a reference to that structure.
- */
- if (pkcs11_token->pkcs11_implemented_ciphers[nid]) {
- switch (nid) {
- case NID_aes_128_ecb:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_aes_128_ecb;
- #else
- *cipher = pkcs11_aes_128_ecb();
- #endif
- break;
- case NID_aes_192_ecb:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_aes_192_ecb;
- #else
- *cipher = pkcs11_aes_192_ecb();
- #endif
- break;
- case NID_aes_256_ecb:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_aes_256_ecb;
- #else
- *cipher = pkcs11_aes_256_ecb();
- #endif
- break;
- case NID_aes_128_cbc:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_aes_128_cbc;
- #else
- *cipher = pkcs11_aes_128_cbc();
- #endif
- break;
- case NID_aes_192_cbc:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_aes_192_cbc;
- #else
- *cipher = pkcs11_aes_192_cbc();
- #endif
- break;
- case NID_aes_256_cbc:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_aes_256_cbc;
- #else
- *cipher = pkcs11_aes_256_cbc();
- #endif
- break;
- case NID_des_ecb:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_des_ecb;
- #else
- *cipher = pkcs11_des_ecb();
- #endif
- break;
- case NID_des_cbc:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_des_cbc;
- #else
- *cipher = pkcs11_des_cbc();
- #endif
- break;
- case NID_des_ede3_ecb:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_tdes_ecb;
- #else
- *cipher = pkcs11_tdes_ecb();
- #endif
- break;
- case NID_des_ede3_cbc:
- #ifdef OLDER_OPENSSL
- *cipher = &pkcs11_tdes_cbc;
- #else
- *cipher = pkcs11_tdes_cbc();
- #endif
- break;
- default:
- *cipher = NULL;
- break;
- }
- }
- return (*cipher != NULL);
- }
-
- static int pkcs11_engine_digests(ENGINE * e, const EVP_MD ** digest,
- const int **nids, int nid)
- {
- if (!digest)
- return get_pkcs11_digests(nids);
-
- if (!pkcs11_token) {
- PKCS11err(PKCS11_F_ENGINE_DIGESTS, PKCS11_R_NO_SLOT_SELECTED);
- return 0;
- }
-
- if (pkcs11_token->pkcs11_implemented_digests[nid]) {
- switch (nid) {
- case NID_ripemd160:
- #ifdef OLDER_OPENSSL
- *digest = &pkcs11_ripemd160;
- #else
- *digest = pkcs11_ripemd160();
- #endif
- break;
- case NID_md5:
- #ifdef OLDER_OPENSSL
- *digest = &pkcs11_md5;
- #else
- *digest = pkcs11_md5();
- #endif
- break;
- case NID_sha1:
- #ifdef OLDER_OPENSSL
- *digest = &pkcs11_sha1;
- #else
- *digest = pkcs11_sha1();
- #endif
- break;
- case NID_sha224:
- #ifdef OLDER_OPENSSL
- *digest = &pkcs11_sha224;
- #else
- *digest = pkcs11_sha224();
- #endif
- break;
- case NID_sha256:
- #ifdef OLDER_OPENSSL
- *digest = &pkcs11_sha256;
- #else
- *digest = pkcs11_sha256();
- #endif
- break;
- case NID_sha384:
- #ifdef OLDER_OPENSSL
- *digest = &pkcs11_sha384;
- #else
- *digest = pkcs11_sha384();
- #endif
- break;
- case NID_sha512:
- #ifdef OLDER_OPENSSL
- *digest = &pkcs11_sha512;
- #else
- *digest = pkcs11_sha512();
- #endif
- break;
- default:
- *digest = NULL;
- break;
- }
- }
- return (*digest != NULL);
- }
-
- void *pkcs11_dso = NULL;
-
- /* These are the static string constants for the DSO file name and the function
- * symbol names to bind to.
- */
- static const char *PKCS11_LIBNAME = NULL;
- static const char *get_PKCS11_LIBNAME(void)
- {
- if(PKCS11_LIBNAME)
- return PKCS11_LIBNAME;
- return def_PKCS11_LIBNAME;
- }
- static void free_PKCS11_LIBNAME(void)
- {
- if(PKCS11_LIBNAME)
- OPENSSL_free((void*)PKCS11_LIBNAME);
- PKCS11_LIBNAME = NULL;
- }
- static long set_PKCS11_LIBNAME(const char *name)
- {
- free_PKCS11_LIBNAME();
- return ((PKCS11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
- }
-
- /* Add new NID's based on this slot's token */
- void pkcs11_regToken(ENGINE *e, struct _token *tok)
- {
- CK_RV rv;
- CK_ULONG mech_cnt;
- CK_MECHANISM_TYPE_PTR mech_list;
- int i;
-
- DBG_fprintf("%s\n", __FUNCTION__);
-
- if (!tok)
- return;
-
- rv = pFunctionList->C_GetMechanismList(tok->slot_id, NULL_PTR, &mech_cnt);
- if (rv != CKR_OK) {
- pkcs11_die(PKCS11_F_ADDTOKEN, PKCS11_R_GETMECHANISMLIST, rv);
- goto err;
- }
-
- /* Bounds check mech_cnt ? */
- mech_list = (CK_MECHANISM_TYPE_PTR) OPENSSL_malloc(mech_cnt * sizeof(CK_MECHANISM_TYPE));
- if (mech_list == NULL) {
- pkcs11_die(PKCS11_F_ADDTOKEN, PKCS11_R_MALLOC_FAILURE, rv);
- goto err;
- }
-
- rv = pFunctionList->C_GetMechanismList(tok->slot_id, mech_list, &mech_cnt);
- if (rv != CKR_OK) {
- pkcs11_die(PKCS11_F_ADDTOKEN, PKCS11_R_GETMECHANISMLIST, rv);
- goto err_free;
- }
-
- /* Check which mechanisms are performed in hardware */
- for( i = 0; i < mech_cnt; i++ ) {
- switch (mech_list[i]) {
- case CKM_RSA_PKCS_KEY_PAIR_GEN:
- case CKM_RSA_PKCS:
- case CKM_RSA_9796:
- case CKM_RSA_X_509:
- case CKM_RSA_PKCS_OAEP:
- case CKM_RSA_X9_31:
- case CKM_RSA_X9_31_KEY_PAIR_GEN:
- case CKM_MD5_RSA_PKCS:
- #ifndef OPENSSL_NO_RSA
- DBG_fprintf("%s: registering RSA\n", __FUNCTION__);
- #ifdef OLDER_OPENSSL
- ENGINE_set_RSA(e, &pkcs11_rsa);
- #else
- ENGINE_set_RSA(e, pkcs11_rsa);
- pkcs11_rsa = RSA_meth_new("PKCS#11 RSA", 0);
- RSA_meth_set_pub_enc(pkcs11_rsa,
- pkcs11_RSA_public_encrypt);
- RSA_meth_set_pub_dec(pkcs11_rsa,
- pkcs11_RSA_public_decrypt);
- RSA_meth_set_priv_enc(pkcs11_rsa,
- pkcs11_RSA_private_encrypt);
- RSA_meth_set_priv_dec(pkcs11_rsa,
- pkcs11_RSA_private_decrypt);
- RSA_meth_set_init(pkcs11_rsa,
- pkcs11_RSA_init);
- RSA_meth_set_finish(pkcs11_rsa,
- pkcs11_RSA_finish);
- // RSA_meth_set_sign(pkcs11_rsa,
- // pkcs11_RSA_sign);
- // RSA_meth_set_verify(pkcs11_rsa,
- // pkcs11_RSA_verify);
- RSA_meth_set_keygen(pkcs11_rsa,
- pkcs11_RSA_generate_key);
- #endif
- ENGINE_set_load_privkey_function(e, pkcs11_load_privkey);
- ENGINE_set_load_pubkey_function(e, pkcs11_load_pubkey);
- #endif
- break;
- case CKM_DH_PKCS_KEY_PAIR_GEN:
- case CKM_DH_PKCS_DERIVE:
- case CKM_X9_42_DH_KEY_PAIR_GEN:
- case CKM_X9_42_DH_DERIVE:
- case CKM_X9_42_DH_HYBRID_DERIVE:
- case CKM_DH_PKCS_PARAMETER_GEN:
- case CKM_X9_42_DH_PARAMETER_GEN:
- break;
- case CKM_DES_ECB:
- tok->pkcs11_implemented_ciphers[NID_des_ecb] = 1;
- num_cipher_nids++;
- break;
- case CKM_DES_CBC:
- case CKM_DES_CBC_PAD:
- tok->pkcs11_implemented_ciphers[NID_des_cbc] = 1;
- num_cipher_nids++;
- break;
- case CKM_DES_KEY_GEN:
- case CKM_DES_MAC:
- case CKM_DES_MAC_GENERAL:
- break;
- case CKM_DES3_ECB:
- tok->pkcs11_implemented_ciphers[NID_des_ede3_ecb] = 1;
- num_cipher_nids++;
- break;
- case CKM_DES3_CBC:
- case CKM_DES3_CBC_PAD:
- tok->pkcs11_implemented_ciphers[NID_des_ede3_cbc] = 1;
- num_cipher_nids++;
- break;
- case CKM_DES3_KEY_GEN:
- case CKM_DES3_MAC:
- case CKM_DES3_MAC_GENERAL:
- break;
- case CKM_SHA_1:
- tok->pkcs11_implemented_digests[NID_sha1] = 1;
- num_digest_nids++;
- break;
- case CKM_SHA_1_HMAC:
- case CKM_SHA_1_HMAC_GENERAL:
- tok->pkcs11_implemented_digests[NID_hmacWithSHA1] = 1;
- num_digest_nids++;
- break;
- case CKM_PBA_SHA1_WITH_SHA1_HMAC:
- case CKM_SHA1_KEY_DERIVATION:
- case CKM_SHA1_RSA_PKCS:
- tok->pkcs11_implemented_digests[NID_sha1WithRSAEncryption] = 1;
- num_digest_nids++;
- break;
-
- case CKM_SHA224:
- tok->pkcs11_implemented_digests[NID_sha224] = 1;
- num_digest_nids++;
- break;
- case CKM_SHA224_KEY_DERIVATION:
- case CKM_SHA224_RSA_PKCS:
- tok->pkcs11_implemented_digests[NID_sha224WithRSAEncryption] = 1;
- num_digest_nids++;
- break;
-
-
- case CKM_SHA256:
- tok->pkcs11_implemented_digests[NID_sha256] = 1;
- num_digest_nids++;
- break;
- case CKM_SHA256_KEY_DERIVATION:
- case CKM_SHA256_RSA_PKCS:
- tok->pkcs11_implemented_digests[NID_sha256WithRSAEncryption] = 1;
- num_digest_nids++;
- break;
-
- case CKM_SHA384:
- tok->pkcs11_implemented_digests[NID_sha384] = 1;
- num_digest_nids++;
- break;
- case CKM_SHA384_KEY_DERIVATION:
- case CKM_SHA384_RSA_PKCS:
- tok->pkcs11_implemented_digests[NID_sha384WithRSAEncryption] = 1;
- num_digest_nids++;
- break;
- case CKM_SHA512:
- tok->pkcs11_implemented_digests[NID_sha512] = 1;
- num_digest_nids++;
- break;
- case CKM_SHA512_KEY_DERIVATION:
- case CKM_SHA512_RSA_PKCS:
- tok->pkcs11_implemented_digests[NID_sha512WithRSAEncryption] = 1;
- num_digest_nids++;
- break;
-
- case CKM_AES_ECB:
- tok->pkcs11_implemented_ciphers[NID_aes_128_ecb] = 1;
- tok->pkcs11_implemented_ciphers[NID_aes_192_ecb] = 1;
- tok->pkcs11_implemented_ciphers[NID_aes_256_ecb] = 1;
- num_cipher_nids += 3;
- break;
- case CKM_AES_KEY_GEN:
- break;
- case CKM_AES_CBC_PAD:
- case CKM_AES_CBC:
- tok->pkcs11_implemented_ciphers[NID_aes_128_cbc] = 1;
- tok->pkcs11_implemented_ciphers[NID_aes_192_cbc] = 1;
- tok->pkcs11_implemented_ciphers[NID_aes_256_cbc] = 1;
- num_cipher_nids += 3;
- break;
- case CKM_AES_MAC:
- case CKM_AES_MAC_GENERAL:
- break;
- case CKM_MD5:
- tok->pkcs11_implemented_digests[NID_md5] = 1;
- num_digest_nids++;
- break;
- case CKM_MD5_HMAC:
- case CKM_MD5_HMAC_GENERAL:
- case CKM_SSL3_PRE_MASTER_KEY_GEN:
- case CKM_SSL3_MASTER_KEY_DERIVE:
- case CKM_SSL3_KEY_AND_MAC_DERIVE:
- case CKM_SSL3_MD5_MAC:
- case CKM_SSL3_SHA1_MAC:
- break;
- case CKM_RIPEMD160:
- tok->pkcs11_implemented_digests[NID_ripemd160] = 1;
- num_digest_nids++;
- break;
- case CKM_RIPEMD160_HMAC:
- case CKM_RIPEMD160_HMAC_GENERAL:
- break;
- default:
- DBG_fprintf("The token in slot %lx has reported that it can "
- "perform\nmechanism 0x%lx, which is not available to "
- "accelerate in openssl.\n", tok->slot_id, mech_list[i]);
- break;
- }
- }
-
- err_free:
- OPENSSL_free(mech_list);
- err:
- return;
- }
-
- /* Add a new token struct to the list
- * This is called during the bind_pkcs11, in other words after openSSL has
- * decided to use us for some operation.
- */
- struct _token *pkcs11_addToken(CK_SLOT_ID slot_id)
- {
- struct _token *new_tok = (struct _token *) OPENSSL_malloc(sizeof(struct _token));
-
- if (new_tok == NULL) {
- PKCS11err(PKCS11_F_ADDTOKEN, PKCS11_R_MALLOC_FAILURE);
- return NULL;
- }
-
- memset(new_tok, 0, sizeof(struct _token));
- new_tok->slot_id = slot_id;
-
- new_tok->token_next = pkcs11_token_list;
- pkcs11_token_list = new_tok;
-
- return new_tok;
- }
-
- /*
- * pre_init_pkcs11: this is called at openSSL startup. Here is where we
- * try to convince openSSL to use us. If it decides not to, there is no
- * guarantee that we will ever be asked to clean up. So everything we
- * do must be self-contained.
- */
- static int pre_init_pkcs11(ENGINE *e)
- {
- CK_C_GetFunctionList p;
- CK_RV rv = CKR_OK;
- CK_INFO Info;
- CK_SLOT_ID_PTR pSlotList;
- CK_ULONG ulSlotCount;
- CK_SLOT_INFO slotInfo;
- struct _token *tok;
- int i;
-
- if(pkcs11_dso)
- {
- PKCS11err(PKCS11_F_PREINIT, PKCS11_R_ALREADY_LOADED);
- goto err;
- }
-
- /* Attempt to load PKCS#11 library */
- pkcs11_dso = dlopen(get_PKCS11_LIBNAME(), RTLD_NOW);
-
- if(pkcs11_dso == NULL)
- {
- PKCS11err(PKCS11_F_PREINIT, PKCS11_R_DSO_FAILURE);
- goto err;
- }
-
- /* get the C_GetFunctionList function from the loaded library */
- p = (CK_C_GetFunctionList)dlsym(pkcs11_dso, PKCS11_GET_FUNCTION_LIST);
- if ( !p )
- {
- PKCS11err(PKCS11_F_PREINIT, PKCS11_R_DSO_FAILURE);
- goto err;
- }
-
- /* get the full function list from the loaded library */
- rv = p(&pFunctionList);
- if (rv != CKR_OK)
- {
- pkcs11_die(PKCS11_F_PREINIT, PKCS11_R_DSO_FAILURE, rv);
- goto err;
- }
-
- #ifdef BULL_CRYPTOBOX
- /* the address of the CryptoBox is in /etc/CryptoBox */
- rv = C_InitializeRpc (NULL, NULL, NULL);
- if (rv != CKR_OK)
- goto err;
- #endif
-
- /* Initialize Cryptoki */
- rv = pFunctionList->C_Initialize(NULL_PTR);
- if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
- {
- pkcs11_die(PKCS11_F_PREINIT, PKCS11_R_INITIALIZE, rv);
- goto err;
- }
- rv = pFunctionList->C_GetInfo(&Info);
- if (rv != CKR_OK)
- {
- pkcs11_die(PKCS11_F_PREINIT, PKCS11_R_GETINFO, rv);
- pFunctionList->C_Finalize(NULL);
- goto err;
- }
-
- if (strncmp((char *)Info.libraryDescription, BULL_TRUSTWAY_LIBRARY_DESCRIPTION, 32))
- {
- rv = pFunctionList->C_GetSlotList(TRUE, NULL_PTR, &ulSlotCount);
- if ((rv != CKR_OK) || (ulSlotCount == 0))
- {
- pkcs11_die(PKCS11_F_PREINIT, PKCS11_R_GETSLOTLIST, rv);
- }
- else
- {
- pSlotList = (CK_SLOT_ID_PTR) OPENSSL_malloc(ulSlotCount * sizeof(CK_SLOT_ID));
- if ( pSlotList != NULL)
- {
- rv = pFunctionList->C_GetSlotList(TRUE, pSlotList, &ulSlotCount);
- if (rv != CKR_OK)
- {
- pkcs11_die(PKCS11_F_PREINIT, PKCS11_R_GETSLOTLIST, rv);
- pFunctionList->C_Finalize(NULL);
- OPENSSL_free(pSlotList);
- goto err;
- }
-
- /* Check each slot to see if there's a hardware token present.
- */
- for (i = 0; i < ulSlotCount; i++)
- {
- rv = pFunctionList->C_GetSlotInfo(pSlotList[i], &slotInfo);
- if (rv != CKR_OK)
- {
- pkcs11_die(PKCS11_F_PREINIT, PKCS11_R_GETSLOTINFO,
- rv);
- pFunctionList->C_Finalize(NULL);
- OPENSSL_free(pSlotList);
- goto err;
- }
-
- /* we're mallocing memory here that may need to be freed
- * if openssl chooses not to use us. We'll free it in
- * the library destructor, pkcs11_engine_destructor */
- tok = pkcs11_addToken(pSlotList[i]);
- pkcs11_regToken(e, tok);
- }
- OPENSSL_free(pSlotList);
- }
- }
- }
- else
- {
- /* Bull Trustway CC2000 crypto hardware detected */
- Bull_TrustWay = TRUE;
- SLOTID = 0xFFFFFFFF;
- }
-
- /* Finish with Cryptoki: We will restart if openSSL calls one of our
- * functions */
- pFunctionList->C_Finalize(NULL);
- dlclose(pkcs11_dso);
- pkcs11_dso = NULL;
-
- return 1;
-
- err:
- if(pkcs11_dso)
- dlclose(pkcs11_dso);
- pkcs11_dso = NULL;
- return 0;
- }
-
- /* initialization function */
- /* This is called when openSSL has decided to use us, and warns us to
- * initialize. pkcs11_finish will be called when all is done. */
- static int pkcs11_init(ENGINE *e)
- {
- CK_C_GetFunctionList p;
- CK_RV rv = CKR_OK;
- CK_INFO Info;
- CK_SLOT_ID_PTR pSlotList;
- CK_ULONG ulSlotCount;
- CK_SLOT_INFO slotInfo;
- int i;
-
- if(pkcs11_dso)
- {
- PKCS11err(PKCS11_F_INIT, PKCS11_R_ALREADY_LOADED);
- goto err;
- }
-
- /* Attempt to load PKCS#11 library */
- pkcs11_dso = dlopen(get_PKCS11_LIBNAME(), RTLD_NOW);
-
- if(pkcs11_dso == NULL)
- {
- PKCS11err(PKCS11_F_INIT, PKCS11_R_DSO_FAILURE);
- goto err;
- }
-
- /* get the C_GetFunctionList function from the loaded library */
- p = (CK_C_GetFunctionList)dlsym(pkcs11_dso, PKCS11_GET_FUNCTION_LIST);
- if ( !p )
- {
- PKCS11err(PKCS11_F_INIT, PKCS11_R_DSO_FAILURE);
- goto err;
- }
-
- /* get the full function list from the loaded library */
- rv = p(&pFunctionList);
- if (rv != CKR_OK)
- {
- pkcs11_die(PKCS11_F_INIT, PKCS11_R_DSO_FAILURE, rv);
- goto err;
- }
-
- #ifdef BULL_CRYPTOBOX
- /* the address of the CryptoBox is in /etc/CryptoBox */
- rv = C_InitializeRpc (NULL, NULL, NULL);
- if (rv != CKR_OK)
- goto err;
- #endif
-
- rv = pFunctionList->C_Initialize(NULL_PTR);
- if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
- {
- pkcs11_die(PKCS11_F_INIT, PKCS11_R_INITIALIZE, rv);
- goto err;
- }
- rv = pFunctionList->C_GetInfo(&Info);
- if (rv != CKR_OK)
- {
- pkcs11_die(PKCS11_F_INIT, PKCS11_R_GETINFO, rv);
- pFunctionList->C_Finalize(NULL);
- goto err;
- }
-
- if (strncmp((char *)Info.libraryDescription, BULL_TRUSTWAY_LIBRARY_DESCRIPTION, 32))
- {
- rv = pFunctionList->C_GetSlotList(TRUE, NULL_PTR, &ulSlotCount);
- if ((rv != CKR_OK) || (ulSlotCount == 0))
- {
- pkcs11_die(PKCS11_F_INIT, PKCS11_R_GETSLOTLIST, rv);
- }
- else
- {
- pSlotList = (CK_SLOT_ID_PTR) OPENSSL_malloc(ulSlotCount * sizeof(CK_SLOT_ID));
- if ( pSlotList != NULL)
- {
- rv = pFunctionList->C_GetSlotList(TRUE, pSlotList, &ulSlotCount);
- if (rv != CKR_OK)
- {
- pkcs11_die(PKCS11_F_INIT, PKCS11_R_GETSLOTLIST, rv);
- pFunctionList->C_Finalize(NULL);
- OPENSSL_free(pSlotList);
- goto err;
- }
-
- /* Check each slot to see if there's a hardware token present.
- */
- for (i = 0; i < ulSlotCount; i++)
- {
- rv = pFunctionList->C_GetSlotInfo(pSlotList[i], &slotInfo);
- if (rv != CKR_OK)
- {
- pkcs11_die(PKCS11_F_INIT, PKCS11_R_GETSLOTINFO, rv);
- pFunctionList->C_Finalize(NULL);
- OPENSSL_free(pSlotList);
- goto err;
- }
-
- pkcs11_addToken(pSlotList[i]);
- }
- OPENSSL_free(pSlotList);
- }
- }
- }
- else
- {
- /* Bull Trustway CC2000 crypto hardware detected */
- Bull_TrustWay = TRUE;
- SLOTID = 0xFFFFFFFF;
- }
-
- #ifndef OPENSSL_NO_RSA
- /* Everything's fine. */
- if (rsaPubKey == -1)
- rsaPubKey = RSA_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- if (rsaPrivKey == -1)
- rsaPrivKey = RSA_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- if (deletePubKeyOnFree == -1)
- deletePubKeyOnFree = RSA_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- if (deletePrivKeyOnFree == -1)
- deletePrivKeyOnFree = RSA_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- if (pkcs11Session == -1)
- pkcs11Session = RSA_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- #endif
-
- if (pkcs11_token_list == NULL)
- PKCS11err(PKCS11_F_INIT, PKCS11_R_NOTOKENS);
-
- PKCS11_Initialized = 1;
-
- /* TODO: This should only be done on linux systems */
- pthread_atfork(NULL, NULL, (void(*)())pkcs11_atfork_init);
-
- return 1;
-
- err:
- if(pkcs11_dso)
- dlclose(pkcs11_dso);
- pkcs11_dso = NULL;
- return 0;
- }
-
- /* Destructor (complements the "ENGINE_pkcs11()" constructor) */
- /* XXX HUH? Can we just DSO_load once, then??? */
- static int pkcs11_destroy(ENGINE *e)
- {
- DBG_fprintf("%s: called\n", __FUNCTION__);
-
- #ifndef OLDER_OPENSSL
- pkcs11_des_ecb_destroy();
- pkcs11_des_cbc_destroy();
- pkcs11_tdes_ecb_destroy();
- pkcs11_tdes_cbc_destroy();
- pkcs11_aes_128_cbc_destroy();
- pkcs11_aes_192_cbc_destroy();
- pkcs11_aes_256_cbc_destroy();
- pkcs11_aes_128_ecb_destroy();
- pkcs11_aes_192_ecb_destroy();
- pkcs11_aes_256_ecb_destroy();
- pkcs11_sha1_destroy();
- pkcs11_sha224_destroy();
- pkcs11_sha256_destroy();
- pkcs11_sha384_destroy();
- pkcs11_sha512_destroy();
- pkcs11_md5_destroy();
- pkcs11_ripemd160_destroy();
- #endif
-
- free_PKCS11_LIBNAME();
- ERR_unload_pkcs11_strings();
- return 1;
- }
-
- /* termination function */
- static int pkcs11_finish(ENGINE *e)
- {
- struct _token *tmp;
-
- if(pkcs11_dso == NULL)
- {
- PKCS11err(PKCS11_F_FINISH, PKCS11_R_NOT_LOADED);
- goto err;
- }
- assert(pFunctionList != NULL);
-
- while (pkcs11_token_list) {
- tmp = pkcs11_token_list->token_next;
- OPENSSL_free(pkcs11_token_list);
- pkcs11_token_list = tmp;
- }
-
- pFunctionList->C_Finalize(NULL);
-
- if(dlclose(pkcs11_dso))
- { PKCS11err(PKCS11_F_FINISH, PKCS11_R_DSO_FAILURE);
- goto err;
- }
- pkcs11_dso = NULL;
- pFunctionList = NULL;
-
- return 1;
-
- err:
- pkcs11_dso = NULL;
- pFunctionList = NULL;
- return 0;
- }
-
- static int pkcs11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
- {
- int initialized = ((pkcs11_dso == NULL) ? 0 : 1);
- struct _token *tok;
-
- switch(cmd)
- {
- case PKCS11_CMD_SO_PATH:
- if(p == NULL)
- {
- PKCS11err(PKCS11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
- if(initialized)
- {
- PKCS11err(PKCS11_F_CTRL, PKCS11_R_ALREADY_LOADED);
- return 0;
- }
- return set_PKCS11_LIBNAME((const char*)p);
- case PKCS11_CMD_SLOT_ID:
- tok = pkcs11_token_list;
- while (tok) {
- if (tok->slot_id == i) {
- pkcs11_token = tok;
- DBG_fprintf("slot %ld selected\n", i);
- return 1;
- }
- tok = tok->token_next;
- }
- PKCS11err(PKCS11_F_CTRL, PKCS11_R_TOKEN_NOT_AVAILABLE);
- return 0;
- default:
- break;
- }
- PKCS11err(PKCS11_F_CTRL,PKCS11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
- return 0;
- }
-
- #ifndef OPENSSL_NO_RSA
- CK_OBJECT_HANDLE pkcs11_FindOrCreateKey(CK_SESSION_HANDLE h,
- RSA *rsa,
- CK_OBJECT_CLASS oKey,
- CK_BBOOL fKeyCreate)
- {
- CK_RV rv;
- CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
- CK_ULONG Matches;
- CK_KEY_TYPE kType = CKK_RSA;
- CK_ULONG ulKeyAttributeCount;
-
- #ifndef OLDER_OPENSSL
- const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
- #endif
-
- CK_ATTRIBUTE pubKeyTemplate[] =
- {
- {CKA_CLASS, &oKey, sizeof(CK_OBJECT_CLASS)},
- {CKA_KEY_TYPE, &kType, sizeof(CK_KEY_TYPE)},
- {CKA_MODULUS, (void *)NULL, 0},
- {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
- };
- CK_ATTRIBUTE privKeyTemplate[] =
- {
- {CKA_CLASS, &oKey, sizeof(CK_OBJECT_CLASS)},
- {CKA_KEY_TYPE, &kType, sizeof(CK_KEY_TYPE)},
- {CKA_MODULUS, (void *)NULL, 0},
- {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
- {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
- {CKA_PRIME_1, (void *)NULL, 0},
- {CKA_PRIME_2, (void *)NULL, 0},
- {CKA_EXPONENT_1, (void *)NULL, 0},
- {CKA_EXPONENT_2, (void *)NULL, 0},
- {CKA_COEFFICIENT, (void *)NULL, 0}
- };
- long deletePubKey;
-
- DBG_fprintf("%s\n", __FUNCTION__);
-
- if (oKey == CKO_PUBLIC_KEY) {
- DBG_fprintf("looking up a public key\n");
-
- #ifdef OLDER_OPENSSL
- pubKeyTemplate[2].ulValueLen = BN_num_bytes(rsa->n);
- pubKeyTemplate[3].ulValueLen = BN_num_bytes(rsa->e);
- #else
- RSA_get0_key(rsa, &n, &e, NULL);
- pubKeyTemplate[2].ulValueLen = BN_num_bytes(n);
- pubKeyTemplate[3].ulValueLen = BN_num_bytes(e);
- #endif
-
- pubKeyTemplate[2].pValue = (CK_VOID_PTR)OPENSSL_malloc(
- (size_t)pubKeyTemplate[2].ulValueLen);
- pubKeyTemplate[3].pValue = (CK_VOID_PTR)OPENSSL_malloc(
- (size_t)pubKeyTemplate[3].ulValueLen);
-
- #ifdef OLDER_OPENSSL
- BN_bn2bin(rsa->n, pubKeyTemplate[2].pValue);
- BN_bn2bin(rsa->e, pubKeyTemplate[3].pValue);
- #else
- BN_bn2bin(n, pubKeyTemplate[2].pValue);
- BN_bn2bin(e, pubKeyTemplate[3].pValue);
- #endif
-
- ulKeyAttributeCount = 4;
- rv = pFunctionList->C_FindObjectsInit(h, pubKeyTemplate, ulKeyAttributeCount);
- } else {
- DBG_fprintf("looking up a private key\n");
-
- #ifdef OLDER_OPENSSL
- privKeyTemplate[2].ulValueLen = BN_num_bytes(rsa->n);
- privKeyTemplate[4].ulValueLen = BN_num_bytes(rsa->d);
- privKeyTemplate[5].ulValueLen = BN_num_bytes(rsa->p);
- privKeyTemplate[6].ulValueLen = BN_num_bytes(rsa->q);
- privKeyTemplate[7].ulValueLen = BN_num_bytes(rsa->dmp1);
- privKeyTemplate[8].ulValueLen = BN_num_bytes(rsa->dmq1);
- privKeyTemplate[9].ulValueLen = BN_num_bytes(rsa->iqmp);
- #else
- RSA_get0_key(rsa, &n, NULL, &d);
- RSA_get0_factors(rsa, &p, &q);
- RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
- privKeyTemplate[2].ulValueLen = BN_num_bytes(n);
- privKeyTemplate[4].ulValueLen = BN_num_bytes(d);
- privKeyTemplate[5].ulValueLen = BN_num_bytes(p);
- privKeyTemplate[6].ulValueLen = BN_num_bytes(q);
- privKeyTemplate[7].ulValueLen = BN_num_bytes(dmp1);
- privKeyTemplate[8].ulValueLen = BN_num_bytes(dmq1);
- privKeyTemplate[9].ulValueLen = BN_num_bytes(iqmp);
- #endif
-
- privKeyTemplate[2].pValue = (CK_VOID_PTR)OPENSSL_malloc(
|