Skip to content

Commit

Permalink
Merge branch 'ya-isakov'
Browse files Browse the repository at this point in the history
  • Loading branch information
chris2511 committed Jul 29, 2022
2 parents 3865281 + 6d09846 commit 2d8269f
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 16 deletions.
3 changes: 3 additions & 0 deletions lib/opensc-pkcs11.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ typedef unsigned long ck_key_type_t;
#define CKK_AES (0x1f)
#define CKK_BLOWFISH (0x20)
#define CKK_TWOFISH (0x21)
#define CKK_EC_EDWARDS (0x40)
#define CKK_EC_MONTGOMERY (0x41)
#define CKK_VENDOR_DEFINED ((unsigned long) (1 << 31))


Expand Down Expand Up @@ -664,6 +666,7 @@ typedef unsigned long ck_mechanism_type_t;
#define CKM_ECDH1_DERIVE (0x1050)
#define CKM_ECDH1_COFACTOR_DERIVE (0x1051)
#define CKM_ECMQV_DERIVE (0x1052)
#define CKM_EDDSA (0x1057)
#define CKM_JUNIPER_KEY_GEN (0x1060)
#define CKM_JUNIPER_ECB128 (0x1061)
#define CKM_JUNIPER_CBC128 (0x1062)
Expand Down
131 changes: 115 additions & 16 deletions lib/pkcs11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,23 @@ int pkcs11::encrypt(int flen, const unsigned char *from,
return size;
}

// Shared between libressl and openssl
static int eng_idx = -1;
static int eng_finish(ENGINE *e)
{
pkcs11 *p11 = (pkcs11 *)ENGINE_get_ex_data(e, eng_idx);
delete p11;
ENGINE_set_ex_data(e, eng_idx, NULL);
return 1;
}

static int eng_pmeth_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
void *p = EVP_PKEY_CTX_get_app_data(src);
EVP_PKEY_CTX_set_app_data(dst, p);
return 1;
}

#ifndef LIBRESSL_VERSION_NUMBER
static int rsa_privdata_free(RSA *rsa)
{
Expand Down Expand Up @@ -719,6 +736,8 @@ static DSA_SIG *dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa)

#ifndef OPENSSL_NO_EC

static EVP_PKEY_METHOD *p11_eddsa_method;

static void ec_privdata_free(EC_KEY *ec)
{
pkcs11 *p11 = (pkcs11*)EC_KEY_get_ex_data(ec, 0);
Expand Down Expand Up @@ -811,6 +830,61 @@ static EC_KEY_METHOD *setup_ec_key_meth()
ec_set_private_proc, ec_set_public_proc);
return ec_key_meth;
}

static int eddsa_eng_meths(ENGINE *e, EVP_PKEY_METHOD **m, const int **nids, int nid)
{
static const int my_nids[] = {EVP_PKEY_ED25519 };
(void)e;
if (m) {
switch (nid) {
case EVP_PKEY_ED25519:
*m = p11_eddsa_method;
return 1;
return 0;
}
}
if (nids) {
*nids = my_nids;
return ARRAY_SIZE(my_nids);
}
return -1;

}

static int eng_pmeth_sign_eddsa(EVP_MD_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen)
{
int len, rs_len, ret = -1;
unsigned char rs_buf[512];
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
pkcs11 *p11 = (pkcs11 *)ENGINE_get_ex_data(EVP_PKEY_get0_engine(pkey), eng_idx);

// siglen is unsigned and can' cope with -1 as return value
len = p11->encrypt(tbslen, tbs, rs_buf, sizeof rs_buf, CKM_EDDSA);
if (len & 0x01) // Must be even
goto out;
memcpy(sig, rs_buf, len);
*siglen = len;
ret = 1;
out:
ign_openssl_error();
return ret;
}

static int eng_pmeth_ctrl_eddsa(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
(void)p1;
switch (type) {
case EVP_PKEY_CTRL_MD:
if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
return 1;
ECerr(EC_F_PKEY_ECD_CTRL, EC_R_INVALID_DIGEST_TYPE);
return 0;
}
qWarning() << "EC Don't call me" << type;
return -2;
}
#endif

EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj)
Expand All @@ -820,6 +894,32 @@ EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj)
#ifndef OPENSSL_NO_EC
static EC_KEY_METHOD *ec_key_meth = NULL;
EC_KEY *ec;
static ENGINE *e = NULL;

if (!e) {
e = ENGINE_new();
Q_CHECK_PTR(e);

ENGINE_set_pkey_meths(e, eddsa_eng_meths);
ENGINE_set_finish_function(e, eng_finish);
if (eng_idx == -1)
eng_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
ENGINE_set_ex_data(e, eng_idx, NULL);
// Why is engine attached to pubkey? I'm commenting it, as I do
// not want it to be attached to RSA/DSA/EC
//CRYPTO_add(&pub->references, 1, CRYPTO_LOCK_EVP_PKEY);
//pub->engine = e;

if (!p11_eddsa_method) {
p11_eddsa_method = EVP_PKEY_meth_new(EVP_PKEY_ED25519,
EVP_PKEY_FLAG_SIGCTX_CUSTOM);
EVP_PKEY_meth_set_digestsign(p11_eddsa_method,
eng_pmeth_sign_eddsa);
EVP_PKEY_meth_set_ctrl(p11_eddsa_method,
eng_pmeth_ctrl_eddsa, NULL);
EVP_PKEY_meth_set_copy(p11_eddsa_method, eng_pmeth_copy);
}
}
#endif
RSA *rsa;
DSA *dsa;
Expand Down Expand Up @@ -876,27 +976,33 @@ EVP_PKEY *pkcs11::getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj)
openssl_error();
EVP_PKEY_assign_EC_KEY(evp, ec);
break;
case EVP_PKEY_ED25519:
size_t len;
if (ENGINE_get_ex_data(e, eng_idx))
qWarning() << "We forgot to free the previous Card key.";
ENGINE_set_ex_data(e, eng_idx, this);
p11obj = obj;
EVP_PKEY_get_raw_public_key(pub, NULL, &len);
unsigned char *pubkey = (unsigned char *)OPENSSL_malloc(len);
Q_CHECK_PTR(pubkey);
EVP_PKEY_get_raw_public_key(pub, pubkey, &len);
evp = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, e, pubkey, len);
openssl_error();
OPENSSL_free(pubkey);
//EVP_PKEY_set1_engine(evp, e);
break;
#endif
}
return evp;
}
#else

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

static int eng_finish(ENGINE *e)
{
pkcs11 *p11 = (pkcs11 *)ENGINE_get_ex_data(e, eng_idx);
delete p11;
ENGINE_set_ex_data(e, eng_idx, NULL);
return 1;
}

static int eng_pmeth_ctrl_rsa(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
switch (type) {
Expand Down Expand Up @@ -1109,13 +1215,6 @@ static int eng_pmeth_sign_ec(EVP_PKEY_CTX *ctx,
}
#endif

static int eng_pmeth_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
void *p = EVP_PKEY_CTX_get_app_data(src);
EVP_PKEY_CTX_set_app_data(dst, p);
return 1;
}

static int eng_meths(ENGINE *e, EVP_PKEY_METHOD **m, const int **nids, int nid)
{
static const int my_nids[] = { EVP_PKEY_EC, EVP_PKEY_RSA };
Expand Down
23 changes: 23 additions & 0 deletions lib/pki_scard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,25 @@ EVP_PKEY *pki_scard::load_pubkey(pkcs11 &p11, CK_OBJECT_HANDLE object) const
EVP_PKEY_assign_EC_KEY(pkey, ec);
break;
}
case CKK_EC_EDWARDS: {
QByteArray ba;
ASN1_OCTET_STRING *os;
pk11_attr_data grp(CKA_EC_PARAMS);
p11.loadAttribute(grp, object);
pk11_attr_data pt(CKA_EC_POINT);
p11.loadAttribute(pt, object);
ba = pt.getData();
os = (ASN1_OCTET_STRING *)
d2i_bytearray(D2I_VOID(d2i_ASN1_OCTET_STRING), ba);
pki_openssl_error();
pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
(const uint8_t *)os->data,
os->length);
pki_openssl_error();
ASN1_OCTET_STRING_free(os);
pki_openssl_error();
break;
}
#endif
default:
throw errorEx(QString("Unsupported CKA_KEY_TYPE: %1\n").arg(keytype));
Expand Down Expand Up @@ -328,6 +347,10 @@ pk11_attlist pki_scard::objectAttributesNoId(EVP_PKEY *pk, bool priv) const
attrs << pk11_attr_ulong(CKA_KEY_TYPE, CKK_EC) <<
pk11_attr_data(CKA_EC_PARAMS, ba);
break;
case EVP_PKEY_ED25519:
attrs << pk11_attr_ulong(CKA_KEY_TYPE, CKK_EC_EDWARDS);
// should it also return params, somehow?
break;
#endif
default:
throw errorEx(QString("Unknown Keytype %d")
Expand Down

0 comments on commit 2d8269f

Please sign in to comment.