Esempio n. 1
0
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
{
    X509_PUBKEY *pk = NULL;

    if (x == NULL)
        return (0);

    if ((pk = X509_PUBKEY_new()) == NULL)
        goto error;

    if (pkey->ameth) {
        if (pkey->ameth->pub_encode) {
            if (!pkey->ameth->pub_encode(pk, pkey)) {
                X509err(X509_F_X509_PUBKEY_SET,
                        X509_R_PUBLIC_KEY_ENCODE_ERROR);
                goto error;
            }
        } else {
            X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED);
            goto error;
        }
    } else {
        X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM);
        goto error;
    }

    X509_PUBKEY_free(*x);
    *x = pk;
    return 1;

 error:
    X509_PUBKEY_free(pk);
    return 0;
}
Esempio n. 2
0
static int test_X509_PUBKEY_inplace(void)
{
  int ret = 0;
  X509_PUBKEY *xp = NULL;
  const unsigned char *p = kExampleECPubKeyDER;
  size_t input_len = sizeof(kExampleECPubKeyDER);

  if (!TEST_ptr(xp = d2i_X509_PUBKEY(NULL, &p, input_len)))
    goto done;

  if (!TEST_ptr(X509_PUBKEY_get0(xp)))
    goto done;

  p = kExampleBadECPubKeyDER;
  input_len = sizeof(kExampleBadECPubKeyDER);

  if (!TEST_ptr(xp = d2i_X509_PUBKEY(&xp, &p, input_len)))
    goto done;

  if (!TEST_true(X509_PUBKEY_get0(xp) == NULL))
    goto done;

  ret = 1;

done:
  X509_PUBKEY_free(xp);
  return ret;
}
Esempio n. 3
0
ByteArray PublicKey::getKeyIdentifier() throw (EncodeException)
{
	ByteArray ret;
	unsigned int size;
	X509_PUBKEY *pubkey = NULL;
	
	if(X509_PUBKEY_set(&pubkey, this->key) == 0)
	{
		throw EncodeException(EncodeException::UNKNOWN, "PublicKey::getKeyIdentifier");
	}
			
	ret = ByteArray(EVP_MAX_MD_SIZE);
	EVP_Digest(pubkey->public_key->data, pubkey->public_key->length, ret.getDataPointer(), &size, EVP_sha1(), NULL);
	ret = ByteArray(ret.getDataPointer(), size);

	X509_PUBKEY_free(pubkey);
	
	return ret;
	
	//return ByteArray(digest, digestLen);

	/*	ByteArray der = this->getDerEncoded();
	MessageDigest md(MessageDigest::SHA1);
	
	MessageDigest::loadMessageDigestAlgorithms();
	
	return md.doFinal(der);*/
}
Esempio n. 4
0
uint8_t *
cga_key2der(EVP_PKEY *k, int *dlen)
{
	uint8_t *p;
	uint8_t *der = NULL;
	X509_PUBKEY *pki = NULL;
	
	if (X509_PUBKEY_set(&pki, k) == 0) {
		ssl_err(__FUNCTION__, "X509_PUBKEY_set() failed");
		goto done;
	}

	if ((*dlen = i2d_X509_PUBKEY(pki, NULL)) < 0) {
		ssl_err(__FUNCTION__, "i2d_PublicKey failed");
		goto done;
	}
	if ((der = malloc(*dlen)) == NULL) {
		APPLOG_NOMEM();
		goto done;
	}

	p = der;
	if (i2d_X509_PUBKEY(pki, &p) < 0) {
		ssl_err(__FUNCTION__, "i2d_PublicKey failed");
		free(der);
		der = NULL;
	}
	DBG(&dbg_asn1, "DER-encoded key is %d bytes", *dlen);

done:
	if (pki) X509_PUBKEY_free(pki);
	return (der);
}
Esempio n. 5
0
int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
	{
	X509_PUBKEY *xpk=NULL;
	int ret;
	if(!a) return 0;
	if(!X509_PUBKEY_set(&xpk, a)) return 0;
	ret = i2d_X509_PUBKEY(xpk, pp);
	X509_PUBKEY_free(xpk);
	return ret;
	}
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, unsigned char **pp,
	     long length)
{
	X509_PUBKEY *xpk;
	EVP_PKEY *pktmp;
	xpk = d2i_X509_PUBKEY(NULL, pp, length);
	if(!xpk) return NULL;
	pktmp = X509_PUBKEY_get(xpk);
	X509_PUBKEY_free(xpk);
	if(!pktmp) return NULL;
	if(a) {
		EVP_PKEY_free(*a);
		*a = pktmp;
	}
	return pktmp;
}
Esempio n. 7
0
EVP_PKEY *
cga_der2key(uint8_t *dk, int klen)
{
	EVP_PKEY *k;
	X509_PUBKEY *xpk;

	if ((xpk = d2i_X509_PUBKEY(NULL,
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
				   (const unsigned char **)
#endif
				   &dk, klen))
	    == NULL) {
		applog(LOG_ERR, "%s: d2i failed", __FUNCTION__);
		return (NULL);
	}
	k = X509_PUBKEY_get(xpk);
	X509_PUBKEY_free(xpk);

	return (k);
}
Esempio n. 8
0
int PKI_X509_CERT_check_pubkey(PKI_X509_CERT *x, PKI_X509_KEYPAIR *k)
{
	int ret = 0;

	X509_PUBKEY *pub_key = NULL;
	PKI_X509_KEYPAIR_VALUE *k_val = NULL;

	PKI_STRING *c_pubkey = NULL;
	PKI_STRING *k_pubkey = NULL;

	// Input checks
	if (!x || !x->value || !k || !k->value) return -1;

	// Gets the certificate's public key bits
	c_pubkey = PKI_X509_CERT_get_data(x, PKI_X509_DATA_PUBKEY_BITSTRING);
	if (!c_pubkey) return -99;

	// Gets the Key Value from the KeyPair
	k_val = PKI_X509_get_value(k);
	if (!k_val) 
	{
		// Let's return ok, because in HSMs we might not have
		// access to the pubkey data
		return 0;
	}

	// Gets the KeyPair public key bits
	if (!X509_PUBKEY_set(&pub_key, k_val)) return -99;

	// Now let's point to tke KeyPair's public key
	k_pubkey = pub_key->public_key;

	// Compares the two bit strings
	ret = PKI_STRING_cmp(c_pubkey, k_pubkey);
	
	// Frees the memory
	X509_PUBKEY_free(pub_key);

	// Let's return the result of the operation
	return ret;
}
Esempio n. 9
0
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
	{
	X509_PUBKEY *pk=NULL;
	X509_ALGOR *a;
	ASN1_OBJECT *o;
	unsigned char *s,*p = NULL;
	int i;

	if (x == NULL) return(0);

	if ((pk=X509_PUBKEY_new()) == NULL) goto err;
	a=pk->algor;

	/* set the algorithm id */
	if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err;
	ASN1_OBJECT_free(a->algorithm);
	a->algorithm=o;

	/* Set the parameter list */
	if (!pkey->save_parameters || (pkey->type == EVP_PKEY_RSA))
		{
		if ((a->parameter == NULL) ||
			(a->parameter->type != V_ASN1_NULL))
			{
			ASN1_TYPE_free(a->parameter);
			if (!(a->parameter=ASN1_TYPE_new()))
				{
				X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
				goto err;
				}
			a->parameter->type=V_ASN1_NULL;
			}
		}
#ifndef OPENSSL_NO_DSA
	else if (pkey->type == EVP_PKEY_DSA)
		{
		unsigned char *pp;
		DSA *dsa;
		
		dsa=pkey->pkey.dsa;
		dsa->write_params=0;
		ASN1_TYPE_free(a->parameter);
		if ((i=i2d_DSAparams(dsa,NULL)) <= 0)
			goto err;
		if (!(p=(unsigned char *)OPENSSL_malloc(i)))
			{
			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		pp=p;
		i2d_DSAparams(dsa,&pp);
		if (!(a->parameter=ASN1_TYPE_new()))
			{
			OPENSSL_free(p);
			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		a->parameter->type=V_ASN1_SEQUENCE;
		if (!(a->parameter->value.sequence=ASN1_STRING_new()))
			{
			OPENSSL_free(p);
			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		if (!ASN1_STRING_set(a->parameter->value.sequence,p,i))
			{
			OPENSSL_free(p);
			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		OPENSSL_free(p);
		}
#endif
#ifndef OPENSSL_NO_EC
	else if (pkey->type == EVP_PKEY_EC)
		{
		int nid=0;
		unsigned char *pp;
		EC_KEY *ec_key;
		const EC_GROUP *group;
		
		ec_key = pkey->pkey.ec;
		ASN1_TYPE_free(a->parameter);

		if ((a->parameter = ASN1_TYPE_new()) == NULL)
			{
			X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB);
			goto err;
			}

		group = EC_KEY_get0_group(ec_key);
		if (EC_GROUP_get_asn1_flag(group)
                     && (nid = EC_GROUP_get_curve_name(group)))
			{
			/* just set the OID */
			a->parameter->type = V_ASN1_OBJECT;
			a->parameter->value.object = OBJ_nid2obj(nid);
			}
		else /* explicit parameters */
			{
			if ((i = i2d_ECParameters(ec_key, NULL)) == 0)
				{
				X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB);
				goto err;
				}
			if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL)
				{
				X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
				goto err;
				}	
			pp = p;
			if (!i2d_ECParameters(ec_key, &pp))
				{
				X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB);
				OPENSSL_free(p);
				goto err;
				}
			a->parameter->type = V_ASN1_SEQUENCE;
			if ((a->parameter->value.sequence = ASN1_STRING_new()) == NULL)
				{
				X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB);
				OPENSSL_free(p);
				goto err;
				}
			ASN1_STRING_set(a->parameter->value.sequence, p, i);
			OPENSSL_free(p);
			}
		}
#endif
	else if (1)
		{
		X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM);
		goto err;
		}

	if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err;
	if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL)
		{
		X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	p=s;
	i2d_PublicKey(pkey,&p);
	if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i))
		{
		X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
		goto err;
		}
  	/* Set number of unused bits to zero */
	pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
	pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;

	OPENSSL_free(s);

#if 0
	CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
	pk->pkey=pkey;
#endif

	if (*x != NULL)
		X509_PUBKEY_free(*x);

	*x=pk;

	return 1;
err:
	if (pk != NULL) X509_PUBKEY_free(pk);
	return 0;
	}
Esempio n. 10
0
OP_STATUS CryptoSignature_impl::SetPublicKey(const UINT8* public_key, int key_length)
{
	if (!public_key || key_length <= 0)
		return OpStatus::ERR_OUT_OF_RANGE;

	// This function supports public keys in different formats, such as
	// X509_PUBKEY and EVP_PKEY-with-RSA-key-only objects.
	// It should be made more generic, simple and straightforward:
	// only EVP_PKEY objects should be supported.

	// This function tries to decode data at "public_key" pointer as X509_PUBKEY,
	// if fails - as EVP_PKEY_RSA.

	// Clear the existing key, if any.
	if (m_keyspec)
	{
		EVP_PKEY_free(m_keyspec);
		m_keyspec = NULL;
	}


	// Try hypothesis: public key is X509_PUBKEY.

	// Temporary variable as recommended by "man d2i_X509".
	const unsigned char* public_key_tmp = public_key;
	// Construct X509_PUBKEY object. We own it.
	X509_PUBKEY* pubkey = d2i_X509_PUBKEY(NULL, &public_key_tmp, key_length);
	if (pubkey)
	{
		m_keyspec = X509_PUBKEY_get(pubkey);
		// X509_PUBKEY_get allocates new EVP_PKEY, so it's safe
		// to deallocate pubkey now.
		X509_PUBKEY_free(pubkey);
	}
	ERR_clear_error();


	// Try hypothesis: public key is EVP_PKEY_RSA.

	if (m_keyspec == NULL)
	{
		switch (m_cipher_algorithm )
		{
		case CRYPTO_CIPHER_TYPE_RSA:
			// Temporary variable my have changed its value, resetting.
			public_key_tmp = public_key;
			m_keyspec = d2i_PublicKey(EVP_PKEY_RSA, NULL, &public_key_tmp, key_length);
			ERR_clear_error();
			break;

		default:
			return OpStatus::ERR_NOT_SUPPORTED;
		}
	}


	if (m_keyspec)
		return OpStatus::OK;

	return OpStatus::ERR;
}
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
	{
	X509_PUBKEY *pk=NULL;
	X509_ALGOR *a;
	ASN1_OBJECT *o;
	unsigned char *s,*p = NULL;
	int i;

	if (x == NULL) return(0);

	if ((pk=X509_PUBKEY_new()) == NULL) goto err;
	a=pk->algor;

	/* set the algorithm id */
	if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err;
	ASN1_OBJECT_free(a->algorithm);
	a->algorithm=o;

	/* Set the parameter list */
	if (!pkey->save_parameters || (pkey->type == EVP_PKEY_RSA))
		{
		if ((a->parameter == NULL) ||
			(a->parameter->type != V_ASN1_NULL))
			{
			ASN1_TYPE_free(a->parameter);
			if (!(a->parameter=ASN1_TYPE_new()))
				{
				X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
				goto err;
				}
			a->parameter->type=V_ASN1_NULL;
			}
		}
	else
#ifndef OPENSSL_NO_DSA
		if (pkey->type == EVP_PKEY_DSA)
		{
		unsigned char *pp;
		DSA *dsa;

		dsa=pkey->pkey.dsa;
		dsa->write_params=0;
		ASN1_TYPE_free(a->parameter);
		if ((i=i2d_DSAparams(dsa,NULL)) <= 0)
			goto err;
		if (!(p=(unsigned char *)OPENSSL_malloc(i)))
			{
			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		pp=p;
		i2d_DSAparams(dsa,&pp);
		if (!(a->parameter=ASN1_TYPE_new()))
			{
			OPENSSL_free(p);
			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		a->parameter->type=V_ASN1_SEQUENCE;
		if (!(a->parameter->value.sequence=ASN1_STRING_new()))
			{
			OPENSSL_free(p);
			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		if (!ASN1_STRING_set(a->parameter->value.sequence,p,i))
			{
			OPENSSL_free(p);
			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		OPENSSL_free(p);
		}
	else
#endif
		{
		X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM);
		goto err;
		}

	if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err;
	if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL)
		{
		X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	p=s;
	i2d_PublicKey(pkey,&p);
	if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i))
		{
		X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	/* Set number of unused bits to zero */
	pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
	pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;

	OPENSSL_free(s);

#if 0
	CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
	pk->pkey=pkey;
#endif

	if (*x != NULL)
		X509_PUBKEY_free(*x);

	*x=pk;

	return 1;
err:
	if (pk != NULL) X509_PUBKEY_free(pk);
	return 0;
	}
Esempio n. 12
0
int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx)
{
    int is_sct_valid = -1;
    SCT_CTX *sctx = NULL;
    X509_PUBKEY *pub = NULL, *log_pkey = NULL;
    const CTLOG *log;

    /*
     * With an unrecognized SCT version we don't know what such an SCT means,
     * let alone validate one.  So we return validation failure (0).
     */
    if (sct->version != SCT_VERSION_V1) {
        sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION;
        return 0;
    }

    log = CTLOG_STORE_get0_log_by_id(ctx->log_store,
                                     sct->log_id, sct->log_id_len);

    /* Similarly, an SCT from an unknown log also cannot be validated. */
    if (log == NULL) {
        sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG;
        return 0;
    }

    sctx = SCT_CTX_new();
    if (sctx == NULL)
        goto err;

    if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(log)) != 1)
        goto err;
    if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1)
        goto err;

    if (SCT_get_log_entry_type(sct) == CT_LOG_ENTRY_TYPE_PRECERT) {
        EVP_PKEY *issuer_pkey;

        if (ctx->issuer == NULL) {
            sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED;
            goto end;
        }

        issuer_pkey = X509_get0_pubkey(ctx->issuer);

        if (X509_PUBKEY_set(&pub, issuer_pkey) != 1)
            goto err;
        if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1)
            goto err;
    }

    /*
     * XXX: Potential for optimization.  This repeats some idempotent heavy
     * lifting on the certificate for each candidate SCT, and appears to not
     * use any information in the SCT itself, only the certificate is
     * processed.  So it may make more sense to to do this just once, perhaps
     * associated with the shared (by all SCTs) policy eval ctx.
     *
     * XXX: Failure here is global (SCT independent) and represents either an
     * issue with the certificate (e.g. duplicate extensions) or an out of
     * memory condition.  When the certificate is incompatible with CT, we just
     * mark the SCTs invalid, rather than report a failure to determine the
     * validation status.  That way, callbacks that want to do "soft" SCT
     * processing will not abort handshakes with false positive internal
     * errors.  Since the function does not distinguish between certificate
     * issues (peer's fault) and internal problems (out fault) the safe thing
     * to do is to report a validation failure and let the callback or
     * application decide what to do.
     */
    if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1)
        sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED;
    else
        sct->validation_status = SCT_verify(sctx, sct) == 1 ?
            SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID;

end:
    is_sct_valid = sct->validation_status == SCT_VALIDATION_STATUS_VALID;
err:
    X509_PUBKEY_free(pub);
    X509_PUBKEY_free(log_pkey);
    SCT_CTX_free(sctx);

    return is_sct_valid;
}
Esempio n. 13
0
CPK_MASTER_SECRET *CPK_MASTER_SECRET_create(const char *domain_id,
	EVP_PKEY *pkey, X509_ALGOR *map_algor)
{
	int e = 1;
	CPK_MASTER_SECRET *master = NULL;
	BIGNUM *bn = NULL, *order = NULL;
	X509_PUBKEY *pubkey = NULL;
	int pkey_type;
	int i, bn_size, num_factors;
	unsigned char *bn_ptr;
	
	if (strlen(domain_id) <= 0 || strlen(domain_id) > CPK_MAX_ID_LENGTH) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, CPK_R_INVALID_ID_LENGTH);
		goto err;
	}
	
	pkey_type = EVP_PKEY_id(pkey);
	if (pkey_type == EVP_PKEY_DSA) {
		if (!(order = ((DSA *)EVP_PKEY_get0(pkey))->q)) {
			CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, CPK_R_BAD_ARGUMENT);
			goto err;
		}
	} else if (pkey_type == EVP_PKEY_EC) {
		const EC_GROUP *ec_group;
		if (!(order = BN_new())) {
			CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_MALLOC_FAILURE);
			goto err;
		}
		ec_group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0(pkey));
		if (!EC_GROUP_get_order(ec_group, order, NULL)) {
			CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB);
			goto err;
		}
		//FIXME OPENSSL_assert
		assert(EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0(pkey)) != NULL);
	} else {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, CPK_R_INVALID_PKEY_TYPE);
		goto err;		
	}

	if (!(master = CPK_MASTER_SECRET_new())) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	
	master->version = 1;
	if (!X509_NAME_add_entry_by_NID(master->id, NID_organizationName,
		MBSTRING_UTF8, (unsigned char *)domain_id, -1, -1, 0)) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB);
		goto err;
	}
	
	/* 
	 * convert EVP_PKEY to X509_ALGOR through X509_PUBKEY_set
	 * X509_ALGOR_set0() is another choice but require more code
	 */
	// FIXME: X509_PUBKEY require pkey has a public key
	if (!X509_PUBKEY_set(&pubkey, pkey)) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB);
		goto err;
	}
	X509_ALGOR_free(master->pkey_algor);
	if (!(master->pkey_algor = X509_ALGOR_dup(pubkey->algor))) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB);
		goto err;
	}
		
	//FIXME: check the validity of CPK_MAP
	X509_ALGOR_free(master->map_algor);
	if (!(master->map_algor = X509_ALGOR_dup(map_algor))) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if ((num_factors = CPK_MAP_num_factors(map_algor)) <= 0) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, CPK_R_INVALID_MAP_ALGOR);
		goto err;
	}
	
	/*
	 * create secret factors, for both DSA and EC,
	 * the private keys are both big integers, 
	 */
	bn_size = BN_num_bytes(order);
	if (!ASN1_STRING_set(master->secret_factors, NULL, bn_size * num_factors)) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_ASN1_LIB);
		goto err;
	}
	bn_ptr = M_ASN1_STRING_data(master->secret_factors);
	memset(bn_ptr, 0, M_ASN1_STRING_length(master->secret_factors));
	
	if (!(bn = BN_new())) {
		CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	for (i = 0; i < num_factors; i++) {
		do {
			if (!BN_rand_range(bn, order)) {
				CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE,
					ERR_R_RAND_LIB);
				goto err;
			}
		} while (BN_is_zero(bn));
		
		if (!BN_bn2bin(bn, bn_ptr + bn_size - BN_num_bytes(bn))) {
			CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_BN_LIB);
			goto err;
		}
		bn_ptr += bn_size;
	}
	
	e = 0;
err:
	if (e && master) {
		CPK_MASTER_SECRET_free(master);
		master = NULL;
	}
	if (pubkey) X509_PUBKEY_free(pubkey);
	if (order && pkey_type == EVP_PKEY_EC) BN_free(order);
	if (bn) BN_free(bn);
	return master;
}