//Create base 64 encoded digital signature of given data
bool digiSign(StringBuffer &b64Signature, size32_t dataSz, const void *data, const CLoadedKey &signingKey)
{
    OwnedEVPMdCtx signingCtx(EVP_MD_CTX_create());
    //initialize context for SHA-256 hashing function
    int rc = EVP_DigestSignInit(signingCtx, nullptr, EVP_sha256(), nullptr, signingKey);
    if (rc <= 0)
        throwEVPException(-1, "digiSign:EVP_DigestSignInit");

    //add string to the context
    if (EVP_DigestSignUpdate(signingCtx, data, dataSz) <= 0)
        throwEVPException(-1, "digiSign:EVP_DigestSignUpdate");

    //compute length of signature
    size_t encMsgLen;
    if (EVP_DigestSignFinal(signingCtx, nullptr, &encMsgLen) <= 0)
        throwEVPException(-1, "digiSign:EVP_DigestSignFinal1");

    if (encMsgLen == 0)
        throwEVPException(-1, "digiSign:EVP_DigestSignFinal length returned 0");

    //compute signature (signed digest)
    OwnedEVPMemory encMsg = OPENSSL_malloc(encMsgLen);
    if (encMsg == nullptr)
        throw MakeStringException(-1, "digiSign:OPENSSL_malloc(%u) returned NULL", (unsigned)encMsgLen);

    if (EVP_DigestSignFinal(signingCtx, (unsigned char *)encMsg.get(), &encMsgLen) <= 0)
        throwEVPException(-1, "digiSign:EVP_DigestSignFinal2");

    //convert to base64
    JBASE64_Encode(encMsg, encMsgLen, b64Signature, false);

    return true;
}
Exemple #2
0
static int PKCS7_SIGNER_INFO_sign_0(PKCS7_SIGNER_INFO *si)
{
  EVP_MD_CTX mctx;
  EVP_PKEY_CTX *pctx;
  unsigned char *abuf = NULL;
  int alen;
  size_t siglen;
  const EVP_MD *md = NULL;

  md = EVP_get_digestbyobj(si->digest_alg->algorithm);
  if (md == NULL)
    return 0;

  EVP_MD_CTX_init(&mctx);
  if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
    goto err;

  if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
                        EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0)
  {
    PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
    goto err;
  }

  alen = ASN1_item_i2d((ASN1_VALUE *) si->auth_attr, &abuf,
                       ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
  if (!abuf)
    goto err;
  if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0)
    goto err;
  OPENSSL_free(abuf);
  abuf = NULL;
  if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0)
    goto err;
  abuf = OPENSSL_malloc(siglen);
  if (!abuf)
    goto err;

  if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0)
    goto err;
  if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
                        EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0)
  {
    PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
    goto err;
  }

  EVP_MD_CTX_cleanup(&mctx);

  ASN1_STRING_set0(si->enc_digest, abuf, siglen);

  return 1;

err:
  if (abuf)
    OPENSSL_free(abuf);
  EVP_MD_CTX_cleanup(&mctx);
  return 0;

}
Handle<std::string> RSA_PKCS1_sign(Handle<ScopedEVP_PKEY> hKey, const EVP_MD *md, Handle<std::string> hData) {
    LOG_FUNC();

    ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
    EVP_PKEY_CTX* pctx = nullptr;

    size_t siglen = 0;
    if (ctx.isEmpty() ||
            !EVP_DigestSignInit(ctx.Get(), &pctx, md, nullptr, hKey->Get())) {
        THROW_OPENSSL("EVP_DigestSignInit");
    }

    byte* data = (byte*)hData->c_str();
    size_t datalen = hData->length();

    if (1 != EVP_DigestSignUpdate(ctx.Get(), data, datalen)) {
        THROW_OPENSSL("EVP_DigestSignUpdate");
    }
    if (1 != EVP_DigestSignFinal(ctx.Get(), nullptr, &siglen)) {
        THROW_OPENSSL("EVP_DigestSignFinal");
    }

    Handle<std::string> hOutput(new std::string());
    hOutput->resize(siglen);
    byte *output = (byte*)hOutput->c_str();

    if (!EVP_DigestSignFinal(ctx.Get(), output, &siglen))
        THROW_OPENSSL("EVP_DigestSignFinal");

    return hOutput;
}
int signMsgRSA(EVP_PKEY* key, const unsigned char* msg, 
	unsigned char** sig, size_t* slen, size_t msglen){
	
	EVP_MD_CTX* ctx = NULL;
	const EVP_MD* md = NULL;
	
	if(msg == NULL || sig == NULL || slen == NULL)
		return 0;

	ctx = EVP_MD_CTX_create();
	md = EVP_get_digestbyname(hn);

	if(md == NULL){
		printf("ERR EVP_get_digestbyname\n");
		return 0;		
	}
	if(ctx == NULL){
		printf("ERR EVP_MD_CTX_create\n");
		return 0;		
	}

	if(1 != EVP_DigestInit_ex(ctx, md, NULL)){
		printf("ERR EVP_DigestInit_ex\n");
		return 0;
	}
	if(1 != EVP_DigestSignInit(ctx, NULL, md, NULL, key)){
		printf("ERR EVP_DigestSignInit\n");
		return 0;
	}

	/*SE FIRMA EL MENSAJE*/
	if(1 != EVP_DigestSignUpdate(ctx, msg, msglen)){
		printf("ERR EVP_DigestSignUpdate\n");
		return 0;
	}

	if(1 != EVP_DigestSignFinal(ctx, NULL, slen)){
		printf("ERR EVP_DigestSignFinal\n");
		return 0;	
	}
	*sig = OPENSSL_malloc(*slen);
	
	if(*sig == NULL){
		printf("ERR OPENSSL_malloc\n");
	}

	if(1 != EVP_DigestSignFinal(ctx, *sig, slen)){
		printf("ERR EVP_DigestSignFinal\n");
		return 0;
	}

	EVP_MD_CTX_destroy(ctx);
	ctx = NULL;

	return 1;

}
Exemple #5
0
static int test_EVP_DigestSignInit(void) {
  int ret = 0;
  EVP_PKEY *pkey = NULL;
  uint8_t *sig = NULL;
  size_t sig_len = 0;
  EVP_MD_CTX md_ctx, md_ctx_verify;

  EVP_MD_CTX_init(&md_ctx);
  EVP_MD_CTX_init(&md_ctx_verify);

  pkey = load_example_rsa_key();
  if (pkey == NULL ||
      !EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
      !EVP_DigestSignUpdate(&md_ctx, kMsg, sizeof(kMsg))) {
    goto out;
  }
  /* Determine the size of the signature. */
  if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) {
    goto out;
  }
  /* Sanity check for testing. */
  if (sig_len != EVP_PKEY_size(pkey)) {
    fprintf(stderr, "sig_len mismatch\n");
    goto out;
  }

  sig = malloc(sig_len);
  if (sig == NULL || !EVP_DigestSignFinal(&md_ctx, sig, &sig_len)) {
    goto out;
  }

  /* Ensure that the signature round-trips. */
  if (!EVP_DigestVerifyInit(&md_ctx_verify, NULL, EVP_sha256(), NULL, pkey) ||
      !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
      !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
    goto out;
  }

  ret = 1;

out:
  if (!ret) {
    BIO_print_errors_fp(stderr);
  }

  EVP_MD_CTX_cleanup(&md_ctx);
  EVP_MD_CTX_cleanup(&md_ctx_verify);
  if (pkey) {
    EVP_PKEY_free(pkey);
  }
  if (sig) {
    free(sig);
  }

  return ret;
}
Exemple #6
0
static int test_EVP_DigestSignInit(void)
{
    int ret = 0;
    EVP_PKEY *pkey = NULL;
    unsigned char *sig = NULL;
    size_t sig_len = 0;
    EVP_MD_CTX *md_ctx, *md_ctx_verify;

    md_ctx = EVP_MD_CTX_new();
    md_ctx_verify = EVP_MD_CTX_new();
    if (md_ctx == NULL || md_ctx_verify == NULL)
        goto out;

    pkey = load_example_rsa_key();
    if (pkey == NULL ||
        !EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
        !EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
        goto out;
    }
    /* Determine the size of the signature. */
    if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
        goto out;
    }
    /* Sanity check for testing. */
    if (sig_len != (size_t)EVP_PKEY_size(pkey)) {
        fprintf(stderr, "sig_len mismatch\n");
        goto out;
    }

    sig = OPENSSL_malloc(sig_len);
    if (sig == NULL || !EVP_DigestSignFinal(md_ctx, sig, &sig_len)) {
        goto out;
    }

    /* Ensure that the signature round-trips. */
    if (!EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sha256(), NULL, pkey)
        || !EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, sizeof(kMsg))
        || !EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len)) {
        goto out;
    }

    ret = 1;

 out:
    if (!ret) {
        ERR_print_errors_fp(stderr);
    }

    EVP_MD_CTX_free(md_ctx);
    EVP_MD_CTX_free(md_ctx_verify);
    EVP_PKEY_free(pkey);
    OPENSSL_free(sig);

    return ret;
}
Exemple #7
0
/* test_algorithm_roundtrip signs a message using an already-initialized
 * |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
 * AlgorithmIdentifier to verify the signature. */
static int test_algorithm_roundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
  int ret = 0;
  uint8_t *sig = NULL;
  size_t sig_len = 0;
  EVP_MD_CTX md_ctx_verify;
  X509_ALGOR *algor = NULL;

  EVP_MD_CTX_init(&md_ctx_verify);

  if (!EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
    goto out;
  }

  /* Save the algorithm. */
  algor = X509_ALGOR_new();
  if (algor == NULL || !EVP_DigestSignAlgorithm(md_ctx, algor)) {
    goto out;
  }

  /* Determine the size of the signature. */
  if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
    goto out;
  }
  /* Sanity check for testing. */
  if (sig_len != EVP_PKEY_size(pkey)) {
    fprintf(stderr, "sig_len mismatch\n");
    goto out;
  }

  sig = malloc(sig_len);
  if (sig == NULL || !EVP_DigestSignFinal(md_ctx, sig, &sig_len)) {
    goto out;
  }

  /* Ensure that the signature round-trips. */
  if (!EVP_DigestVerifyInitFromAlgorithm(&md_ctx_verify, algor, pkey) ||
      !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
      !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
    goto out;
  }

  ret = 1;

out:
  EVP_MD_CTX_cleanup(&md_ctx_verify);
  if (sig) {
    free(sig);
  }
  if (algor) {
    X509_ALGOR_free(algor);
  }

  return ret;
}
Exemple #8
0
static int sign_it(const unsigned char *msg, size_t mlen, unsigned char **sig, size_t *slen, EVP_PKEY *pkey) {
    int result = GS_FAILED;
    
    *sig = NULL;
    *slen = 0;
    
    EVP_MD_CTX *ctx = EVP_MD_CTX_create();
    if (ctx == NULL)
        return GS_FAILED;
    
    const EVP_MD *md = EVP_get_digestbyname("SHA256");
    if (md == NULL)
        goto cleanup;
    
    int rc = EVP_DigestInit_ex(ctx, md, NULL);
    if (rc != 1)
        goto cleanup;
    
    rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey);
    if (rc != 1)
        goto cleanup;
    
    rc = EVP_DigestSignUpdate(ctx, msg, mlen);
    if (rc != 1)
        goto cleanup;
    
    size_t req = 0;
    rc = EVP_DigestSignFinal(ctx, NULL, &req);
    if (rc != 1 || !(req > 0))
        goto cleanup;
    
    *sig = OPENSSL_malloc(req);
    if (*sig == NULL)
        goto cleanup;
    
    *slen = req;
    rc = EVP_DigestSignFinal(ctx, *sig, slen);
    if (rc != 1 || req != *slen)
        goto cleanup;
    
    result = GS_OK;
    
cleanup:
    EVP_MD_CTX_destroy(ctx);
    ctx = NULL;
    
    return result;
}
Exemple #9
0
static int sign(void *ctx,char *file,void *in,int ilen,void *out,int *olen)
{
	int r=NOCARD;
	size_t slen=*olen;
	ENGINE *e=(ENGINE *)ctx;
	EVP_PKEY *key;
	EVP_MD_CTX *mdc;

	resume_engine(e,engbits);

	if(!(key=ENGINE_load_private_key(e,file,NULL,NULL)))goto err1;

	r=CRYPTOFAIL;
	if(!(mdc=EVP_MD_CTX_create()))goto err2;
	if(EVP_DigestInit_ex(mdc,EVP_sha256(),NULL)!=1)goto err3;
	if(EVP_DigestSignInit(mdc,NULL,EVP_sha256(),NULL,key)!=1)goto err3;
	if(EVP_DigestSignUpdate(mdc,in,ilen)!=1)goto err3;
	if(EVP_DigestSignFinal(mdc,out,&slen)!=1)goto err3;
	*olen=slen;
	r=OK;

err3:	EVP_MD_CTX_destroy(mdc);
err2:	EVP_PKEY_free(key);
err1:	suspend_engine(e,&engbits);
	return r;
}
Exemple #10
0
/*
 * Generates the mac for the Finished message. Returns the length of the MAC or
 * 0 on error.
 */
size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
                             unsigned char *out)
{
    const EVP_MD *md = ssl_handshake_md(s);
    unsigned char hash[EVP_MAX_MD_SIZE];
    size_t hashlen, ret = 0;
    EVP_PKEY *key = NULL;
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();

    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen))
        goto err;

    if (str == s->method->ssl3_enc->server_finished_label)
        key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
                                   s->server_finished_secret, hashlen);
    else
        key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
                                   s->client_finished_secret, hashlen);

    if (key == NULL
            || ctx == NULL
            || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0
            || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0
            || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0)
        goto err;

    ret = hashlen;
 err:
    EVP_PKEY_free(key);
    EVP_MD_CTX_free(ctx);
    return ret;
}
Exemple #11
0
void
SignerFilter::finalize()
{
  size_t sigLen = 0;
  if (EVP_DigestSignFinal(m_impl->ctx, nullptr, &sigLen) != 1)
    NDN_THROW(Error(getIndex(), "Failed to estimate buffer length"));

  auto buffer = make_unique<OBuffer>(sigLen);
  if (EVP_DigestSignFinal(m_impl->ctx, buffer->data(), &sigLen) != 1)
    NDN_THROW(Error(getIndex(), "Failed to finalize signature"));

  buffer->erase(buffer->begin() + sigLen, buffer->end());
  setOutputBuffer(std::move(buffer));

  flushAllOutput();
}
Exemple #12
0
static int ssl_sign_ecdsa(SSL *ssl, uint8_t *out, size_t *out_len,
                          size_t max_out, int curve, const EVP_MD *md,
                          const uint8_t *in, size_t in_len) {
  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey);
  if (ec_key == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
    return 0;
  }

  /* In TLS 1.3, the curve is also specified by the signature algorithm. */
  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
      (curve == NID_undef ||
       EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
    return 0;
  }

  EVP_MD_CTX ctx;
  EVP_MD_CTX_init(&ctx);
  *out_len = max_out;
  int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
            EVP_DigestSignUpdate(&ctx, in, in_len) &&
            EVP_DigestSignFinal(&ctx, out, out_len);
  EVP_MD_CTX_cleanup(&ctx);
  return ret;
}
Exemple #13
0
static int s2n_evp_hmac_p_hash_digest(struct s2n_prf_working_space *ws, void *digest, uint32_t size)
{
    /* EVP_DigestSign API's require size_t data structures */
    size_t digest_size = size;

    GUARD_OSSL(EVP_DigestSignFinal(ws->tls.p_hash.evp_hmac.evp_digest.ctx, (unsigned char *)digest, &digest_size), S2N_ERR_P_HASH_FINAL_FAILED);

    return 0;
}
Exemple #14
0
int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
                   const unsigned char *tbs, size_t tbslen)
{
    if (ctx->pctx->pmeth->digestsign != NULL)
        return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen);
    if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0)
        return 0;
    return EVP_DigestSignFinal(ctx, sigret, siglen);
}
static int test_EVP_DigestSignInit(void)
{
    int ret = 0;
    EVP_PKEY *pkey = NULL;
    unsigned char *sig = NULL;
    size_t sig_len = 0;
    EVP_MD_CTX *md_ctx, *md_ctx_verify = NULL;

    if (!TEST_ptr(md_ctx = EVP_MD_CTX_new())
            || !TEST_ptr(md_ctx_verify = EVP_MD_CTX_new())
            || !TEST_ptr(pkey = load_example_rsa_key()))
        goto out;

    if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey))
            || !TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))))
        goto out;

    /* Determine the size of the signature. */
    if (!TEST_true(EVP_DigestSignFinal(md_ctx, NULL, &sig_len))
            || !TEST_size_t_eq(sig_len, (size_t)EVP_PKEY_size(pkey)))
        goto out;

    if (!TEST_ptr(sig = OPENSSL_malloc(sig_len))
            || !TEST_true(EVP_DigestSignFinal(md_ctx, sig, &sig_len)))
        goto out;

    /* Ensure that the signature round-trips. */
    if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sha256(),
                                        NULL, pkey))
            || !TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify,
                                                 kMsg, sizeof(kMsg)))
            || !TEST_true(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len)))
        goto out;

    ret = 1;

 out:
    EVP_MD_CTX_free(md_ctx);
    EVP_MD_CTX_free(md_ctx_verify);
    EVP_PKEY_free(pkey);
    OPENSSL_free(sig);

    return ret;
}
Exemple #16
0
char *compute_and_encode_signature(const grpc_auth_json_key *json_key,
                                   const char *signature_algorithm,
                                   const char *to_sign) {
  const EVP_MD *md = openssl_digest_from_algorithm(signature_algorithm);
  EVP_MD_CTX *md_ctx = NULL;
  EVP_PKEY *key = EVP_PKEY_new();
  size_t sig_len = 0;
  unsigned char *sig = NULL;
  char *result = NULL;
  if (md == NULL) return NULL;
  md_ctx = EVP_MD_CTX_create();
  if (md_ctx == NULL) {
    gpr_log(GPR_ERROR, "Could not create MD_CTX");
    goto end;
  }
  EVP_PKEY_set1_RSA(key, json_key->private_key);
  if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, key) != 1) {
    gpr_log(GPR_ERROR, "DigestInit failed.");
    goto end;
  }
  if (EVP_DigestSignUpdate(md_ctx, to_sign, strlen(to_sign)) != 1) {
    gpr_log(GPR_ERROR, "DigestUpdate failed.");
    goto end;
  }
  if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) {
    gpr_log(GPR_ERROR, "DigestFinal (get signature length) failed.");
    goto end;
  }
  sig = gpr_malloc(sig_len);
  if (EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) {
    gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed.");
    goto end;
  }
  result = grpc_base64_encode(sig, sig_len, 1, 0);

end:
  if (key != NULL) EVP_PKEY_free(key);
  if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
  if (sig != NULL) gpr_free(sig);
  return result;
}
Exemple #17
0
static bool
sig_done(jose_io_t *io)
{
    io_t *i = containerof(io, io_t, io);
    size_t len = 0;

    if (EVP_DigestSignFinal(i->emc, NULL, &len) <= 0)
        return false;

    uint8_t buf[len];

    if (EVP_DigestSignFinal(i->emc, buf, &len) <= 0)
        return false;

    if (json_object_set_new(i->sig, "signature",
                            jose_b64_enc(buf, len)) < 0)
        return false;

    return add_entity(i->obj, i->sig,
                      "signatures", "signature", "protected", "header", NULL);
}
Exemple #18
0
int
lws_genhmac_destroy(struct lws_genhmac_ctx *ctx, void *result)
{
	size_t size = lws_genhmac_size(ctx->type);
	int n = EVP_DigestSignFinal(ctx->ctx, result, &size);

	EVP_MD_CTX_destroy(ctx->ctx);
	if (n != 1)
		return -1;

	return 0;
}
Exemple #19
0
static int ssl_sign_rsa_pkcs1(SSL *ssl, uint8_t *out, size_t *out_len,
                              size_t max_out, const EVP_MD *md,
                              const uint8_t *in, size_t in_len) {
  EVP_MD_CTX ctx;
  EVP_MD_CTX_init(&ctx);
  *out_len = max_out;
  int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
            EVP_DigestSignUpdate(&ctx, in, in_len) &&
            EVP_DigestSignFinal(&ctx, out, out_len);
  EVP_MD_CTX_cleanup(&ctx);
  return ret;
}
QByteArray
NvPairingManager::signMessage(QByteArray message)
{
    EVP_MD_CTX *ctx = EVP_MD_CTX_create();
    THROW_BAD_ALLOC_IF_NULL(ctx);

    const EVP_MD *md = EVP_get_digestbyname("SHA256");
    THROW_BAD_ALLOC_IF_NULL(md);

    EVP_DigestInit_ex(ctx, md, NULL);
    EVP_DigestSignInit(ctx, NULL, md, NULL, m_PrivateKey);
    EVP_DigestSignUpdate(ctx, reinterpret_cast<unsigned char*>(message.data()), message.length());

    size_t signatureLength = 0;
    EVP_DigestSignFinal(ctx, NULL, &signatureLength);

    QByteArray signature((int)signatureLength, 0);
    EVP_DigestSignFinal(ctx, reinterpret_cast<unsigned char*>(signature.data()), &signatureLength);

    EVP_MD_CTX_destroy(ctx);

    return signature;
}
Exemple #21
0
/*
 * Generates the mac for the Finished message. Returns the length of the MAC or
 * 0 on error.
 */
size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
                             unsigned char *out)
{
    const EVP_MD *md = ssl_handshake_md(s);
    unsigned char hash[EVP_MAX_MD_SIZE];
    size_t hashlen, ret = 0;
    EVP_PKEY *key = NULL;
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();

    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
        /* SSLfatal() already called */
        goto err;
    }

    if (str == s->method->ssl3_enc->server_finished_label) {
        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
                                           s->server_finished_secret, hashlen);
    } else if (SSL_IS_FIRST_HANDSHAKE(s)) {
        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
                                           s->client_finished_secret, hashlen);
    } else {
        unsigned char finsecret[EVP_MAX_MD_SIZE];

        if (!tls13_derive_finishedkey(s, ssl_handshake_md(s),
                                      s->client_app_traffic_secret,
                                      finsecret, hashlen))
            goto err;

        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret,
                                           hashlen);
        OPENSSL_cleanse(finsecret, sizeof(finsecret));
    }

    if (key == NULL
            || ctx == NULL
            || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0
            || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0
            || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) {
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC,
                 ERR_R_INTERNAL_ERROR);
        goto err;
    }

    ret = hashlen;
 err:
    EVP_PKEY_free(key);
    EVP_MD_CTX_free(ctx);
    return ret;
}
Exemple #22
0
soter_status_t soter_sign_final_rsa_pss_pkcs8(soter_sign_ctx_t* ctx, void* signature, size_t* signature_length)
{
    EVP_PKEY* pkey = EVP_PKEY_CTX_get0_pkey(ctx->pkey_ctx);
    if (!pkey) {
        return SOTER_INVALID_PARAMETER;
    }
    if ((*signature_length) < (size_t)EVP_PKEY_size(pkey)) {
        (*signature_length) = (size_t)EVP_PKEY_size(pkey);
        return SOTER_BUFFER_TOO_SMALL;
    }
    if (!EVP_DigestSignFinal(ctx->md_ctx, signature, signature_length)) {
        return SOTER_FAIL;
    }
    return SOTER_SUCCESS;
}
Exemple #23
0
static int ssl_sign_rsa_pss(SSL *ssl, uint8_t *out, size_t *out_len,
                              size_t max_out, const EVP_MD *md,
                              const uint8_t *in, size_t in_len) {
  EVP_MD_CTX ctx;
  EVP_MD_CTX_init(&ctx);
  *out_len = max_out;
  EVP_PKEY_CTX *pctx;
  int ret =
      EVP_DigestSignInit(&ctx, &pctx, md, NULL, ssl->cert->privatekey) &&
      EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
      EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
      EVP_DigestSignUpdate(&ctx, in, in_len) &&
      EVP_DigestSignFinal(&ctx, out, out_len);
  EVP_MD_CTX_cleanup(&ctx);
  return ret;
}
soter_status_t soter_sign_final_ecdsa_none_pkcs8(soter_sign_ctx_t* ctx, void* signature, size_t *signature_length)
{
  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pkey_ctx);
  if (!pkey && EVP_PKEY_base_id(pkey)!=EVP_PKEY_EC){
    return SOTER_INVALID_PARAMETER;
  } /* TODO: need review */
  soter_status_t res = SOTER_SUCCESS;
  if(!signature || (*signature_length)<(size_t)EVP_PKEY_size(pkey)){
    (*signature_length)=(size_t)EVP_PKEY_size(pkey);
    res = SOTER_BUFFER_TOO_SMALL;
  } else {
      if(EVP_DigestSignFinal(ctx->md_ctx, signature, signature_length)!=1)
	res = SOTER_INVALID_SIGNATURE;
  }
  return res;
}
Exemple #25
0
static LUA_FUNCTION(openssl_signFinal)
{
  EVP_MD_CTX *ctx = CHECK_OBJECT(1, EVP_MD_CTX, "openssl.evp_digest_ctx");
  EVP_PKEY *pkey = lua_gettop(L) > 1 ? CHECK_OBJECT(2, EVP_PKEY, "openssl.evp_pkey") : NULL;
  size_t siglen = EVP_PKEY_size(pkey);
  unsigned char *sigbuf = malloc(siglen + 1);
  int ret = 0;
  if (pkey)
    ret = EVP_SignFinal(ctx, sigbuf, (unsigned int *)&siglen, pkey);
  else
    ret = EVP_DigestSignFinal(ctx, sigbuf, &siglen);
  if (ret == 1)
  {
    lua_pushlstring(L, (char *)sigbuf, siglen);
  }
  free(sigbuf);
  EVP_MD_CTX_cleanup(ctx);
  if (ret == 1)
    return 1;
  return openssl_pushresult(L, ret);
}
Exemple #26
0
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
          EVP_PKEY *key, unsigned char *sigin, int siglen,
          const char *sig_name, const char *md_name,
          const char *file, BIO *bmd)
{
    size_t len;
    int i;

    for (;;) {
        i = BIO_read(bp, (char *)buf, BUFSIZE);
        if (i < 0) {
            BIO_printf(bio_err, "Read Error in %s\n", file);
            ERR_print_errors(bio_err);
            return 1;
        }
        if (i == 0)
            break;
    }
    if (sigin) {
        EVP_MD_CTX *ctx;
        BIO_get_md_ctx(bp, &ctx);
        i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
        if (i > 0)
            BIO_printf(out, "Verified OK\n");
        else if (i == 0) {
            BIO_printf(out, "Verification Failure\n");
            return 1;
        } else {
            BIO_printf(bio_err, "Error Verifying Data\n");
            ERR_print_errors(bio_err);
            return 1;
        }
        return 0;
    }
    if (key) {
        EVP_MD_CTX *ctx;
        BIO_get_md_ctx(bp, &ctx);
        len = BUFSIZE;
        if (!EVP_DigestSignFinal(ctx, buf, &len)) {
            BIO_printf(bio_err, "Error Signing Data\n");
            ERR_print_errors(bio_err);
            return 1;
        }
    } else {
        len = BIO_gets(bp, (char *)buf, BUFSIZE);
        if ((int)len < 0) {
            ERR_print_errors(bio_err);
            return 1;
        }
    }

    if (binout)
        BIO_write(out, buf, len);
    else if (sep == 2) {
        for (i = 0; i < (int)len; i++)
            BIO_printf(out, "%02x", buf[i]);
        BIO_printf(out, " *%s\n", file);
    } else {
        if (sig_name) {
            BIO_puts(out, sig_name);
            if (md_name)
                BIO_printf(out, "-%s", md_name);
            BIO_printf(out, "(%s)= ", file);
        } else if (md_name)
            BIO_printf(out, "%s(%s)= ", md_name, file);
        else
            BIO_printf(out, "(%s)= ", file);
        for (i = 0; i < (int)len; i++) {
            if (sep && (i != 0))
                BIO_printf(out, ":");
            BIO_printf(out, "%02x", buf[i]);
        }
        BIO_printf(out, "\n");
    }
    return 0;
}
Exemple #27
0
int tls1_mac(SSL *ssl, unsigned char *md, int send)
	{
	SSL3_RECORD *rec;
	unsigned char *seq;
	EVP_MD_CTX *hash;
	size_t md_size;
	int i;
	EVP_MD_CTX hmac, *mac_ctx;
	unsigned char buf[5]; 
	int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM));
	int t;

	if (send)
		{
		rec= &(ssl->s3->wrec);
		seq= &(ssl->s3->write_sequence[0]);
		hash=ssl->write_hash;
		}
	else
		{
		rec= &(ssl->s3->rrec);
		seq= &(ssl->s3->read_sequence[0]);
		hash=ssl->read_hash;
		}

	t=EVP_MD_CTX_size(hash);
	TINYCLR_SSL_ASSERT(t >= 0);
	md_size=t;

	buf[0]=rec->type;
	buf[1]=(unsigned char)(ssl->version>>8);
	buf[2]=(unsigned char)(ssl->version);
	buf[3]=rec->length>>8;
	buf[4]=rec->length&0xff;

	/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
	if (stream_mac) 
		{
			mac_ctx = hash;
		}
		else
		{
			EVP_MD_CTX_copy(&hmac,hash);
			mac_ctx = &hmac;
		}

	if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER)
		{
		unsigned char dtlsseq[8],*p=dtlsseq;

		s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
		TINYCLR_SSL_MEMCPY (p,&seq[2],6);

		EVP_DigestSignUpdate(mac_ctx,dtlsseq,8);
		}
	else
		EVP_DigestSignUpdate(mac_ctx,seq,8);

	EVP_DigestSignUpdate(mac_ctx,buf,5);
	EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
	t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
	TINYCLR_SSL_ASSERT(t > 0);
		
	if (!stream_mac) EVP_MD_CTX_cleanup(&hmac);
#ifdef TLS_DEBUG
TINYCLR_SSL_PRINTF("sec=");
{unsigned int z; for (z=0; z<md_size; z++) TINYCLR_SSL_PRINTF("%02X ",mac_sec[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("seq=");
{int z; for (z=0; z<8; z++) TINYCLR_SSL_PRINTF("%02X ",seq[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("buf=");
{int z; for (z=0; z<5; z++) TINYCLR_SSL_PRINTF("%02X ",buf[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) TINYCLR_SSL_PRINTF("%02X ",buf[z]); TINYCLR_SSL_PRINTF("\n"); }
#endif

	if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER)
		{
		for (i=7; i>=0; i--)
			{
			++seq[i];
			if (seq[i] != 0) break; 
			}
		}

#ifdef TLS_DEBUG
{unsigned int z; for (z=0; z<md_size; z++) TINYCLR_SSL_PRINTF("%02X ",md[z]); TINYCLR_SSL_PRINTF("\n"); }
#endif
	return(md_size);
	}
Exemple #28
0
int main()
{
	int ret = -1;
	int verbose = 0;
	BIO *out = NULL;

	int id = EVP_PKEY_SM2;
	const EVP_MD *md = EVP_sm3();
	ENGINE *engine = NULL;

	EVP_PKEY_CTX *pkctx = NULL;
	EVP_PKEY *pkey = NULL;
	EVP_MD_CTX *mdctx = NULL;
	EVP_CIPHER_CTX *cpctx = NULL;

	unsigned char dgst[EVP_MAX_MD_SIZE] = "hello world";
	size_t dgstlen = 32;
	unsigned char sig[256];
	size_t siglen = sizeof(sig);

	unsigned char msg[] = "hello world this is the message";
	size_t msglen = sizeof(msg);
	unsigned char cbuf[512];
	size_t cbuflen = sizeof(cbuf);
	unsigned char mbuf[512];
	size_t mbuflen = sizeof(mbuf);

	int len;
	unsigned int ulen;

	ERR_load_crypto_strings();

	out = BIO_new_fp(stdout, BIO_NOCLOSE);

	if (!(pkctx = EVP_PKEY_CTX_new_id(id, engine))) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_PKEY_keygen_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_PKEY_keygen(pkctx, &pkey)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	EVP_PKEY_CTX_free(pkctx);

	if (0) {
		EVP_PKEY_print_public(out, pkey, 4, NULL);
		BIO_printf(out, "\n");
		EVP_PKEY_print_private(out, pkey, 4, NULL);
		BIO_printf(out, "\n");
	}

	if (!(pkctx = EVP_PKEY_CTX_new(pkey, engine))) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	/* EVP_PKEY_sign() */

	if (!EVP_PKEY_sign_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	bzero(sig, sizeof(sig));
	siglen = sizeof(sig);
	dgstlen = 32;

	if (!EVP_PKEY_sign(pkctx, sig, &siglen, dgst, dgstlen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		size_t i;
		printf("signature (%zu bytes) = ", siglen);
		for (i = 0; i < siglen; i++) {
			printf("%02X", sig[i]);
		}
		printf("\n");
	}

	if (!EVP_PKEY_verify_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (EVP_PKEY_verify(pkctx, sig, siglen, dgst, dgstlen) != SM2_VERIFY_SUCCESS) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		printf("signature verification success!\n");
	}

	/* EVP_PKEY_encrypt() */

	if (!EVP_PKEY_encrypt_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	cbuflen = sizeof(cbuf);
	if (!EVP_PKEY_encrypt(pkctx, cbuf, &cbuflen, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		size_t i;
		printf("ciphertext (%zu bytes) = ", cbuflen);
		for (i = 0; i < cbuflen; i++) {
			printf("%02X", cbuf[i]);
		}
		printf("\n");
	}

	if (!EVP_PKEY_decrypt_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	bzero(mbuf, sizeof(mbuf));
	mbuflen = sizeof(mbuf);
	if (!EVP_PKEY_decrypt(pkctx, mbuf, &mbuflen, cbuf, cbuflen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		printf("original  message = %s\n", msg);
		printf("decrypted message = %s\n", mbuf);
	}


	/* EVP_PKEY_encrypt_old */


	if ((len = EVP_PKEY_encrypt_old(cbuf, msg, (int)msglen, pkey)) <= 0) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		int i;
		printf("ciphertext (%d bytes) = ", len);
		for (i = 0; i < len; i++) {
			printf("%02X", cbuf[i]);
		}
		printf("\n");
	}

	bzero(mbuf, sizeof(mbuf));
	if ((len = EVP_PKEY_decrypt_old(mbuf, cbuf, len, pkey)) <= 0) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		printf("original  message = %s\n", msg);
		printf("decrypted message = %s\n", mbuf);
	}

	if (!(mdctx = EVP_MD_CTX_create())) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	
	/* EVP_SignInit_ex/Update/Final_ex */

	if (!EVP_SignInit_ex(mdctx, EVP_sm3(), engine)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_SignUpdate(mdctx, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_SignFinal(mdctx, sig, &ulen, pkey)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}
	siglen = ulen;

	if (verbose) {
		size_t i;
		printf("signature (%zu bytes) = ", siglen);
		for (i = 0; i < siglen; i++) {
			printf("%02X", sig[i]);
		}
		printf("\n");
	}

	if (!EVP_VerifyInit_ex(mdctx, EVP_sm3(), engine)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_VerifyUpdate(mdctx, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (EVP_VerifyFinal(mdctx, sig, ulen, pkey) != SM2_VERIFY_SUCCESS) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}


	/* EVP_DigestSignInit/Update/Final() */
	// FIXME: return values might be different, not just 1 or 0
	if (!EVP_DigestSignInit(mdctx, &pkctx, md, engine, pkey)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_DigestSignUpdate(mdctx, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	siglen = sizeof(sig);
	if (!EVP_DigestSignFinal(mdctx, sig, &siglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	pkctx = NULL;	
	if (!EVP_DigestVerifyInit(mdctx, &pkctx, md, engine, pkey)) {
		ERR_print_errors_fp(stderr);
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_DigestVerifyUpdate(mdctx, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_DigestVerifyFinal(mdctx, sig, siglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}


	/* EVP_SealInit/Update/Final() EVP_OpenInit/Update/Final() */
	/*
	EVP_PKEY *pk[NUM_PKEYS] = {0};
	unsigned char iv[16];
	unsigned char ek[NUM_PKEYS][256];
	int eklen[NUM_PKEYS];

	RAND_pseudo_bytes(iv, sizeof(iv));

	int i;
	for (i = 0; i < NUM_PKEYS; i++) {
	}

	if (!(cpctx = EVP_CIPHER_CTX_new())) {
		goto end;
	}

	if (!EVP_SealInit(cpctx, cipher, ek, &ekl, iv, pubk, npubk)) {
		goto end;
	}

	if (!EVP_SealUpdate(cpctx, msg, msglen)) {
		goto end;
	}

	if (!EVP_SealFinal(cpctx, cbuf, (int *)&cbuflen)) {
		goto end;
	}
	*/

	printf("test success!\n");
	ret = 1;
end:
	ERR_print_errors_fp(stderr);
	return ret;
}
Exemple #29
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);
}
static char *ngx_http_acme_sign_json(ngx_conf_t *cf, void *conf, json_t *payload, RSA *key, ngx_str_t replay_nonce, json_t **flattened_jws)
{
    /*
     * Structure according to RFC7515:
     *
     * {
     *  "payload":"<payload contents>",
     *  "protected":"<integrity-protected header contents>",
     *  "header":<non-integrity-protected header contents>,
     *  "signature":"<signature contents>"
     * }
     *
     * Example:
     *
     * {
     *  "payload":
     *   "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",
     *  "protected":"eyJhbGciOiJFUzI1NiJ9",
     *  "header": {"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},
     *  "signature":
     *   "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q"
     * }
     */

    /*
     * ACME restrictions:
     * The JWS MUST use the Flattened JSON Serialization
     * The JWS MUST be encoded using UTF-8
     * The JWS Header or Protected Header MUST include “alg” and “jwk” fields
     * The JWS MUST NOT have the value “none” in its “alg” field
     */

    json_t *jwk;
    json_t *header;
    ngx_str_t encoded_protected_header, serialized_payload, encoded_payload, tmp;
    ngx_str_t signing_input, signature, encoded_signature;
    u_char *tmp_char_p;

    /* Variables for signing */
    EVP_PKEY *evp_key;
    EVP_MD_CTX *mdctx = NULL;
    int ret = 0;

    /*
     * Encode payload
     */

    serialized_payload = (ngx_str_t)ngx_string_dynamic(json_dumps(payload, 0));
    encoded_payload.len = ngx_base64_encoded_length(serialized_payload.len);
    encoded_payload.data = ngx_alloc(encoded_payload.len, cf->log);
    ngx_encode_base64url(&encoded_payload, &serialized_payload);

    println_debug("Signing payload: ", &serialized_payload);

    /*
     * Create header
     */

    /* jwk header */
    if(ngx_http_acme_create_jwk(cf, conf, key, &jwk) != NGX_CONF_OK) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Failed to create the JWK from the account key");
        ngx_free(serialized_payload.data);
        ngx_free(encoded_payload.data);
        return NGX_CONF_ERROR;
    }

    /* Pack header into JSON */
    header = json_pack("{s:s, s:s%, s:o}", "alg", "RS256", "nonce", replay_nonce.data, replay_nonce.len, "jwk", jwk);
    if(header == NULL) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error packing JWS header");
        ngx_free(serialized_payload.data);
        ngx_free(encoded_payload.data);
        return NGX_CONF_ERROR;
    }

    /* Serialize and base64url encode header */
    tmp = (ngx_str_t)ngx_string_dynamic(json_dumps(header, 0));
    encoded_protected_header.len = ngx_base64_encoded_length(tmp.len);
    encoded_protected_header.data = ngx_alloc(encoded_protected_header.len, cf->log);
    ngx_encode_base64url(&encoded_protected_header, &tmp);
    ngx_free(tmp.data);
    json_decref(header);

    /*
     * Create signature
     */

    /* Create signing input */
    /* = ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload)) */
    signing_input.len = encoded_protected_header.len + strlen(".") + encoded_payload.len;
    signing_input.data = ngx_alloc(signing_input.len, cf->log);
    tmp_char_p = ngx_copy(signing_input.data, encoded_protected_header.data, encoded_protected_header.len);
    tmp_char_p = ngx_copy(tmp_char_p, ".", strlen("."));
    tmp_char_p = ngx_copy(tmp_char_p, encoded_payload.data, encoded_payload.len);

    /* Convert the RSA key to the EVP_PKEY structure */
    evp_key = EVP_PKEY_new();
    if(evp_key == NULL) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "Error signing the message digest for the JWS signature.");
        return NGX_CONF_ERROR;
    }

    if(EVP_PKEY_set1_RSA(evp_key, key) == 0) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "Error signing the message digest for the JWS signature.");
        return NGX_CONF_ERROR;
    }

    /* Create the message digest context */
    ret = 0;
    mdctx = EVP_MD_CTX_create();
    if(mdctx == NULL)
        goto err;

    /* Initialize the DigestSign operation - SHA-256 has been selected as the message digest function */
    if(EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, evp_key) != 1)
        goto err;

    /* Call update with the message */
    if(EVP_DigestSignUpdate(mdctx, signing_input.data, signing_input.len) != 1)
        goto err;

    /* Finalise the DigestSign operation */
    /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the */
    /* signature. The length is returned in siglen. */
    if(EVP_DigestSignFinal(mdctx, NULL, &signature.len) != 1)
        goto err;

    /* Allocate memory for the signature */
    signature.data = ngx_alloc(signature.len, cf->log);

    /* Obtain the signature */
    if(EVP_DigestSignFinal(mdctx, signature.data, &signature.len) != 1)
        goto err;

    /* Success */
    ret = 1;

    err:
    if(ret != 1) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "Error signing the message digest for the JWS signature. OpenSSL error 0x%xl", ERR_get_error());
        return NGX_CONF_ERROR;
    }

    /* Clean up */
    EVP_MD_CTX_destroy(mdctx);
    EVP_PKEY_free(evp_key);

    /* base64url encode the signature */
    encoded_signature.len = ngx_base64_encoded_length(signature.len);
    encoded_signature.data = ngx_alloc(encoded_signature.len, cf->log);
    ngx_encode_base64url(&encoded_signature, &signature);
    ngx_free(signature.data);

    /*
     * Create flattened JWS serialization
     */

    *flattened_jws = json_pack("{s:s%,s:s%,s:s%}",
            "payload", encoded_payload.data, encoded_payload.len,
            "protected", encoded_protected_header.data, encoded_protected_header.len,
            "signature", encoded_signature.data, encoded_signature.len
            );

    ngx_free(serialized_payload.data);
    // TODO (KK) Maybe this is too early for a free since the strings will be used in the flattened JWS (but when to free then?)
    ngx_free(encoded_payload.data);
    ngx_free(encoded_protected_header.data);
    ngx_free(encoded_signature.data);

    if(*flattened_jws == NULL) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error serializing flattened JWS");
        return NGX_CONF_ERROR;
    }


    return NGX_CONF_OK;
} /* ngx_http_acme_sign_json */