diff options
Diffstat (limited to 'ckcapi-session.c')
-rw-r--r-- | ckcapi-session.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/ckcapi-session.c b/ckcapi-session.c index 46de60a..0745cb7 100644 --- a/ckcapi-session.c +++ b/ckcapi-session.c @@ -23,10 +23,20 @@ #include "ckcapi-builtin.h" #include "ckcapi-cert.h" #include "ckcapi-object.h" +#include "ckcapi-rsa.h" #include "ckcapi-session.h" #include "ckcapi-token.h" #include "ckcapi-trust.h" +/* For operation_type in CkCapiSession */ +enum +{ + OPERATION_NONE, + OPERATION_FIND, + OPERATION_SIGN, + OPERATION_DECRYPT +}; + static CkCapiArray* all_sessions = NULL; static void @@ -721,3 +731,192 @@ ckcapi_session_find_final(CkCapiSession* sess) } +/* ---------------------------------------------------------------------------- + * CRYPTO OPERATIONS + */ + +typedef struct _CryptoContext +{ + CK_MECHANISM_TYPE mech_type; + CkCapiDestroyFunc mech_cleanup; + void* mech_data; +} +CryptoContext; + +void +cleanup_crypto_operation(CkCapiSession* sess) +{ + CryptoContext* ctx; + + if(sess->operation_data) + { + ctx = (CryptoContext*)sess->operation_data; + if(ctx->mech_cleanup) + (ctx->mech_cleanup)(ctx->mech_data); + free(ctx); + } + + sess->operation_type = OPERATION_NONE; + sess->operation_data = NULL; + sess->operation_cancel = NULL; +} + +CK_RV +ckcapi_session_sign_init(CkCapiSession* sess, CK_MECHANISM_PTR mech, + CkCapiObjectData *objdata) +{ + CryptoContext* ctx; + CK_RV ret; + + ASSERT(sess); + ASSERT(mech); + ASSERT(objdata); + + if(sess->operation_type != OPERATION_NONE) + return CKR_OPERATION_ACTIVE; + + ctx = calloc(1, sizeof(CryptoContext)); + if(!ctx) + return CKR_HOST_MEMORY; + + ctx->mech_type = mech->mechanism; + + switch(mech->mechanism) + { + case CKM_RSA_PKCS: + ret = ckcapi_rsa_pkcs_sign_init(objdata, &ctx->mech_data); + ctx->mech_cleanup = ckcapi_rsa_pkcs_sign_cleanup; + default: + ret = CKR_MECHANISM_INVALID; + }; + + if(ret != CKR_OK) + { + free(ctx); + ASSERT(!sess->operation_data); + return ret; + } + + sess->operation_type = OPERATION_SIGN; + sess->operation_data = ctx; + sess->operation_cancel = cleanup_crypto_operation; + return CKR_OK; +} + +CK_RV +ckcapi_session_sign(CkCapiSession* sess, CK_BYTE_PTR data, CK_ULONG n_data, + CK_BYTE_PTR signature, CK_ULONG_PTR n_signature) +{ + CryptoContext *ctx; + BOOL incomplete; + CK_RV ret; + + ASSERT(sess); + ASSERT(data); + ASSERT(n_data); + + if(sess->operation_type != OPERATION_SIGN) + return CKR_OPERATION_NOT_INITIALIZED; + + ctx = (CryptoContext*)sess->operation_data; + switch(ctx->mech_type) + { + case CKM_RSA_PKCS: + ret = ckcapi_rsa_pkcs_sign_perform(data, n_data, signature, n_signature, + &ctx->mech_data); + break; + + default: + ASSERT(FALSE); + ret = CKR_GENERAL_ERROR; + break; + } + + /* Buffer calculation, we don't end operation */ + incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !signature)); + + if(!incomplete) + cleanup_crypto_operation(sess); + + return ret; +} + +CK_RV +ckcapi_session_decrypt_init(CkCapiSession* sess, CK_MECHANISM_PTR mech, + CkCapiObjectData *objdata) +{ + CryptoContext* ctx; + CK_RV ret; + + ASSERT(sess); + ASSERT(mech); + ASSERT(objdata); + + if(sess->operation_type != OPERATION_NONE) + return CKR_OPERATION_ACTIVE; + + ctx = calloc(1, sizeof(CryptoContext)); + if(!ctx) + return CKR_HOST_MEMORY; + + ctx->mech_type = mech->mechanism; + + switch(mech->mechanism) + { + case CKM_RSA_PKCS: + ret = ckcapi_rsa_pkcs_decrypt_init(objdata, &ctx->mech_data); + ctx->mech_cleanup = ckcapi_rsa_pkcs_decrypt_cleanup; + default: + ret = CKR_MECHANISM_INVALID; + }; + + if(ret != CKR_OK) + { + free(ctx); + ASSERT(!sess->operation_data); + return ret; + } + + sess->operation_type = OPERATION_DECRYPT; + sess->operation_data = ctx; + sess->operation_cancel = cleanup_crypto_operation; + return CKR_OK; +} + +CK_RV +ckcapi_session_decrypt(CkCapiSession* sess, CK_BYTE_PTR encdata, CK_ULONG n_encdata, + CK_BYTE_PTR result, CK_ULONG_PTR n_result) +{ + CryptoContext *ctx; + BOOL incomplete; + CK_RV ret; + + ASSERT(sess); + ASSERT(encdata); + ASSERT(n_encdata); + + if(sess->operation_type != OPERATION_DECRYPT) + return CKR_OPERATION_NOT_INITIALIZED; + + ctx = (CryptoContext*)sess->operation_data; + switch(ctx->mech_type) + { + case CKM_RSA_PKCS: + ret = ckcapi_rsa_pkcs_decrypt_perform(encdata, n_encdata, result, n_result, + &ctx->mech_data); + break; + + default: + ASSERT(FALSE); + ret = CKR_GENERAL_ERROR; + break; + } + + /* Buffer calculation, we don't end operation */ + incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !result)); + + if(!incomplete) + cleanup_crypto_operation(sess); + + return ret; +} |