From 2f086f5261d945f95e3d5dfafe90fbab9ad54bd2 Mon Sep 17 00:00:00 2001 From: fabled Date: Mon, 22 Oct 2001 21:09:17 +0000 Subject: [PATCH] Implementid basic signing functionality. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@24 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/pkcs11/digestsign.c | 107 +++++++++++++++++++++++++++++++++++++--- src/pkcs11/sc-pkcs11.h | 8 +++ src/pkcs11/slot.c | 57 +++++++++++++++++---- 3 files changed, 157 insertions(+), 15 deletions(-) diff --git a/src/pkcs11/digestsign.c b/src/pkcs11/digestsign.c index 7245a740..6b6e06e8 100644 --- a/src/pkcs11/digestsign.c +++ b/src/pkcs11/digestsign.c @@ -1,5 +1,24 @@ +#include +#include + #include "sc-pkcs11.h" +static void hex_dump(const unsigned char *buf, int count) +{ + int i; + for (i = 0; i < count; i++) { + unsigned char c = buf[i]; + int printch = 0; + if (!isalnum(c) && !ispunct(c) && !isspace(c)) + printch = 0; + if (printch) + LOG("%02X%c ", c, c); + else + LOG("%02X ", c); + } + LOG("\n"); +} + CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism) /* the digesting mechanism */ { @@ -44,8 +63,41 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ CK_OBJECT_HANDLE hKey) /* handle of the signature key */ { - LOG("C_SignInit\n"); - return CKR_FUNCTION_NOT_SUPPORTED; + struct pkcs11_slot *slt; + struct pkcs11_session *ses; + struct pkcs11_object *object; + + LOG("C_SignInit(%d, {%d, 0x%x, %d}, %d)\n", + hSession, + pMechanism->mechanism, pMechanism->pParameter, pMechanism->ulParameterLen, + hKey); + + if (hSession < 1 || hSession > PKCS11_MAX_SESSIONS || session[hSession] == NULL) + return CKR_SESSION_HANDLE_INVALID; + ses = session[hSession]; + slt = &slot[ses->slot]; + if (hKey < 1 || hKey > slt->num_objects) + return CKR_OBJECT_HANDLE_INVALID; + object = slt->object[hKey]; + + if (object->object_type != CKO_PRIVATE_KEY) + return CKR_OBJECT_HANDLE_INVALID; + + switch (pMechanism->mechanism) { + case CKM_RSA_PKCS: + // Signing according to PKCS#1 standard + LOG("CKM_RSA_PKCS mechanism requested\n"); + ses->sign.algorithm_ref = 0x02; + break; + default: + LOG("Requested mechanism #d not supported\n", pMechanism->mechanism); + break; + } + + LOG("Token id is %d\n", object->token_id); + ses->sign.private_key_id = object->token_id; + + return CKR_OK; } CK_RV C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */ @@ -54,15 +106,57 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* receives the signature */ CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */ { - LOG("C_Sign\n"); - return CKR_FUNCTION_NOT_SUPPORTED; + char signature[1024]; + struct sc_pkcs15_card *p15card; + struct sc_security_env senv; + struct pkcs11_session *ses; + int i, c; + + LOG("C_Sign(%d, 0x%x, %d, 0x%x, 0x%x)\n", + hSession, pData, ulDataLen, pSignature, pulSignatureLen); + hex_dump(pData, ulDataLen); + + if (hSession < 1 || hSession > PKCS11_MAX_SESSIONS || session[hSession] == NULL) + return CKR_SESSION_HANDLE_INVALID; + ses = session[hSession]; + p15card = slot[ses->slot].p15card; + + senv.signature = 1; + senv.algorithm_ref = ses->sign.algorithm_ref; //0x02; + senv.key_ref = 0; + senv.key_file_id = p15card->prkey_info[ses->sign.private_key_id].file_id; + senv.app_df_path = p15card->file_app.path; + i = sc_set_security_env(p15card->card, &senv); + if (i) { + LOG("Security environment set failed: %s\n", sc_strerror(i)); + return CKR_DEVICE_ERROR; + } + + c = sc_compute_signature(p15card->card, pData, ulDataLen, signature, sizeof(signature)); + if (c < 0) { + LOG("Compute signature failed: (%d) %s\n", c, sc_strerror(c)); + return CKR_DEVICE_ERROR; + } + + if (*pulSignatureLen < c) { + LOG("Buffer too small, %d < %d\n", *pulSignatureLen, c); + return CKR_BUFFER_TOO_SMALL; + } + + LOG("Got signature, %d bytes (buffer was %d)\n", c, *pulSignatureLen); + hex_dump(signature, c); + memcpy(pSignature, signature, c); + *pulSignatureLen = c; + + return CKR_OK; } CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pPart, /* the data (digest) to be signed */ CK_ULONG ulPartLen) /* count of bytes to be signed */ { - LOG("C_SignUpdate\n"); + LOG("C_SignUpdate(%d, 0x%x, %d)\n", + hSession, pPart, ulPartLen); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -70,7 +164,8 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* receives the signature */ CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */ { - LOG("C_SignFinal\n"); + LOG("C_SignFinal(%d, 0x%x, %d)\n", + hSession, pSignature, pulSignatureLen); return CKR_FUNCTION_NOT_SUPPORTED; } diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 1b950962..89e49965 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -5,6 +5,7 @@ #include "pkcs11/pkcs11.h" #include "../sc.h" +#include "../sc-pkcs15.h" #define PKCS11_MAX_SLOTS 4 #define PKCS11_MAX_SESSIONS 8 @@ -12,6 +13,7 @@ // Object information struct pkcs11_object { + int object_type, token_id; int num_attributes; CK_ATTRIBUTE_PTR attribute; }; @@ -21,6 +23,11 @@ struct pkcs11_search_context { int num_matches, position; CK_OBJECT_HANDLE handles[PKCS11_MAX_OBJECTS]; }; +// Signing information +struct pkcs11_sign_context { + int private_key_id; + int algorithm_ref; +}; // Per session information; "context" struct pkcs11_session { @@ -31,6 +38,7 @@ struct pkcs11_session { CK_VOID_PTR notify_parameter; struct pkcs11_search_context search; + struct pkcs11_sign_context sign; //... }; diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 204576b7..fd06d0f1 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -2,6 +2,30 @@ #include #include "sc-pkcs11.h" +static CK_BYTE modulus[] = +#if 0 + "\x00\xc7\x50\xbb\x9e\xf7\x43\x18\x7e\x8d\xb5\xe3\xa1\x6e\x4c" + "\x8c\x0f\x0f\xc7\x9a\xce\xad\x05\x1b\x16\xf0\x30\x25\xdb\x1f" + "\xbd\xf3\x68\x76\x29\xee\x75\x97\xba\x20\x1a\x48\xa8\x55\xa1" + "\x50\x91\x45\x0e\x64\x70\xcd\xda\x52\x0b\x67\x94\x16\x89\x73" + "\x7d\xa1\x7c\x5b\xa9\x29\xd8\xe2\x38\xc8\x24\x73\xaa\xc1\x7a" + "\x99\x6f\x4f\xe9\xa6\xcc\x9e\x02\xd4\xb2\xf1\xf5\xe5\x94\x1f" + "\x30\x70\x6c\x29\xe6\x65\x06\x55\x67\xc5\xa7\x35\x82\x5c\x6d" + "\x4d\xe7\x60\x83\xf4\x0c\xed\xbe\x6b\xb1\xc3\xe4\x55\x99\x7f" + "\x79\x07\x99\x2f\x65\x8b\xe5\x89\xe5"; +#else + "\x00\xba\xb3\xc3\x65\xfb\xab\xd3\x4f\xf1\xe8\x72\xb8\xaa\x48" + "\x6a\x82\x31\x43\xc9\x3e\xe6\xff\x6b\xb6\x0e\xa3\x82\xb4\xda" + "\x3f\xed\xa6\x0b\xbc\xf2\xd3\xad\x53\x88\x88\x14\x14\x3f\x2b" + "\x24\x8d\xd7\x3f\x4b\xb3\xe6\xc1\xb9\xb1\x4d\x3a\x10\xc4\x65" + "\xdc\xe2\xa1\x27\xd2\x8f\xb2\x67\x54\x34\x73\x53\xeb\xec\x84" + "\xab\xdd\xc1\x76\xc9\x73\x49\x4c\x7c\x18\x98\xd3\x40\xc4\x1c" + "\xfd\x0d\x6b\xae\xb7\x9f\x44\xc6\x0a\x5a\x89\x91\xb8\x6e\x20" + "\x38\x2b\xff\x42\xf7\xfe\x95\xc0\x1f\xa5\xca\x07\x2e\x4a\xb0" + "\x9c\x07\x60\x02\x61\xe1\x8b\x25\x01"; +#endif + + void set_attribute(CK_ATTRIBUTE_PTR attr, CK_OBJECT_CLASS oc, void *ptr, int len) { attr->type = oc; @@ -10,35 +34,50 @@ void set_attribute(CK_ATTRIBUTE_PTR attr, CK_OBJECT_CLASS oc, void *ptr, int len attr->ulValueLen = len; } -int slot_add_object(int id, CK_ATTRIBUTE_PTR object, int num_attrs) +int slot_add_object(int id, int token_id, CK_ATTRIBUTE_PTR object, int num_attrs) { struct pkcs11_slot *slt = &slot[id]; - int idx; + int idx, i; if (slt->num_objects >= PKCS11_MAX_OBJECTS) return CKR_BUFFER_TOO_SMALL; idx = ++slt->num_objects; slt->object[idx] = (struct pkcs11_object*) malloc(sizeof(struct pkcs11_object)); + slt->object[idx]->object_type = -1; + slt->object[idx]->token_id = token_id; slt->object[idx]->num_attributes = num_attrs; slt->object[idx]->attribute = object; + for (i = 0; i < num_attrs; i++) { + if (object[i].type == CKA_CLASS && object[i].ulValueLen == 4) { + slt->object[idx]->object_type = *(int*)object[i].pValue; + break; + } + } + return CKR_OK; } -int slot_add_private_key_object(int id, struct sc_pkcs15_prkey_info *key) +int slot_add_private_key_object(int id, int token_id, struct sc_pkcs15_prkey_info *key) { static CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; - CK_ATTRIBUTE_PTR object = (CK_ATTRIBUTE_PTR) malloc(sizeof(CK_ATTRIBUTE) * 3); + static CK_BBOOL btrue = 1; + static CK_KEY_TYPE rsakey = CKK_RSA; + CK_ATTRIBUTE_PTR object = (CK_ATTRIBUTE_PTR) malloc(sizeof(CK_ATTRIBUTE) * 6); set_attribute(&object[0], CKA_CLASS, &key_class, sizeof(key_class)); set_attribute(&object[1], CKA_LABEL, key->com_attr.label, strlen(key->com_attr.label)); set_attribute(&object[2], CKA_ID, key->id.value, key->id.len); + set_attribute(&object[3], CKA_TOKEN, &btrue, sizeof(btrue)); + set_attribute(&object[4], CKA_KEY_TYPE, &rsakey, sizeof(rsakey)); + set_attribute(&object[5], CKA_MODULUS, modulus, sizeof(modulus)-1); - return slot_add_object(id, object, 3); + return slot_add_object(id, token_id, object, 6); } -int slot_add_certificate_object(int id, struct sc_pkcs15_cert_info *cert, +int slot_add_certificate_object(int id, int token_id, + struct sc_pkcs15_cert_info *cert, u8 *x509data, int x509length) { static CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; @@ -49,7 +88,7 @@ int slot_add_certificate_object(int id, struct sc_pkcs15_cert_info *cert, set_attribute(&object[2], CKA_ID, cert->id.value, cert->id.len); set_attribute(&object[3], CKA_VALUE, x509data, x509length); - return slot_add_object(id, object, 4); + return slot_add_object(id, token_id, object, 4); } int slot_connect(int id) @@ -96,7 +135,7 @@ int slot_connect(int id) return len; LOG("Adding '%s' certificate object.\n", p15card->cert_info[c].com_attr.label); - slot_add_certificate_object(id, &p15card->cert_info[c], + slot_add_certificate_object(id, c, &p15card->cert_info[c], buf, len); } @@ -107,7 +146,7 @@ int slot_connect(int id) LOG("Found total of %d private keys.\n", r); for (c = 0; c < r; c++) { LOG("Adding '%s' private key object.\n", p15card->prkey_info[c].com_attr.label); - slot_add_private_key_object(id, &p15card->prkey_info[c]); + slot_add_private_key_object(id, c, &p15card->prkey_info[c]); } return CKR_OK;