From 9321c92f3e214bf7e4264eb3d3a4cd74bfee53c5 Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Fri, 7 Nov 2014 21:42:58 +0100 Subject: [PATCH] DSA add Token keygen for DSA and start DSA token signing --- lib/pkcs11.cpp | 130 ++++++++++++++++++++++++++++++++++++++++------ lib/pki_scard.cpp | 5 +- 2 files changed, 119 insertions(+), 16 deletions(-) diff --git a/lib/pkcs11.cpp b/lib/pkcs11.cpp index 26c8cd70..ea5a48ab 100644 --- a/lib/pkcs11.cpp +++ b/lib/pkcs11.cpp @@ -472,43 +472,68 @@ pk11_attr_data pkcs11::findUniqueID(unsigned long oclass) return id; } -pk11_attr_data pkcs11::generateKey(QString name, unsigned long ec_rsa_mech, +pk11_attr_data pkcs11::generateKey(QString name, unsigned long mech, unsigned long bits, int nid) { CK_RV rv; - CK_OBJECT_HANDLE pubkey, privkey; - pk11_attlist priv_atts, pub_atts; - CK_MECHANISM mechanism = {ec_rsa_mech, NULL_PTR, 0}; + CK_OBJECT_HANDLE pubkey, privkey, dsa_param_obj; + pk11_attlist priv_atts, pub_atts, dsa_param; + CK_MECHANISM mechanism = {mech, NULL_PTR, 0}; pk11_attr_data label(CKA_LABEL, name.toUtf8()); pk11_attr_data new_id = findUniqueID(CKO_PUBLIC_KEY); - pub_atts << + pub_atts << label << new_id << pk11_attr_ulong(CKA_CLASS, CKO_PUBLIC_KEY) << pk11_attr_bool(CKA_TOKEN, true) << pk11_attr_bool(CKA_PRIVATE, false) << pk11_attr_bool(CKA_ENCRYPT, true) << pk11_attr_bool(CKA_VERIFY, true) << - pk11_attr_bool(CKA_WRAP, true) << - label << new_id; + pk11_attr_bool(CKA_WRAP, true); - priv_atts << + priv_atts << label << new_id << pk11_attr_ulong(CKA_CLASS, CKO_PRIVATE_KEY) << pk11_attr_bool(CKA_TOKEN, true) << pk11_attr_bool(CKA_PRIVATE, true) << pk11_attr_bool(CKA_SENSITIVE, true) << pk11_attr_bool(CKA_DECRYPT, true) << pk11_attr_bool(CKA_SIGN, true) << - pk11_attr_bool(CKA_UNWRAP, true) << - label << new_id; + pk11_attr_bool(CKA_UNWRAP, true); - if (ec_rsa_mech == CKM_RSA_PKCS_KEY_PAIR_GEN) { + switch (mech) { + case CKM_RSA_PKCS_KEY_PAIR_GEN: pub_atts << pk11_attr_ulong(CKA_MODULUS_BITS, bits) << pk11_attr_data(CKA_PUBLIC_EXPONENT, 0x10001); -//DSA: Spec Seite 191 (175) C_GenerateKey + break; + case CKM_DSA_KEY_PAIR_GEN: { + //DSA: Spec Seite 191 (175) C_GenerateKey + CK_MECHANISM mechanism = {CKM_DSA_PARAMETER_GEN, NULL_PTR, 0}; + dsa_param << label << + pk11_attr_ulong(CKA_CLASS, CKO_DOMAIN_PARAMETERS) << + pk11_attr_ulong(CKA_KEY_TYPE, CKK_DSA) << + pk11_attr_bool(CKA_TOKEN, true) << + pk11_attr_bool(CKA_PRIVATE, false) << + pk11_attr_ulong(CKA_PRIME_BITS, bits); + p11slot.isValid(); + WAITCURSOR_START; + rv = p11slot.p11()->C_GenerateKey(session, &mechanism, + dsa_param.getAttributes(), dsa_param.length(), + &dsa_param_obj); + WAITCURSOR_END; + if (rv != CKR_OK) + pk11error("C_GenerateKey(DSA_PARAMETER)", rv); + + pk11_attr_data p(CKA_PRIME), q(CKA_SUBPRIME), g(CKA_BASE); + loadAttribute(p, dsa_param_obj); + loadAttribute(q, dsa_param_obj); + loadAttribute(g, dsa_param_obj); + + pub_atts << p << q << g; + break; + } #ifndef OPENSSL_NO_EC - } else if (ec_rsa_mech == CKM_EC_KEY_PAIR_GEN) { + case CKM_EC_KEY_PAIR_GEN: { CK_MECHANISM_INFO info; mechanismInfo(p11slot, CKM_EC_KEY_PAIR_GEN, &info); @@ -524,8 +549,9 @@ pk11_attr_data pkcs11::generateKey(QString name, unsigned long ec_rsa_mech, pub_atts << pk11_attr_data(CKA_EC_PARAMS, i2d_bytearray(I2D_VOID(i2d_ECPKParameters), group)); EC_GROUP_free(group); + } #endif - } else { + default: throw errorEx(("Unsupported Key generation mechanism")); } p11slot.isValid(); @@ -692,6 +718,7 @@ EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj) static int eng_idx = -1; static EVP_PKEY_METHOD *p11_rsa_method; +static EVP_PKEY_METHOD *p11_dsa_method; #ifndef OPENSSL_NO_EC static EVP_PKEY_METHOD *p11_ec_method; #endif @@ -709,7 +736,7 @@ static int eng_pmeth_ctrl_rsa(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) switch (type) { case EVP_PKEY_CTRL_RSA_PADDING: return p1 == RSA_PKCS1_PADDING ? 1 : -2; -#ifndef OPENSSL_NO_EC // WTF ??? +#ifndef OPENSSL_NO_EC case EVP_PKEY_CTRL_GET_RSA_PADDING: *(int *)p2 = RSA_PKCS1_PADDING; return 1; @@ -723,6 +750,25 @@ static int eng_pmeth_ctrl_rsa(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return -2; } +static int eng_pmeth_ctrl_dsa(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) +{ + switch (type) { + case EVP_PKEY_CTRL_MD: + EVP_PKEY_CTX_set_data(ctx, NULL); + switch (EVP_MD_type((const EVP_MD *)p2)) { + case NID_sha1: + case NID_sha256: + EVP_PKEY_CTX_set_data(ctx, p2); + return 1; + } + EVP_PKEY_CTX_set_data(ctx, p2); + return 0; + case EVP_PKEY_CTRL_DIGESTINIT: + return 1; + } + return -2; +} + #ifndef OPENSSL_NO_EC static int eng_pmeth_ctrl_ec(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { @@ -817,6 +863,48 @@ static int eng_pmeth_sign_rsa(EVP_PKEY_CTX *ctx, return (len < 0) ? -1 : 1; } +static int eng_pmeth_sign_dsa(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + EVP_PKEY *pkey; + int len, rs_len, ret = -1; + unsigned char rs_buf[128]; + DSA_SIG *dsa_sig = DSA_SIG_new(); + + pkey = EVP_PKEY_CTX_get0_pkey(ctx); + + if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) + return -1; + + pkcs11 *p11 = (pkcs11 *)ENGINE_get_ex_data(pkey->engine, eng_idx); + + // siglen is unsigned and can't cope with -1 as return value + len = p11->encrypt(tbslen, tbs, rs_buf, sizeof rs_buf, CKM_DSA); +// len = p11->encrypt(tbslen, tbs, sig, *siglen, CKM_DSA); + if (len & 0x01) // Must be even + goto out; + + fprintf(stderr, "DSA len_in:%zd, len_out:%d\n", tbslen, len); + rs_len = len/2; + + if (!BN_bin2bn(rs_buf, rs_len, dsa_sig->s)) + goto out; + if (!BN_bin2bn(rs_buf + rs_len, rs_len, dsa_sig->r)) + goto out; + len = i2d_DSA_SIG(dsa_sig, &sig); + openssl_error(); + if (len <= 0) + goto out; + fprintf(stderr, "DSA len_in:%zd, len_i2d:%d *siglen:%zd\n", tbslen, len, *siglen); + *siglen = len; + ret = 1; +out: + DSA_SIG_free(dsa_sig); + ign_openssl_error(); + return ret; +} + #ifndef OPENSSL_NO_EC static int eng_pmeth_sign_ec(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, @@ -874,6 +962,9 @@ static int eng_meths(ENGINE *e, EVP_PKEY_METHOD **m, const int **nids, int nid) case EVP_PKEY_RSA: *m = p11_rsa_method; return 1; + case EVP_PKEY_DSA: + *m = p11_dsa_method; + return 1; } return 0; } @@ -909,6 +1000,14 @@ EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj) eng_pmeth_ctrl_rsa, NULL); EVP_PKEY_meth_set_copy(p11_rsa_method, eng_pmeth_copy); } + if (!p11_dsa_method) { + p11_dsa_method = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0); + EVP_PKEY_meth_set_sign(p11_dsa_method, + NULL, eng_pmeth_sign_dsa); + EVP_PKEY_meth_set_ctrl(p11_dsa_method, + eng_pmeth_ctrl_dsa, NULL); + EVP_PKEY_meth_set_copy(p11_dsa_method, eng_pmeth_copy); + } #ifndef OPENSSL_NO_EC if (!p11_ec_method) { p11_ec_method = EVP_PKEY_meth_new(EVP_PKEY_EC, 0); @@ -928,6 +1027,7 @@ EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj) switch (EVP_PKEY_type(pub->type)) { case EVP_PKEY_RSA: + case EVP_PKEY_DSA: #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: #endif diff --git a/lib/pki_scard.cpp b/lib/pki_scard.cpp index fe1c971d..d4f2ec68 100644 --- a/lib/pki_scard.cpp +++ b/lib/pki_scard.cpp @@ -410,7 +410,7 @@ void pki_scard::store_token(slotid slot, EVP_PKEY *pkey) break; } default: - throw errorEx(tr("Only RSA and EC keys can be stored on tokens")); + throw errorEx(tr("Only RSA, DSA and EC keys can be stored on tokens")); } @@ -583,6 +583,9 @@ void pki_scard::generateKey_card(int type, slotid slot, int size, case EVP_PKEY_RSA: kt.method = CKM_RSA_PKCS_KEY_PAIR_GEN; break; + case EVP_PKEY_DSA: + kt.method = CKM_DSA_KEY_PAIR_GEN; + break; #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: kt.method = CKM_EC_KEY_PAIR_GEN;