zxid

 view release on metacpan or  search on metacpan

smime-vfy.c  view on Meta::CPAN

  if (data_out) *data_out = NULL;
  if (!x509 || !pkey || !enc_entity || !data_out) GOTO_ERR("NULL arg(s)");
  LOG_PRINT("decrypt: get_pkcs7_from_pem");
  if (!(p7 = get_pkcs7_from_pem(enc_entity))) goto err;
  
  /* Decrypt the symmetric key with private key and obtain symmetric
   * cipher stream (BIO). The cert is needed here to look up one of
   * possibly multiple recipient infos present in PKCS7 object. Issuer
   * and serial number must match (these two fields form unique ID for
   * cert). Actual public key part of the X509 cert is not used for
   * anything here.  */

  LOG_PRINT("decrypt: dataDecode");
  if (!(p7bio=PKCS7_dataDecode(p7,pkey,NULL/*detached*/,x509)))
    GOTO_ERR("12 no recipient matches cert or private key could not decrypt, i.e. wrong key (PKCS7_dataDecode)");
  LOG_PRINT("decrypt: ready to pump");

  /* Pump data from p7bio to decrypt symmetric cipher */
  
  if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");

  for (;;) {
    if ((i=BIO_read(p7bio,buf,sizeof(buf))) <= 0) break;
    BIO_write(wbio,buf,i);
  }  
  BIO_flush(wbio);
  BIO_free_all(p7bio);
  p7bio = NULL;
  PKCS7_free(p7);
  p7 = NULL;

  LOG_PRINT("decrypt: pump done");

  /* Return data (this should now be easier because we just freed
   * some memory) */

  n = get_written_BIO_data(wbio, data_out);
  BIO_free_all(wbio);
  return n;  
  
err:  
  if (p7)    PKCS7_free(p7);
  if (wbio)  BIO_free_all(wbio);
  if (p7bio) BIO_free_all(p7bio);
  return -1;
}

/* Called by:  main */
int  /* return size of data, -1 on failure */
smime_decrypt(const char* privkey,
	      const char* passwd,
	      const char* enc_entity,
	      char** data_out)
{
  int  n = -1;
  EVP_PKEY *pkey = NULL;
  X509  *x509 = NULL;
  
  if (data_out) *data_out = NULL;
  if (!privkey || !passwd || !enc_entity || !data_out) GOTO_ERR("NULL arg(s)");
  if (!(pkey = open_private_key(privkey, passwd))) goto err;
  if (!(x509 = extract_certificate(privkey)))      goto err;
  n = decrypt(x509, pkey, enc_entity, data_out);
    
err:  
  if (pkey)  EVP_PKEY_free(pkey);
  if (x509)  X509_free(x509);
  return n;
}

/* ------------------------------------------------ */

#if 0
/* copied from verify.c */
/* should be X509* but we can just have them as char*. (??? --Sampo) */
/* Called by: */
static int
verify_callback(int ok, X509_STORE_CTX *ctx) {
  char buf[256];
  X509 *err_cert;
  int err,depth;

  err_cert=X509_STORE_CTX_get_current_cert(ctx);
  err=	 X509_STORE_CTX_get_error(ctx);
  depth= X509_STORE_CTX_get_error_depth(ctx);

  X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf));
  fprintf(stderr,"depth=%d %s\n",depth,buf);
  if (!ok) {
    fprintf(stderr,"verify error:num=%d:%s\n",err,
	    X509_verify_cert_error_string(err));
    if (depth < 6) {
      ok=1;
      X509_STORE_CTX_set_error(ctx,X509_V_OK);
    } else {
      ok=0;
      X509_STORE_CTX_set_error(ctx,X509_V_ERR_CERT_CHAIN_TOO_LONG);
    }
  }
  switch (ctx->error) {
  case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
    X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,sizeof(buf));
    fprintf(stderr,"issuer= %s\n",buf);
    break;
#if 1
  case X509_V_ERR_CERT_NOT_YET_VALID:
  case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
    fprintf(stderr,"notBefore=");
    /*ASN1_UTCTIME_print(bio_err,X509_get_notBefore(ctx->current_cert));
      BIO_printf(bio_err,"\n");*/
    break;
  case X509_V_ERR_CERT_HAS_EXPIRED:
  case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
    fprintf(stderr,"notAfter=");
    /*ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ctx->current_cert));
      BIO_printf(bio_err,"\n"); */
    break;
#endif
  }
  fprintf(stderr,"verify return:%d\n",ok);
  return(ok);



( run in 1.171 second using v1.01-cache-2.11-cpan-364913b4093 )