Added more signature infrestructure.

This commit is contained in:
Alessio Di Mauro
2015-08-04 19:19:04 +02:00
parent 7ce5ea4dc2
commit d312d7a1e1
8 changed files with 293 additions and 54 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ libykcs11_la_SOURCES += token_vendors.c token_vendor.h
libykcs11_la_SOURCES += mechanisms.c mechanisms.h libykcs11_la_SOURCES += mechanisms.c mechanisms.h
libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h
libykcs11_la_SOURCES += utils.c utils.h libykcs11_la_SOURCES += utils.c utils.h
libykcs11_la_SOURCES += openssl_utils.c openssl_utils.h libykcs11_la_SOURCES += openssl_utils.c openssl_utils.h openssl_types.h
libykcs11_la_SOURCES += objects.c objects.h obj_types.h libykcs11_la_SOURCES += objects.c objects.h obj_types.h
#internal.h #internal.h
+99 -6
View File
@@ -53,8 +53,6 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) {
case CKM_RSA_PKCS: case CKM_RSA_PKCS:
case CKM_RSA_9796: case CKM_RSA_9796:
case CKM_RSA_X_509: case CKM_RSA_X_509:
case CKM_MD2_RSA_PKCS:
case CKM_MD5_RSA_PKCS:
case CKM_SHA1_RSA_PKCS: case CKM_SHA1_RSA_PKCS:
// case CKM_SHA224_RSA_PKCS: // case CKM_SHA224_RSA_PKCS:
case CKM_SHA256_RSA_PKCS: case CKM_SHA256_RSA_PKCS:
@@ -85,11 +83,56 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) {
return CK_FALSE; return CK_FALSE;
} }
CK_RV apply_sign_mechanism(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, CK_RV apply_sign_mechanism_init(op_info_t *op_info) {
CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) {
switch (m->mechanism) { if (op_info->type != YKCS11_SIGN)
return CKR_FUNCTION_FAILED;
switch (op_info->mechanism.mechanism) {
case CKM_RSA_PKCS:
// No hash required for this mechanism
return CKR_OK;
case CKM_RSA_PKCS_PSS: // TODO
return CKR_FUNCTION_FAILED;
case CKM_RSA_X_509:
// No hash required for this mechanism
return CKR_OK;
case CKM_SHA1_RSA_PKCS:
case CKM_ECDSA_SHA1:
return do_md_init(YKCS11_SHA1, &op_info->op.sign.md_ctx);
case CKM_SHA256_RSA_PKCS:
return do_md_init(YKCS11_SHA256, &op_info->op.sign.md_ctx);
case CKM_SHA384_RSA_PKCS:
return do_md_init(YKCS11_SHA384, &op_info->op.sign.md_ctx);
case CKM_SHA512_RSA_PKCS:
return do_md_init(YKCS11_SHA512, &op_info->op.sign.md_ctx);
case CKM_ECDSA:
return CKR_FUNCTION_FAILED; // TODO: but no hash needed
default:
CKR_FUNCTION_FAILED;
}
// Never reached
return CKR_FUNCTION_FAILED;
}
CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len) {
CK_RV rv;
if (op_info->type != YKCS11_SIGN)
return CKR_FUNCTION_FAILED;
switch (op_info->mechanism.mechanism) {
case CKM_RSA_PKCS: case CKM_RSA_PKCS:
return do_pkcs_t1(in, in_len, out, out_len, key_len); return CKR_OK;
case CKM_RSA_PKCS_PSS: case CKM_RSA_PKCS_PSS:
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
@@ -101,7 +144,57 @@ CK_RV apply_sign_mechanism(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len,
case CKM_SHA256_RSA_PKCS: case CKM_SHA256_RSA_PKCS:
case CKM_SHA384_RSA_PKCS: case CKM_SHA384_RSA_PKCS:
case CKM_SHA512_RSA_PKCS: case CKM_SHA512_RSA_PKCS:
case CKM_ECDSA_SHA1:
rv = do_md_update(op_info->op.sign.md_ctx, in, in_len);
if (rv != CKR_OK)
return CKR_FUNCTION_FAILED;
return CKR_OK;
case CKM_ECDSA:
return CKR_FUNCTION_FAILED;
default:
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
} }
} }
CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) {
CK_RV rv;
if (op_info->type != YKCS11_SIGN)
return CKR_FUNCTION_FAILED;
switch (op_info->mechanism.mechanism) {
case CKM_RSA_PKCS_PSS:
return CKR_FUNCTION_FAILED;
case CKM_RSA_X_509:
return CKR_OK;
case CKM_SHA1_RSA_PKCS:
case CKM_SHA256_RSA_PKCS:
case CKM_SHA384_RSA_PKCS:
case CKM_SHA512_RSA_PKCS:
case CKM_ECDSA_SHA1:
// Finalize the hash if needed and add digest info
rv = do_md_finalize(op_info->op.sign.md_ctx, CK_TRUE, op_info->buf, &op_info->buf_len);
if (rv != CKR_OK)
return CKR_FUNCTION_FAILED;
fprintf(stderr, "The hashed value is %lu long and looks like\n", op_info->buf_len);
dump_hex(op_info->buf, op_info->buf_len, stderr, CK_TRUE);
case CKM_RSA_PKCS:
// And compute padding for all pkcs1 variants
return do_pkcs_t1(op_info->buf, op_info->buf_len, op_info->buf, sizeof(op_info->buf), op_info->op.sign.key_len);
case CKM_ECDSA:
return CKR_FUNCTION_FAILED;
default:
return CKR_FUNCTION_FAILED;
}
}
+4 -4
View File
@@ -3,11 +3,11 @@
#include "ykcs11.h" #include "ykcs11.h"
CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m);
CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m);
CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m); CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m);
CK_RV apply_sign_mechanism(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len, CK_RV apply_sign_mechanism_init(op_info_t *op_info);
CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len);
CK_RV apply_sign_mechanism_finalize(op_info_t *op_info);
#endif #endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef OPENSSL_TYPES_H
#define OPENSSL_TYPES_H
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/ec.h>
typedef enum {
YKCS11_NO_HASH,
YKCS11_SHA1,
//YKCS11_SHA224,
YKCS11_SHA256,
YKCS11_SHA384,
YKCS11_SHA512,
//YKCS11_RIPEMD128_RSA_PKCS,
//YKCS11_RIPEMD160
} hash_t;
typedef EVP_MD_CTX ykcs11_md_ctx_t;
#endif
+74
View File
@@ -139,3 +139,77 @@ CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_
return CKR_OK; return CKR_OK;
} }
CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx) {
const EVP_MD *md;
switch (hash) {
case YKCS11_NO_HASH:
return CKR_FUNCTION_FAILED;
case YKCS11_SHA1:
md = EVP_sha1();
break;
//case YKCS11_SHA224:
case YKCS11_SHA256:
md = EVP_sha256();
break;
case YKCS11_SHA384:
md = EVP_sha384();
break;
case YKCS11_SHA512:
md = EVP_sha512();
break;
//case YKCS11_RIPEMD128_RSA_PKCS_HASH:
//case YKCS11_RIPEMD160_HASH:
default:
return CKR_FUNCTION_FAILED;
}
*ctx = EVP_MD_CTX_create();
// The OpenSSL function above never fail
if (EVP_DigestInit_ex(*ctx, md, NULL) == 0) {
EVP_MD_CTX_destroy(*ctx);
return CKR_FUNCTION_FAILED;
}
return CKR_OK;
}
CK_RV do_md_update(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR in, CK_ULONG in_len) {
return EVP_DigestUpdate(ctx, in, in_len) == 1 ? CKR_OK : CKR_FUNCTION_FAILED;
}
CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BBOOL di, CK_BYTE_PTR out, CK_ULONG_PTR out_len) {
int rv;
bool rv2;
unsigned int len;
// Finalize digest and store result
rv = EVP_DigestFinal_ex(ctx, out, (unsigned int *)out_len);
// Check wheter digest info is required
if (di == CK_TRUE)
rv2 = prepare_rsa_signature(out, *out_len, out, &len, EVP_MD_CTX_type(ctx));
// Destroy the md context
EVP_MD_CTX_destroy(ctx);
// Error if either of the previous calls failed
if (rv != 1 || !rv2)
return CKR_FUNCTION_FAILED;
*out_len = len;
return CKR_OK;
}
+10 -4
View File
@@ -1,10 +1,12 @@
#ifndef OPENSSL_UTIL_H #ifndef OPENSSL_UTIL_H
#define OPENSSL_UTIL_H #define OPENSSL_UTIL_H
#include <openssl/x509.h> /* #include <openssl/x509.h> */
#include <openssl/evp.h> /* #include <openssl/evp.h> */
#include <openssl/rsa.h> /* #include <openssl/rsa.h> */
#include <openssl/ec.h> /* #include <openssl/ec.h> */
#include "openssl_types.h"
#include "pkcs11t.h" #include "pkcs11t.h"
CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert);
@@ -18,4 +20,8 @@ CK_RV free_key(EVP_PKEY *key);
CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len);
CK_RV do_md_init(hash_t hash, ykcs11_md_ctx_t **ctx);
CK_RV do_md_update(ykcs11_md_ctx_t *ctx, CK_BYTE_PTR in, CK_ULONG in_len);
CK_RV do_md_finalize(ykcs11_md_ctx_t *ctx, CK_BBOOL di, CK_BYTE_PTR out, CK_ULONG_PTR out_len);
#endif #endif
+41 -37
View File
@@ -7,6 +7,7 @@
#include "obj_types.h" #include "obj_types.h"
#include "utils.h" #include "utils.h"
#include "mechanisms.h" #include "mechanisms.h"
#include "openssl_types.h"
#define D(x) do { \ #define D(x) do { \
printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \
@@ -58,16 +59,10 @@ static struct {
piv_obj_id_t *objects; piv_obj_id_t *objects;
} find_obj; } find_obj;
/*static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tide this up, also build at runtime (during open session)? And include inside a session struct? op_info_t op_info;
static CK_ULONG n_token_objects = 0;*/
static struct { /*static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tidy this up, also build at runtime (during open session)? And include inside a session struct?
CK_BBOOL active; static CK_ULONG n_token_objects = 0;*/
CK_MECHANISM mechanism;
CK_ULONG key;
CK_ULONG key_len;
CK_BYTE algo;
} sign_info;
extern CK_FUNCTION_LIST function_list; // TODO: check all return values extern CK_FUNCTION_LIST function_list; // TODO: check all return values
@@ -87,7 +82,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
return CKR_CRYPTOKI_ALREADY_INITIALIZED; return CKR_CRYPTOKI_ALREADY_INITIALIZED;
if (ykpiv_init(&piv_state, YKCS11_DBG) != YKPIV_OK) { if (ykpiv_init(&piv_state, YKCS11_DBG) != YKPIV_OK) {
DBG(("Unable to initialize YubiKey")); DBG(("Unable to initialize libykpiv"));
return CKR_FUNCTION_FAILED; // TODO: better error? return CKR_FUNCTION_FAILED; // TODO: better error?
} }
@@ -1247,7 +1242,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism)); DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism));
return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that
} }
memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM));
// Get key algorithm // Get key algorithm
if (get_attribute(&session, hKey, template) != CKR_OK) { if (get_attribute(&session, hKey, template) != CKR_OK) {
@@ -1265,12 +1260,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
return CKR_KEY_HANDLE_INVALID; return CKR_KEY_HANDLE_INVALID;
} }
sign_info.key_len = key_len; op_info.op.sign.key_len = key_len;
if (key_len == 1024) if (key_len == 1024)
sign_info.algo = YKPIV_ALGO_RSA1024; op_info.op.sign.algo = YKPIV_ALGO_RSA1024;
else else
sign_info.algo = YKPIV_ALGO_RSA2048; op_info.op.sign.algo = YKPIV_ALGO_RSA2048;
} }
else { else {
@@ -1282,33 +1277,38 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
// The buffer contains an uncompressed point of the form 04, x, y // The buffer contains an uncompressed point of the form 04, x, y
// TODO: is this a fine representation for an EC public key? // TODO: is this a fine representation for an EC public key?
sign_info.key_len = ((template[2].ulValueLen - 1) / 2) * 8; op_info.op.sign.key_len = ((template[2].ulValueLen - 1) / 2) * 8;
if (sign_info.key_len == 256) if (op_info.op.sign.key_len == 256)
sign_info.algo = YKPIV_ALGO_ECCP256; op_info.op.sign.algo = YKPIV_ALGO_ECCP256;
/*else /*else
sign_info.algo = ;*/ op_info.algo = ;*/
} }
DBG(("Key length is %lu bit", sign_info.key_len)); //op_info.hash = get_mechanism_hash(pMechanism->mechanism);
sign_info.key = piv_2_ykpiv(hKey); DBG(("Key length is %lu bit", op_info.op.sign.key_len));
if (sign_info.key == 0) {
op_info.op.sign.key = piv_2_ykpiv(hKey);
if (op_info.op.sign.key == 0) {
DBG(("Incorrect key %lu", hKey)); DBG(("Incorrect key %lu", hKey));
return CKR_KEY_HANDLE_INVALID; return CKR_KEY_HANDLE_INVALID;
} }
DBG(("Algorithm is %d", sign_info.algo)); DBG(("Algorithm is %d", op_info.op.sign.algo));
// Make sure that both mechanism and key have the same algorithm // Make sure that both mechanism and key have the same algorithm
if ((is_RSA_mechanism(pMechanism->mechanism) && sign_info.algo == YKPIV_ALGO_ECCP256) || if ((is_RSA_mechanism(pMechanism->mechanism) && op_info.op.sign.algo == YKPIV_ALGO_ECCP256) ||
(!is_RSA_mechanism(pMechanism->mechanism) && (sign_info.algo != YKPIV_ALGO_ECCP256))) { (!is_RSA_mechanism(pMechanism->mechanism) && (op_info.op.sign.algo != YKPIV_ALGO_ECCP256))) {
DBG(("Key and mechanism algorithm do not match")); DBG(("Key and mechanism algorithm do not match"));
return CKR_ARGUMENTS_BAD; return CKR_ARGUMENTS_BAD;
} }
// TODO: also allocate some space for the signature in case of multipart op_info.type = YKCS11_SIGN;
sign_info.active = CK_TRUE; if (apply_sign_mechanism_init(&op_info) != CKR_OK) {
DBG(("Unable to initialize signing operation"));
return CKR_FUNCTION_FAILED;
}
DOUT; DOUT;
return CKR_OK; return CKR_OK;
@@ -1323,28 +1323,32 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
) )
{ {
DIN; DIN;
CK_BYTE buf[YKCS11_MAX_SIG_BUF_LEN];
CK_ULONG buf_len = sizeof(buf);
if (sign_info.active == CK_FALSE) if (op_info.type == YKCS11_NOOP)
return CKR_OPERATION_NOT_INITIALIZED; return CKR_OPERATION_NOT_INITIALIZED;
// TODO: check conditions if (op_info.type != YKCS11_SIGN)
ykpiv_rc r; return CKR_OPERATION_ACTIVE;
CK_CHAR algo;
// TODO: check other conditions
ykpiv_rc r; // TODO: delete this
DBG(("Sending %lu bytes to sign", ulDataLen)); DBG(("Sending %lu bytes to sign", ulDataLen));
dump_hex(pData, ulDataLen, stderr, CK_TRUE); dump_hex(pData, ulDataLen, stderr, CK_TRUE);
if (apply_sign_mechanism(&sign_info.mechanism, pData, ulDataLen, buf, buf_len, 2048 / 8) != CKR_OK) { if (apply_sign_mechanism_update(&op_info, pData, ulDataLen) != CKR_OK) {
DBG(("Unable to apply padding scheme")); DBG(("Unable to perform signing operation step"));
return CKR_FUNCTION_FAILED;
}
if (apply_sign_mechanism_finalize(&op_info) != CKR_OK) {
DBG(("Unable to finalize signing operation"));
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
} }
memcpy(buf, pData, ulDataLen); // ykpiv does padding already
//dump_hex(buf, 256, stderr, CK_TRUE); //dump_hex(buf, 256, stderr, CK_TRUE);
//*pulSignatureLen = 256; //*pulSignatureLen = 256;
DBG(("Using key %lx", sign_info.key)); // TODO: test what happens if there is no key on the card DBG(("Using key %lx", op_info.op.sign.key)); // TODO: test what happens if there is no key on the card
if ((r = ykpiv_sign_data(piv_state, buf, ulDataLen, pSignature, pulSignatureLen, sign_info.algo, sign_info.key)) != YKPIV_OK) { if ((r = ykpiv_sign_data(piv_state, op_info.buf, ulDataLen, pSignature, pulSignatureLen, op_info.op.sign.algo, op_info.op.sign.key)) != YKPIV_OK) {
DBG(("Sign error, %s", ykpiv_strerror(r))); DBG(("Sign error, %s", ykpiv_strerror(r)));
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
} }
+40
View File
@@ -3,8 +3,11 @@
#include "pkcs11t.h" #include "pkcs11t.h"
#include "obj_types.h" #include "obj_types.h"
#include "openssl_types.h"
#include "vendors.h" #include "vendors.h"
#define YKCS11_OP_BUFSIZE 4096
typedef struct { typedef struct {
vendor_id_t vid; vendor_id_t vid;
CK_TOKEN_INFO info; CK_TOKEN_INFO info;
@@ -25,4 +28,41 @@ typedef struct {
ykcs11_slot_t *slot; ykcs11_slot_t *slot;
} ykcs11_session_t; } ykcs11_session_t;
typedef enum {
YKCS11_NOOP,
YKCS11_SIGN,
YKCS11_HASH,
YKCS11_DECRYPT
} ykcs11_op_type_t;
typedef struct {
ykcs11_md_ctx_t *md_ctx;
CK_BYTE algo;
CK_ULONG key;
CK_ULONG key_len;
} sign_info_t;
typedef struct {
CK_BYTE todo;
} hash_info_t;
typedef struct {
CK_BYTE todo;
} decrypt_info_t;
typedef union {
sign_info_t sign;
hash_info_t hash;
decrypt_info_t decrypt;
} op_t;
typedef struct {
ykcs11_op_type_t type;
CK_MECHANISM mechanism;
op_t op;
CK_BYTE buf[YKCS11_OP_BUFSIZE];
CK_ULONG buf_len;
} op_info_t;
#endif #endif