Example #1
0
/**
 * Implements signing certificate selector for EstEID ID-Cards.
 *
 * @param certificates list of certificates to choose from. List of all certificates
 *        found ID-card.
 * @return should return the selected certificate.
 * @throws SignException throws exception if no suitable certificate was found.
 */
digidoc::PKCS11Signer::PKCS11Cert digidoc::EstEIDSigner::selectSigningCertificate(
        const std::vector<PKCS11Signer::PKCS11Cert> &certificates) const throw(SignException)
{
    // Find EstEID signing certificate
    if(certificates.empty())
        THROW_SIGNEXCEPTION("Could not find certificate.");

    for(std::vector<PKCS11Signer::PKCS11Cert>::const_iterator i = certificates.begin(); i < certificates.end(); ++i)
    {
        ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING*)X509_get_ext_d2i(i->cert, NID_key_usage, 0, 0);
        if(!keyusage)
            continue;

        for(int n = 0; n < 9; ++n)
        {
            if(ASN1_BIT_STRING_get_bit(keyusage, n) && n == 1)
            {
                ASN1_BIT_STRING_free( keyusage );
                return *i;
            }
        }
        ASN1_BIT_STRING_free( keyusage );
    }
    THROW_SIGNEXCEPTION("Could not find certificate.");
    return PKCS11Signer::PKCS11Cert();
}
static VALUE
decode_bstr(unsigned char* der, int length, long *unused_bits)
{
    ASN1_BIT_STRING *bstr;
    unsigned char *p, *buf;
    long len;
    VALUE ret;

    p = der;
    if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
	ossl_raise(eASN1Error, NULL);
    len = bstr->length;
    if(!(buf = OPENSSL_malloc(len))){
	ASN1_BIT_STRING_free(bstr);
	ossl_raise(eASN1Error, NULL);
    }
    *unused_bits = 0;
    if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
	*unused_bits = bstr->flags & 0x07;
    memcpy(buf, bstr->data, len);
    ASN1_BIT_STRING_free(bstr);
    ret = ossl_buf2str(buf, len);

    return ret;
}
Example #3
0
static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk)
	{
	ASN1_OBJECT *algobj = NULL;
	ASN1_OCTET_STRING *octet = NULL;
	void *pval = NULL;
	unsigned char *buf=NULL,*databuf,*sptr;
	int i,j,data_len,ret=0;

	int ptype = V_ASN1_UNDEF;
	DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
	algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
	if (pk->save_parameters) 
		{
		ASN1_STRING *params = encode_gost_algor_params(pk);
		pval = params;
		ptype = V_ASN1_SEQUENCE;
		}	
	data_len = BN_num_bytes(dsa->pub_key);
	databuf = OPENSSL_malloc(data_len);
	BN_bn2bin(dsa->pub_key,databuf);
	octet = ASN1_OCTET_STRING_new();
	ASN1_STRING_set(octet,NULL,data_len);
	sptr = ASN1_STRING_data(octet);
	for (i=0,j=data_len-1; i< data_len;i++,j--)
		{
		sptr[i]=databuf[j];
		}
	OPENSSL_free(databuf);
	ret = i2d_ASN1_OCTET_STRING(octet,&buf);
	ASN1_BIT_STRING_free(octet);
	if (ret <0)  return 0;
	return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
	}
Example #4
0
/*******************************************************************************
函数名称: cert_ku_accept
功能描述: 查看某个证书是否有某种密钥用途
输入参数: X509 *x:证书
     u32 kusage:密钥用途

输出参数: 无
返 回 值: 1,有该密钥用途;-1,没有
--------------------------------------------------------------------------------
最近一次修改记录:
修改作者:王朝
修改目的:添加新函数
修改日期:2009年12月28日
*********************************************************************************/
s32 cert_ku_accept(X509 *x,u32 kusage)
{
    ASN1_BIT_STRING *usage = NULL;
    if(NULL != (usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL)))
    {
		if(usage->length > 0)
        {
			x->ex_kusage = usage->data[0];
			if(usage->length > 1)
			{
                x->ex_kusage |= usage->data[1] << 8;
			}
		}
        else
        {
            x->ex_kusage = 0;
        }
        
		ASN1_BIT_STRING_free(usage);
        
        if( (x)->ex_kusage & (kusage) )
        {
            return 1;
        }
        else
        {
            return -1;
        }
	}
    else
    {
        return -1;
    }
}
Example #5
0
int main(int argc, char const *argv[])
{
	long value;
	int ret, len, i;
	unsigned char *bitstr = "8";
	unsigned char buf2[16];
	unsigned char *buf = NULL, *p;
	ASN1_BIT_STRING *a, *q;
	a = ASN1_BIT_STRING_new();
	printf("len = %d\n", a->length);
	ASN1_BIT_STRING_set(a, bitstr, strlen(bitstr));

	len = i2d_ASN1_BIT_STRING(a, NULL);
	p = buf =malloc(sizeof(unsigned char) * len);
	len = i2d_ASN1_BIT_STRING(a, &buf);
	printf("after i2d der content len = %d\n", len);
	printf("len = %d\n", len);

	for (i = 0; i < len; ++i)
	{
		/* code */
		printf("%02x\n", p[i]);
	}
	printf("\n");

	q = d2i_ASN1_BIT_STRING(&a, &p, len);
	printf("after d2i length = %d\n", q->length);
	for (i = 0; i < q->length; ++i)
	{
		printf("%02x\t", q->data[i]);
	}
	printf("\n");
	ASN1_BIT_STRING_free(a);
	return 0;
}
Example #6
0
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
                                     const unsigned char **pp, long len)
{
    ASN1_BIT_STRING *ret = NULL;
    const unsigned char *p;
    unsigned char *s;
    int i;

    if (len < 1) {
        i = ASN1_R_STRING_TOO_SHORT;
        goto err;
    }

    if ((a == NULL) || ((*a) == NULL)) {
        if ((ret = ASN1_BIT_STRING_new()) == NULL)
            return (NULL);
    } else
        ret = (*a);

    p = *pp;
    i = *(p++);
    if (i > 7) {
        i = ASN1_R_INVALID_BIT_STRING_BITS_LEFT;
        goto err;
    }
    /*
     * We do this to preserve the settings.  If we modify the settings, via
     * the _set_bit function, we will recalculate on output
     */
    ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
    ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | i); /* set */

    if (len-- > 1) {            /* using one because of the bits left byte */
        s = OPENSSL_malloc((int)len);
        if (s == NULL) {
            i = ERR_R_MALLOC_FAILURE;
            goto err;
        }
        memcpy(s, p, (int)len);
        s[len - 1] &= (0xff << i);
        p += len;
    } else
        s = NULL;

    ret->length = (int)len;
    OPENSSL_free(ret->data);
    ret->data = s;
    ret->type = V_ASN1_BIT_STRING;
    if (a != NULL)
        (*a) = ret;
    *pp = p;
    return (ret);
 err:
    ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i);
    if ((a == NULL) || (*a != ret))
        ASN1_BIT_STRING_free(ret);
    return (NULL);
}
Example #7
0
static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
	{
	ASN1_OBJECT *algobj = NULL;
	ASN1_OCTET_STRING *octet = NULL;
	void *pval = NULL;
	unsigned char *buf=NULL,*databuf,*sptr;
	int i,j,data_len,ret=0;
	const EC_POINT *pub_key;
	BIGNUM *X,*Y,*order;
	const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
	int ptype = V_ASN1_UNDEF;

	algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
	if (pk->save_parameters) 
		{
		ASN1_STRING *params = encode_gost_algor_params(pk);
		pval = params;
		ptype = V_ASN1_SEQUENCE;
		}
	order = BN_new();
	EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL);
	pub_key=EC_KEY_get0_public_key(ec);
	if (!pub_key) 
		{
		GOSTerr(GOST_F_PUB_ENCODE_GOST01,
			GOST_R_PUBLIC_KEY_UNDEFINED);
		return 0;
		}	
	X=BN_new();
	Y=BN_new();
	EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
		pub_key,X,Y,NULL);
	data_len = 2*BN_num_bytes(order);
	BN_free(order);
	databuf = OPENSSL_malloc(data_len);
	memset(databuf,0,data_len);
	
	store_bignum(X,databuf+data_len/2,data_len/2);
	store_bignum(Y,databuf,data_len/2);

	BN_free(X);
	BN_free(Y);
	octet = ASN1_OCTET_STRING_new();
	ASN1_STRING_set(octet,NULL,data_len);
	sptr=ASN1_STRING_data(octet);
    for (i=0,j=data_len-1;i<data_len;i++,j--) 
		{
        sptr[i]=databuf[j];
		}
    OPENSSL_free(databuf);
	ret = i2d_ASN1_OCTET_STRING(octet,&buf);
	ASN1_BIT_STRING_free(octet);
	if (ret <0)  return 0;
	return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
	}
Example #8
0
/**
 * Returns current certificate key usage bits
 *
 * @return key usage bits
 */
std::vector<digidoc::X509Cert::KeyUsage> digidoc::X509Cert::getKeyUsage() const throw(IOException)
{
    ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING*)X509_get_ext_d2i(cert, NID_key_usage, 0, 0);
    if(!keyusage)
        return std::vector<KeyUsage>();

    std::vector<KeyUsage> usage;
    for(int n = 0; n < 9; ++n)
    {
        if(ASN1_BIT_STRING_get_bit(keyusage, n))
            usage.push_back(KeyUsage(n));
    }
    ASN1_BIT_STRING_free(keyusage);
    return usage;
}
Example #9
0
static VALUE
decode_bstr(unsigned char* der, int length, long *unused_bits)
{
    ASN1_BIT_STRING *bstr;
    const unsigned char *p;
    long len;
    VALUE ret;

    p = der;
    if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
	ossl_raise(eASN1Error, NULL);
    len = bstr->length;
    *unused_bits = 0;
    if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
	*unused_bits = bstr->flags & 0x07;
    ret = rb_str_new((const char *)bstr->data, len);
    ASN1_BIT_STRING_free(bstr);

    return ret;
}
Example #10
0
/**
 * @param cert X509 certificate
 * @return returns if certificate is valid for signing
 */
bool digidoc::PKCS11SignerPrivate::checkCert( X509 *cert ) const
{
    if(!cert)
        return false;
    ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING*)X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL);
    if(!keyusage)
        return false;

    bool ret = false;
    for(int n = 0; n < 9; ++n)
    {
        if(ASN1_BIT_STRING_get_bit(keyusage, n) && n == 1)
        {
            ret = true;
            break;
        }
    }
    ASN1_BIT_STRING_free( keyusage );
    return ret;
}
Example #11
0
static OCSP_BASICRESP *make_dummy_resp(void)
{
    const unsigned char namestr[] = "openssl.example.com";
    unsigned char keybytes[128] = {7};
    OCSP_BASICRESP *bs = OCSP_BASICRESP_new();
    OCSP_BASICRESP *bs_out = NULL;
    OCSP_CERTID *cid = NULL;
    ASN1_TIME *thisupd = ASN1_TIME_set(NULL, time(NULL));
    ASN1_TIME *nextupd = ASN1_TIME_set(NULL, time(NULL) + 200);
    X509_NAME *name = X509_NAME_new();
    ASN1_BIT_STRING *key = ASN1_BIT_STRING_new();
    ASN1_INTEGER *serial = ASN1_INTEGER_new();

    if (!X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC,
                                   namestr, -1, -1, 1)
        || !ASN1_BIT_STRING_set(key, keybytes, sizeof(keybytes))
        || !ASN1_INTEGER_set_uint64(serial, (uint64_t)1))
        goto err;
    cid = OCSP_cert_id_new(EVP_sha256(), name, key, serial);
    if (!TEST_ptr(bs)
        || !TEST_ptr(thisupd)
        || !TEST_ptr(nextupd)
        || !TEST_ptr(cid)
        || !TEST_true(OCSP_basic_add1_status(bs, cid,
                                             V_OCSP_CERTSTATUS_UNKNOWN,
                                             0, NULL, thisupd, nextupd)))
        goto err;
    bs_out = bs;
    bs = NULL;
 err:
    ASN1_TIME_free(thisupd);
    ASN1_TIME_free(nextupd);
    ASN1_BIT_STRING_free(key);
    ASN1_INTEGER_free(serial);
    OCSP_CERTID_free(cid);
    OCSP_BASICRESP_free(bs);
    X509_NAME_free(name);
    return bs_out;
}
Example #12
0
DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length)
{
    int_dhx942_dh *dhx = NULL;
    DH *dh = NULL;
    dh = DH_new();
    if (dh == NULL)
        return NULL;
    dhx = d2i_int_dhx(NULL, pp, length);
    if (dhx == NULL) {
        DH_free(dh);
        return NULL;
    }

    if (a) {
        DH_free(*a);
        *a = dh;
    }

    dh->p = dhx->p;
    dh->q = dhx->q;
    dh->g = dhx->g;
    dh->j = dhx->j;

    if (dhx->vparams) {
        dh->seed = dhx->vparams->seed->data;
        dh->seedlen = dhx->vparams->seed->length;
        dh->counter = dhx->vparams->counter;
        dhx->vparams->seed->data = NULL;
        ASN1_BIT_STRING_free(dhx->vparams->seed);
        OPENSSL_free(dhx->vparams);
        dhx->vparams = NULL;
    }

    OPENSSL_free(dhx);
    return dh;
}
Example #13
0
void X509_KEY_free(X509 *a)
	{
	int i;

	if (a == NULL) return;

	i=CRYPTO_add_lock(&a->references,-1,CRYPTO_LOCK_X509_KEY);
#ifdef REF_PRINT
	REF_PRINT("X509_KEY",a);
#endif
	if (i > 0) return;
#ifdef REF_CHECK
	if (i < 0)
		{
		fprintf(stderr,"X509_KEY_free, bad reference count\n");
		abort();
		}
#endif

	X509_CINF_free(a->cert_info);
	X509_ALGOR_free(a->sig_alg);
	ASN1_BIT_STRING_free(a->signature);
	OPENSSL_free(a);
	}
Example #14
0
void CryptoNative_Asn1BitStringFree(ASN1_STRING* a)
{
    ASN1_BIT_STRING_free(a);
}
Example #15
0
static int
pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
{
	ASN1_OBJECT *algobj = NULL;
	ASN1_OCTET_STRING *octet = NULL;
	ASN1_STRING *params = NULL;
	void *pval = NULL;
	unsigned char *buf = NULL, *sptr;
	int key_size, ret = 0;
	const EC_POINT *pub_key;
	BIGNUM *X = NULL, *Y = NULL;
	const GOST_KEY *ec = pk->pkey.gost;
	int ptype = V_ASN1_UNDEF;

	algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec)));
	if (pk->save_parameters) {
		params = encode_gost01_algor_params(pk);
		if (params == NULL)
			return 0;
		pval = params;
		ptype = V_ASN1_SEQUENCE;
	}

	key_size = GOST_KEY_get_size(ec);

	pub_key = GOST_KEY_get0_public_key(ec);
	if (pub_key == NULL) {
		GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED);
		goto err;
	}

	octet = ASN1_OCTET_STRING_new();
	if (octet == NULL) {
		GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
		goto err;
	}

	ret = ASN1_STRING_set(octet, NULL, 2 * key_size);
	if (ret == 0) {
		GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR);
		goto err;
	}

	sptr = ASN1_STRING_data(octet);

	X = BN_new();
	Y = BN_new();
	if (X == NULL || Y == NULL) {
		GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
		goto err;
	}

	if (EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec),
	    pub_key, X, Y, NULL) == 0) {
		GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_EC_LIB);
		goto err;
	}

	GOST_bn2le(X, sptr, key_size);
	GOST_bn2le(Y, sptr + key_size, key_size);

	BN_free(Y);
	BN_free(X);

	ret = i2d_ASN1_OCTET_STRING(octet, &buf);
	ASN1_BIT_STRING_free(octet);
	if (ret < 0)
		return 0;

	return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);

err:
	BN_free(Y);
	BN_free(X);
	ASN1_BIT_STRING_free(octet);
	ASN1_STRING_free(params);
	return 0;
}
Example #16
0
extern "C" void Asn1BitStringFree(ASN1_STRING* a)
{
    ASN1_BIT_STRING_free(a);
}
Example #17
0
static void x509v3_cache_extensions(X509 *x)
{
  BASIC_CONSTRAINTS *bs;
  PROXY_CERT_INFO_EXTENSION *pci;
  ASN1_BIT_STRING *usage;
  ASN1_BIT_STRING *ns;
  EXTENDED_KEY_USAGE *extusage;
  X509_EXTENSION *ex;
  
  int i;
  if(x->ex_flags & EXFLAG_SET) return;
#ifndef OPENSSL_NO_SHA
  X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
#endif
  /* Does subject name match issuer ? */
  if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
       x->ex_flags |= EXFLAG_SS;
  /* V1 should mean no extensions ... */
  if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
  /* Handle basic constraints */
  if((bs=X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
    if(bs->ca) x->ex_flags |= EXFLAG_CA;
    if(bs->pathlen) {
      if((bs->pathlen->type == V_ASN1_NEG_INTEGER)
            || !bs->ca) {
        x->ex_flags |= EXFLAG_INVALID;
        x->ex_pathlen = 0;
      } else x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
    } else x->ex_pathlen = -1;
    BASIC_CONSTRAINTS_free(bs);
    x->ex_flags |= EXFLAG_BCONS;
  }
  /* Handle proxy certificates */
  if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
    if (x->ex_flags & EXFLAG_CA
        || X509_get_ext_by_NID(x, NID_subject_alt_name, 0) >= 0
        || X509_get_ext_by_NID(x, NID_issuer_alt_name, 0) >= 0) {
      x->ex_flags |= EXFLAG_INVALID;
    }
    if (pci->pcPathLengthConstraint) {
      x->ex_pcpathlen =
        ASN1_INTEGER_get(pci->pcPathLengthConstraint);
    } else x->ex_pcpathlen = -1;
    PROXY_CERT_INFO_EXTENSION_free(pci);
    x->ex_flags |= EXFLAG_PROXY;
  }
  /* Handle key usage */
  if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
    if(usage->length > 0) {
      x->ex_kusage = usage->data[0];
      if(usage->length > 1) 
        x->ex_kusage |= usage->data[1] << 8;
    } else x->ex_kusage = 0;
    x->ex_flags |= EXFLAG_KUSAGE;
    ASN1_BIT_STRING_free(usage);
  }
  x->ex_xkusage = 0;
  if((extusage=X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
    x->ex_flags |= EXFLAG_XKUSAGE;
    for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
      switch(OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage,i))) {
        case NID_server_auth:
        x->ex_xkusage |= XKU_SSL_SERVER;
        break;

        case NID_client_auth:
        x->ex_xkusage |= XKU_SSL_CLIENT;
        break;

        case NID_email_protect:
        x->ex_xkusage |= XKU_SMIME;
        break;

        case NID_code_sign:
        x->ex_xkusage |= XKU_CODE_SIGN;
        break;

        case NID_ms_sgc:
        case NID_ns_sgc:
        x->ex_xkusage |= XKU_SGC;
        break;

        case NID_OCSP_sign:
        x->ex_xkusage |= XKU_OCSP_SIGN;
        break;

        case NID_time_stamp:
        x->ex_xkusage |= XKU_TIMESTAMP;
        break;

        case NID_dvcs:
        x->ex_xkusage |= XKU_DVCS;
        break;
      }
    }
    sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
  }

  if((ns=X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
    if(ns->length > 0) x->ex_nscert = ns->data[0];
    else x->ex_nscert = 0;
    x->ex_flags |= EXFLAG_NSCERT;
    ASN1_BIT_STRING_free(ns);
  }
  x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
  x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
  for (i = 0; i < X509_get_ext_count(x); i++)
    {
    ex = X509_get_ext(x, i);
    if (!X509_EXTENSION_get_critical(ex))
      continue;
    if (!X509_supported_extension(ex))
      {
      x->ex_flags |= EXFLAG_CRITICAL;
      break;
      }
    }
  x->ex_flags |= EXFLAG_SET;
}
Example #18
0
int EstEID_loadCertInfoEntries(EstEID_Certs *certs, int index) {
	EstEID_Map cert = certs->certs[index];
	CK_SLOT_ID slotID = certs->slotIDs[index];

	CK_SESSION_HANDLE session;
	FAIL_IF(EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session)));

	CK_OBJECT_CLASS objectClass = CKO_CERTIFICATE;
	CK_ATTRIBUTE searchAttribute = {CKA_CLASS, &objectClass, sizeof(objectClass)};
	if (EstEID_CK_failure("C_FindObjectsInit", fl->C_FindObjectsInit(session, &searchAttribute, 1))) return FAILURE;

	CK_OBJECT_HANDLE objectHandle;
	CK_ULONG objectCount;
	if (EstEID_CK_failure("C_FindObjects", fl->C_FindObjects(session, &objectHandle, 1, &objectCount))) return FAILURE;

	if (objectCount == 0) return SUCCESS;

	CK_ATTRIBUTE attribute = {CKA_VALUE, NULL_PTR, 0};
	if (EstEID_CK_failure("C_GetAttributeValue", fl->C_GetAttributeValue(session, objectHandle, &attribute, 1))) return FAILURE;

	CK_ULONG certificateLength = attribute.ulValueLen;
	CK_BYTE_PTR certificate = (CK_BYTE_PTR)malloc(certificateLength);
	attribute.pValue = certificate;
	if (EstEID_CK_failure("C_GetAttributeValue", fl->C_GetAttributeValue(session, objectHandle, &attribute, 1))) return FAILURE;

	EstEID_mapPutNoAlloc(cert, strdup("certificateAsHex"), EstEID_bin2hex((char *)certificate, certificateLength));

	const unsigned char *p = certificate;
	X509 *x509 = d2i_X509(NULL, &p, certificateLength);
	
	char *certMD5;
	certMD5 = EstEID_getCertHash((char*)certificate);
	FAIL_IF(EstEID_md5_failure(certMD5));
	EstEID_mapPutNoAlloc(cert, strdup("certHash"), certMD5);
	free(certificate);
// todo: error handling of all openssl functions

	EstEID_mapPutNoAlloc(cert, strdup("validTo"), EstEID_ASN1_TIME_toString(X509_get_notAfter(x509)));
	EstEID_mapPutNoAlloc(cert, strdup("validFrom"), EstEID_ASN1_TIME_toString(X509_get_notBefore(x509)));

	unsigned long keyUsage;
	ASN1_BIT_STRING *usage = (ASN1_BIT_STRING *)X509_get_ext_d2i(x509, NID_key_usage, NULL, NULL);
	if (usage->length > 0) keyUsage = usage->data[0];
	ASN1_BIT_STRING_free(usage);

	if (keyUsage & X509v3_KU_DIGITAL_SIGNATURE) EstEID_mapPut(cert, "usageDigitalSignature", "TRUE");
	if (keyUsage & X509v3_KU_NON_REPUDIATION) {
		EstEID_mapPut(cert, "usageNonRepudiation", "TRUE");
		EstEID_mapPut(cert, "keyUsage", "Non-Repudiation");  // for compatibility with older plugin
	}

	EstEID_loadCertEntries(cert, "", X509_get_subject_name(x509));

	char *certSerialNumber = (char*)malloc(33);
	snprintf(certSerialNumber, 32, "%lX", ASN1_INTEGER_get(X509_get_serialNumber(x509)));
	EstEID_mapPutNoAlloc(cert, strdup("certSerialNumber"), certSerialNumber);
	EstEID_loadCertEntries(cert, "issuer.", X509_get_issuer_name(x509));

	BIO *bio = BIO_new(BIO_s_mem());
	if (!PEM_write_bio_X509(bio, x509)) printf("Cannot create PEM\n");
	char *b;
	int len = BIO_get_mem_data(bio, &b);
	char *pem = (char *)malloc(len + 1);
	strncpy(pem, b, len);
	pem[len] = 0;
	BIO_free(bio);
	EstEID_mapPutNoAlloc(cert, strdup("certificateAsPEM"), pem);

	FAIL_IF(EstEID_CK_failure("C_CloseSession", fl->C_CloseSession(session)));
	return SUCCESS;
}