示例#1
0
static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
    switch (op) {
    case ASN1_PKEY_CTRL_PKCS7_SIGN:
        if (arg1 == 0) {
            int snid, hnid;
            X509_ALGOR *alg1, *alg2;
            PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
            if (alg1 == NULL || alg1->algorithm == NULL)
                return -1;
            hnid = OBJ_obj2nid(alg1->algorithm);
            if (hnid == NID_undef)
                return -1;
            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
                return -1;
            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
        }
        return 1;
#ifndef OPENSSL_NO_CMS
    case ASN1_PKEY_CTRL_CMS_SIGN:
        if (arg1 == 0) {
            int snid, hnid;
            X509_ALGOR *alg1, *alg2;
            CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
            if (alg1 == NULL || alg1->algorithm == NULL)
                return -1;
            hnid = OBJ_obj2nid(alg1->algorithm);
            if (hnid == NID_undef)
                return -1;
            if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
                return -1;
            X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
        }
        return 1;

    case ASN1_PKEY_CTRL_CMS_ENVELOPE:
        if (arg1 == 1)
            return ecdh_cms_decrypt(arg2);
        else if (arg1 == 0)
            return ecdh_cms_encrypt(arg2);
        return -2;

    case ASN1_PKEY_CTRL_CMS_RI_TYPE:
        *(int *)arg2 = CMS_RECIPINFO_AGREE;
        return 1;
#endif

    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
        *(int *)arg2 = NID_sha256;
        return 2;

    default:
        return -2;

    }

}
示例#2
0
main()
	{
	int n1, n2, n3;

	int i, rv;
#ifdef OBJ_XREF_TEST2
	for (i = 0; i <	sizeof(sigoid_srt) / sizeof(nid_triple); i++)
		{
		OBJ_add_sigid(sigoid_srt[i][0], sigoid_srt[i][1],
				sigoid_srt[i][2]);
		}
#endif

	for (i = 0; i <	sizeof(sigoid_srt) / sizeof(nid_triple); i++)
		{
		n1 = sigoid_srt[i][0];
		rv = OBJ_find_sigid_algs(n1, &n2, &n3);
		TINYCLR_SSL_PRINTF("Forward: %d, %s %s %s\n", rv,
			OBJ_nid2ln(n1), OBJ_nid2ln(n2), OBJ_nid2ln(n3));
		n1=0;
		rv = OBJ_find_sigid_by_algs(&n1, n2, n3);
		TINYCLR_SSL_PRINTF("Reverse: %d, %s %s %s\n", rv,
			OBJ_nid2ln(n1), OBJ_nid2ln(n2), OBJ_nid2ln(n3));
		}
	}
示例#3
0
static int
dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
	switch (op) {
	case ASN1_PKEY_CTRL_PKCS7_SIGN:
		if (arg1 == 0) {
			int snid, hnid;
			X509_ALGOR *alg1, *alg2;

			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
			if (alg1 == NULL || alg1->algorithm == NULL)
				return -1;
			hnid = OBJ_obj2nid(alg1->algorithm);
			if (hnid == NID_undef)
				return -1;
			if (!OBJ_find_sigid_by_algs(&snid, hnid,
			    EVP_PKEY_id(pkey)))
				return -1; 
			X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF,
			    0);
		}
		return 1;

	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
		*(int *)arg2 = NID_sha1;
		return 2;

	default:
		return -2;
	}
}
示例#4
0
int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
  if (pkey == NULL) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
    return 0;
  }

  if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
    int pad_mode;
    if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) {
      return 0;
    }
    /* RSA-PSS has special signature algorithm logic. */
    if (pad_mode == RSA_PKCS1_PSS_PADDING) {
      return x509_rsa_ctx_to_pss(ctx, algor);
    }
  }

  if (EVP_PKEY_id(pkey) == EVP_PKEY_ED25519) {
    return X509_ALGOR_set0(algor, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
  }

  /* Default behavior: look up the OID for the algorithm/hash pair and encode
   * that. */
  const EVP_MD *digest = EVP_MD_CTX_md(ctx);
  if (digest == NULL) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
    return 0;
  }

  int sign_nid;
  if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest),
                              EVP_PKEY_id(pkey))) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
    return 0;
  }

  /* RSA signature algorithms include an explicit NULL parameter. Others omit
   * it. */
  int paramtype =
      (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) ? V_ASN1_NULL : V_ASN1_UNDEF;
  X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL);
  return 1;
}
示例#5
0
int ASN1_item_sign_ctx(const ASN1_ITEM *it,
                       X509_ALGOR *algor1, X509_ALGOR *algor2,
                       ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
{
    const EVP_MD *type;
    EVP_PKEY *pkey;
    unsigned char *buf_in = NULL, *buf_out = NULL;
    size_t inl = 0, outl = 0, outll = 0;
    int signid, paramtype;
    int rv;

    type = EVP_MD_CTX_md(ctx);
    pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);

    if (!type || !pkey) {
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
        return 0;
    }

    if (pkey->ameth->item_sign) {
        rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature);
        if (rv == 1)
            outl = signature->length;
        /*-
         * Return value meanings:
         * <=0: error.
         *   1: method does everything.
         *   2: carry on as normal.
         *   3: ASN1 method sets algorithm identifiers: just sign.
         */
        if (rv <= 0)
            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
        if (rv <= 1)
            goto err;
    } else
        rv = 2;

    if (rv == 2) {
        if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
            if (!pkey->ameth ||
                !OBJ_find_sigid_by_algs(&signid,
                                        EVP_MD_nid(type),
                                        pkey->ameth->pkey_id)) {
                ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
                        ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
                return 0;
            }
        } else
            signid = type->pkey_type;

        if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
            paramtype = V_ASN1_NULL;
        else
            paramtype = V_ASN1_UNDEF;

        if (algor1)
            X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
        if (algor2)
            X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);

    }

    inl = ASN1_item_i2d(asn, &buf_in, it);
    outll = outl = EVP_PKEY_size(pkey);
    buf_out = OPENSSL_malloc((unsigned int)outl);
    if ((buf_in == NULL) || (buf_out == NULL)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
        || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
        goto err;
    }

    if (signature->data != NULL)
        OPENSSL_free(signature->data);
    signature->data = buf_out;
    buf_out = NULL;
    signature->length = outl;
    /*
     * In the interests of compatibility, I'll make sure that the bit string
     * has a 'not-used bits' value of 0
     */
    signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
    signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
 err:
    EVP_MD_CTX_cleanup(ctx);
    if (buf_in != NULL) {
        OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
        OPENSSL_free(buf_in);
    }
    if (buf_out != NULL) {
        OPENSSL_cleanse((char *)buf_out, outll);
        OPENSSL_free(buf_out);
    }
    return (outl);
}
示例#6
0
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
{
    EVP_PKEY_CTX *pctx;
    EVP_PKEY *pkey;
    EVP_CIPHER_CTX *ctx;
    int keylen;
    X509_ALGOR *talg, *wrap_alg = NULL;
    ASN1_OBJECT *aoid;
    ASN1_BIT_STRING *pubkey;
    ASN1_STRING *wrap_str;
    ASN1_OCTET_STRING *ukm;
    unsigned char *penc = NULL;
    int penclen;
    int rv = 0;
    int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
    const EVP_MD *kdf_md;
    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
    if (!pctx)
        return 0;
    /* Get ephemeral key */
    pkey = EVP_PKEY_CTX_get0_pkey(pctx);
    if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
                                             NULL, NULL, NULL))
        goto err;
    X509_ALGOR_get0(&aoid, NULL, NULL, talg);
    /* Is everything uninitialised? */
    if (aoid == OBJ_nid2obj(NID_undef)) {

        EC_KEY *eckey = pkey->pkey.ec;
        /* Set the key */
        unsigned char *p;

        penclen = i2o_ECPublicKey(eckey, NULL);
        if (penclen <= 0)
            goto err;
        penc = OPENSSL_malloc(penclen);
        if (!penc)
            goto err;
        p = penc;
        penclen = i2o_ECPublicKey(eckey, &p);
        if (penclen <= 0)
            goto err;
        ASN1_STRING_set0(pubkey, penc, penclen);
        pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
        pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;

        penc = NULL;
        X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
                        V_ASN1_UNDEF, NULL);
    }

    /* See if custom paraneters set */
    kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
    if (kdf_type <= 0)
        goto err;
    if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
        goto err;
    ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
    if (ecdh_nid < 0)
        goto err;
    else if (ecdh_nid == 0)
        ecdh_nid = NID_dh_std_kdf;
    else if (ecdh_nid == 1)
        ecdh_nid = NID_dh_cofactor_kdf;

    if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
        kdf_type = EVP_PKEY_ECDH_KDF_X9_62;
        if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
            goto err;
    } else
        /* Uknown KDF */
        goto err;
    if (kdf_md == NULL) {
        /* Fixme later for better MD */
        kdf_md = EVP_sha1();
        if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
            goto err;
    }

    if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
        goto err;

    /* Lookup NID for KDF+cofactor+digest */

    if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
        goto err;
    /* Get wrap NID */
    ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
    wrap_nid = EVP_CIPHER_CTX_type(ctx);
    keylen = EVP_CIPHER_CTX_key_length(ctx);

    /* Package wrap algorithm in an AlgorithmIdentifier */

    wrap_alg = X509_ALGOR_new();
    if (!wrap_alg)
        goto err;
    wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
    wrap_alg->parameter = ASN1_TYPE_new();
    if (!wrap_alg->parameter)
        goto err;
    if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
        goto err;
    if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
        ASN1_TYPE_free(wrap_alg->parameter);
        wrap_alg->parameter = NULL;
    }

    if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
        goto err;

    penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);

    if (!penclen)
        goto err;

    if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
        goto err;
    penc = NULL;

    /*
     * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
     * of another AlgorithmIdentifier.
     */
    penclen = i2d_X509_ALGOR(wrap_alg, &penc);
    if (!penc || !penclen)
        goto err;
    wrap_str = ASN1_STRING_new();
    if (!wrap_str)
        goto err;
    ASN1_STRING_set0(wrap_str, penc, penclen);
    penc = NULL;
    X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);

    rv = 1;

 err:
    OPENSSL_free(penc);
    X509_ALGOR_free(wrap_alg);
    return rv;
}
示例#7
0
int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
	     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
	     const EVP_MD *type)
	{
	EVP_MD_CTX ctx;
	unsigned char *buf_in=NULL,*buf_out=NULL;
	int inl=0,outl=0,outll=0;
	int signid, paramtype;

	if (type == NULL)
		{
		int def_nid;
		if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
			type = EVP_get_digestbynid(def_nid);
		}

	if (type == NULL)
		{
		ASN1err(ASN1_F_ASN1_ITEM_SIGN, ASN1_R_NO_DEFAULT_DIGEST);
		return 0;
		}

	if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
		{
		if (!pkey->ameth ||
			!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type),
						pkey->ameth->pkey_id))
			{
			ASN1err(ASN1_F_ASN1_ITEM_SIGN,
				ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
			return 0;
			}
		}
	else
		signid = type->pkey_type;

	if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
		paramtype = V_ASN1_NULL;
	else
		paramtype = V_ASN1_UNDEF;

	if (algor1)
		X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
	if (algor2)
		X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);

	EVP_MD_CTX_init(&ctx);
	inl=ASN1_item_i2d(asn,&buf_in, it);
	outll=outl=EVP_PKEY_size(pkey);
	buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
	if ((buf_in == NULL) || (buf_out == NULL))
		{
		outl=0;
		ASN1err(ASN1_F_ASN1_ITEM_SIGN,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	if (!EVP_SignInit_ex(&ctx,type, NULL)
		|| !EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl)
		|| !EVP_SignFinal(&ctx,(unsigned char *)buf_out,
			(unsigned int *)&outl,pkey))
		{
		outl=0;
		ASN1err(ASN1_F_ASN1_ITEM_SIGN,ERR_R_EVP_LIB);
		goto err;
		}
	if (signature->data != NULL) OPENSSL_free(signature->data);
	signature->data=buf_out;
	buf_out=NULL;
	signature->length=outl;
	/* In the interests of compatibility, I'll make sure that
	 * the bit string has a 'not-used bits' value of 0
	 */
	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
err:
	EVP_MD_CTX_cleanup(&ctx);
	if (buf_in != NULL)
		{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
	if (buf_out != NULL)
		{ OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
	return(outl);
	}
/**
 *
 * \brief Generates a digest then sends the digest to the
 *        ATECCX08 chip to generate an ECDSA signature using
 *        private key from TLS_SLOT_AUTH_PRIV slot. The private
 *        key is always stays in the chip: OpenSSL (nor any
 *        other software) has no way to read it.
 *
 * \param[in] ctx - a pointer to the EVP_MD_CTX structure
 * \param[in] it - a pointer to the ASN1_ITEM structure
 * \param[in] asn - a void pointer to the parameter
 * \param[in] algor1 - a pointer to the X509_ALGOR structure
 * \param[in] algor2 - a pointer to the X509_ALGOR structure
 * \param[out] signature - a pointer to the ASN1_BIT_STRING
 *       structure to return the signature in the ASN.1 format
 * \return 1 for success
 */
int eccx08_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
                     X509_ALGOR *algor1, X509_ALGOR *algor2,
                     ASN1_BIT_STRING *signature)
{
    int rc = 0;
    int ret = 0;
    const EVP_MD *type;
    EVP_PKEY *pkey;
    uint8_t *buf_in = NULL, *buf_out = NULL;
    uint8_t *sig_in = NULL, *sig_out = NULL;
    size_t inl = 0, outl = 0, outll = 0;
    int signid, paramtype;
    uint8_t slotid = TLS_SLOT_AUTH_PRIV;
    ATCA_STATUS status = ATCA_GEN_FAIL;

    extern ECDSA_METHOD eccx08_ecdsa;

    type = EVP_MD_CTX_md(ctx);
    pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);

    if (!type || !pkey) {
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
        return 0;
    }

    if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
        if (!pkey->ameth ||
            !OBJ_find_sigid_by_algs(&signid,
                                    EVP_MD_nid(type),
                                    pkey->ameth->pkey_id)) {
            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
                    ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
            return 0;
        }
    } else signid = type->pkey_type;

    if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) paramtype = V_ASN1_NULL;
    else paramtype = V_ASN1_UNDEF;

    if (algor1) X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
    if (algor2) X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);

    inl = ASN1_item_i2d(asn, &buf_in, it);
    outll = outl = EVP_PKEY_size(pkey);
    buf_out = OPENSSL_malloc((unsigned int)outl);
    if ((buf_in == NULL) || (buf_out == NULL)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
        goto done;
    }
#ifdef USE_ECCX08
    eccx08_debug("eccx08_item_sign() - HW\n");

    ret = EVP_DigestUpdate(ctx, buf_in, inl);
    if (!ret) goto done;
    ret = EVP_DigestFinal(ctx, buf_out, (unsigned int *)&outl);
    if (!ret) goto done;
    sig_in = OPENSSL_malloc((unsigned int)outll);  // source of crash
    sig_out = sig_in;
    if (sig_in == NULL) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
        goto done;
    }
    ECDSA_SIG *ecdsasig;
    ecdsasig = eccx08_ecdsa.ecdsa_do_sign(buf_out, outl, NULL, NULL, pkey->pkey.ec);
    if (ecdsasig == NULL) goto done;
    outl = i2d_ECDSA_SIG(ecdsasig, &sig_in);
    if (ecdsasig->r) {
        BN_free(ecdsasig->r);
        ecdsasig->r = NULL;
    }
    if (ecdsasig->s) {
        BN_free(ecdsasig->s);
        ecdsasig->s = NULL;
    }
    ECDSA_SIG_free(ecdsasig);

#else // USE_ECCX08
    eccx08_debug("eccx08_item_sign() - SW\n");
    if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
        || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
        goto done;
    }
#endif // USE_ECCX08
    if (signature->data != NULL) {
        OPENSSL_free(signature->data);
    }
#ifdef USE_ECCX08
    signature->data = sig_out;
    sig_out = NULL;
#else
    signature->data = buf_out;
    buf_out = NULL;
#endif
    signature->length = outl;
    /* 
     * ASN1_item_sign_ctx() in a_sign.c comment (just copy it here): 
     * In the interests of compatibility, I'll make sure that the bit string
     * has a 'not-used bits' value of 0
     */
    signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
    signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;

    rc = 1;
done:
    EVP_MD_CTX_cleanup(ctx);
    if (buf_in != NULL) {
        OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
        OPENSSL_free(buf_in);
    }
    if (buf_out != NULL) {
        OPENSSL_cleanse((char *)buf_out, outll);
        OPENSSL_free(buf_out);
    }
    if (sig_out != NULL) {
        OPENSSL_cleanse((char *)sig_out, outll);
        OPENSSL_free(sig_out);
    }
    return (rc);
}