(This is on 1.0.2 beta 1 as found on openssl.org/source)

I'm getting a double free error when building a CMS EnvelopedData with RSA 
OAEP. Here's how I'm setting things up (error checking left out for brevity):

  int flags = CMS_BINARY | CMS_USE_KEYID | CMS_PARTIAL | CMS_KEY_PARAM;

  CMS_ContentInfo* edata = CMS_encrypt(NULL, NULL, cipher, flags);

  CMS_RecipientInfo* r_info = CMS_add1_recipient_cert(edata, r_cert, flags);

  EVP_PKEY_CTX* wrap_ctx = CMS_RecipientInfo_get0_pkey_ctx(r_info);
  EVP_PKEY_CTX_set_rsa_padding(wrap_ctx, RSA_PKCS1_OAEP_PADDING);
  EVP_PKEY_CTX_set_rsa_oaep_md(wrap_ctx, EVP_sha256());
  EVP_PKEY_CTX_set_rsa_mgf1_md(wrap_ctx, EVP_sha256());
  EVP_PKEY_CTX_set0_rsa_oaep_label(wrap_ctx, my_label, my_label_l);

  CMS_final(edata, in, NULL, flags);


Valgrind says:

==13434== Invalid free() / delete / delete[]
==13434==    at 0x4024B3A: free (vg_replace_malloc.c:366)
==13434==    by 0x8087BE4: CRYPTO_free (mem.c:397)
==13434==    by 0x80B27AC: pkey_rsa_cleanup (rsa_pmeth.c:175)
==13434==    by 0x80615E7: EVP_PKEY_CTX_free (pmeth_lib.c:374)
==13434==    by 0x8082DED: cms_RecipientInfo_ktri_encrypt (cms_env.c:433)
==13434==    by 0x8083930: CMS_RecipientInfo_encrypt (cms_env.c:896)
==13434==    by 0x8083BC5: cms_EnvelopedData_init_bio (cms_env.c:1013)
==13434==    by 0x807D885: CMS_dataInit (cms_lib.c:141)
==13434==    by 0x8080358: CMS_final (cms_smime.c:807)
==13434==    by 0x804A5C4: <snip>
==13434==  Address 0xbeb16466 is on thread 1's stack


Might be a case of PEBKAC, I mostly guessed how this was supposed to work based 
on [1], so I might be doing retarded things.

[1] 
https://github.com/openssl/openssl/commit/f2edf3181e30413c99864e7106125be7da905678




Some more code if anyone wants to try:

#define OSSL_FAIL { ERR_print_errors_fp(stderr); goto end; }

  OpenSSL_add_all_algorithms();
  ERR_load_crypto_strings();

  BIO* in = NULL;
  BIO* tmp_out = NULL;
  CMS_ContentInfo* edata = NULL;
  const EVP_CIPHER* cipher = EVP_aes_256_cbc();

  /* Retrieve recipient certificate */
  FILE* r_cert_file = fopen(recip_cert_path, "rb");
  if (!r_cert_file) {
    printf("Could not open certificate at %s.\n", recip_cert_path);
    goto end;
  }
  if (!PEM_read_X509(r_cert_file, &r_cert, NULL, NULL)) OSSL_FAIL;
  fclose(r_cert_file);

  in = BIO_new_file(in_path, "rb");
  if (!in) OSSL_FAIL;

  int flags = CMS_BINARY | CMS_USE_KEYID | CMS_PARTIAL | CMS_KEY_PARAM;

  edata = CMS_encrypt(NULL, NULL, cipher, flags);
  if (!edata) OSSL_FAIL;

  CMS_RecipientInfo* r_info = CMS_add1_recipient_cert(edata, r_cert, flags);
  if (!r_info) OSSL_FAIL;

  unsigned char oaep_label[] = "BLORG";
  size_t oaep_label_l = sizeof(oaep_label);
  EVP_PKEY_CTX* wrap_ctx = CMS_RecipientInfo_get0_pkey_ctx(r_info);
  if (!wrap_ctx) {
    printf("oh noes! no wrap ctx :(\n");
    goto end;
  }
  if (EVP_PKEY_CTX_set_rsa_padding(wrap_ctx, RSA_PKCS1_OAEP_PADDING)<1)
    OSSL_FAIL;
  if (EVP_PKEY_CTX_set_rsa_oaep_md(wrap_ctx, EVP_sha256())<1)
    OSSL_FAIL;
  if (EVP_PKEY_CTX_set_rsa_mgf1_md(wrap_ctx, EVP_sha256())<1)
    OSSL_FAIL;
  if (EVP_PKEY_CTX_set0_rsa_oaep_label(wrap_ctx, oaep_label, oaep_label_l)<1)
    OSSL_FAIL;

  if (! CMS_final(edata, in, NULL, flags) ) OSSL_FAIL;

  /* Out */
  char* env_out = malloc(strlen(in_path) + sizeof(".ENV.CMS"));
  strncpy(env_out, in_path, strlen(out_path)+1);
  strcat(env_out, ".ENV.CMS");
  BIO* tmp_out = BIO_new_file(env_out, "wb");
  if (!tmp_out) OSSL_FAIL;
  if (!i2d_CMS_bio(tmp_out, edata)) OSSL_FAIL;
  if (BIO_flush(tmp_out)<1) OSSL_FAIL;
  free(env_out);

end:
  if (edata) CMS_ContentInfo_free(edata);
  if (r_cert) X509_free(r_cert);
  if (in) BIO_free(in);
  if (tmp_out) BIO_free(tmp_out);

  ERR_free_strings();
  EVP_cleanup();


PS: Many thanks to Tom and Steve for their previous help on nested CMS 
structures :) ended up parsing the ASN.1 string myself, which was 1) not 
difficult 2) very instructive.
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to