zxid

 view release on metacpan or  search on metacpan

smime-enc.c  view on Meta::CPAN


message to be signed
--sig42
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
Content-Description: S/MIME Clear Signed Message

MIAGCSqGSIb3DQEHA6CAMIIIZQIBADGCATcwggEzAgEAMIGbMIGVMQswCQYDVQQG
EwJQVDEPMA0GA1UEBxMGTGlzYm9hMRcwFQYDVQQKEw5OZXVyb25pbywgTGRhLjEZ
G0DXAj0zd/4AAAAA==
--sig42--
*/

/* Called by:  smime_clear_sign */
char*  /* returns smime encoded clear signed blob, or NULL if error */
clear_sign(X509* x509, EVP_PKEY* pkey, const char* mime_entity)
{
  char* b;
  char* b64;
  BIO*  wbio = 0;
  int   n;
  
  LOG_PRINT("clear sig, canon entity...");
  if (!(mime_entity = mime_canon(mime_entity))) goto err;
  LOG_PRINT("clear sig, entity canoned. Now sig engine");
  
  /* Run crypto stuff over the mime_entity */
  
  if (!(wbio = smime_sign_engine(x509, pkey, mime_entity, 1))) goto err;
  LOG_PRINT("clear sig: signed, now get data");
  n = BIO_get_mem_data(wbio,&b64);
  LOG_PRINT("clear sig: cut pem markers...");
  if (!(b64 = cut_pem_markers_off(b64, n, "PKCS7"))) goto err;
  
  /* Wrap up the result in multipart/signed object */
  
  if (!(b = smime_mk_multipart_signed(mime_entity, b64))) goto err;
  
  LOG_PRINT("clear sig: done. free bio");
  BIO_free_all(wbio);  /* this will also free b64 because b64 hangs from bio */
  return b;

err:
  if (wbio) BIO_free_all(wbio);
  return NULL;
}

/* Called by:  main x2 */
char*
smime_clear_sign(const char* privkey,
		 const char* password,
		 const char* mime_entity)
{
  char* b = NULL;
  X509* x509 = NULL;
  EVP_PKEY* pkey = NULL;

  /* Get key and certificate (why do we need both?) */
  
  if (!(pkey = open_private_key(privkey, password))) goto err;
  if (!(x509 = extract_certificate(privkey))) goto err;
  if (!(b = clear_sign(x509, pkey, mime_entity))) goto err;

err:
  if (pkey)  EVP_PKEY_free(pkey);
  if (x509)  X509_free(x509);
  return b;
}

/* Sign a mime entity, such as produced by mime_mk_multipart(). Signature
 * and entity are output as one base64 blob so the entity is not trivially
 * visible. */

/*
MIME-Version: 1.0
Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7m"
Content-Description: S/MIME Signed Message

MIAGCSqGSIb3DQEHA6CAMIIIZQIBADGCATcwggEzAgEAMIGbMIGVMQswCQYDVQQG
EwJQVDEPMA0GA1UEBxMGTGlzYm9hMRcwFQYDVQQKEw5OZXVyb25pbywgTGRhLjEZ
G0DXAj0zd/4AAAAA==
 */

/* Called by:  smime_sign */
char*  /* returns smime blob, NULL if error */
sign(X509* x509, EVP_PKEY* pkey, const char* mime_entity)
{
  char* b;
  char* b64;
  BIO*  wbio;
  int   n;

  mime_entity = mime_canon(mime_entity);
  
  /* Run crypto stuff over the mime_entity */
  
  if (!(wbio = smime_sign_engine(x509, pkey, mime_entity, 0))) goto err;
  n = BIO_get_mem_data(wbio,&b64);
  if (!(b64 = cut_pem_markers_off(b64, n, "PKCS7"))) goto err;

  /* Add headers */

  if (!(b = strdup("Content-type: application/x-pkcs7-mime; name=\"smime.p7m\"" CRLF
		   "Content-transfer-encoding: base64" CRLF
		   "Content-Disposition: attachment; filename=\"smime.p7m\"" CRLF
		   CRLF))) GOTO_ERR("no memory?");
  if (!(b = concat(b, b64))) GOTO_ERR("no memory?");
  
  BIO_free_all(wbio);  /* also frees b64 */
  return b;
  
err:
  if (wbio) BIO_free_all(wbio);
  return NULL;
}

/* Called by:  main */
char*
smime_sign(const char* privkey, const char* password, const char* mime_entity)
{
  char* b = NULL;
  X509* x509 = NULL;
  EVP_PKEY* pkey = NULL;

  /* Get key and certificate (why do we need both?) */
  
  if (!(pkey = open_private_key(privkey, password))) goto err;
  if (!(x509 = extract_certificate(privkey))) goto err;
  if (!(b = sign(x509, pkey, mime_entity))) goto err;

err:
  if (pkey)  EVP_PKEY_free(pkey);
  if (x509)  X509_free(x509);
  return b;
}

/* Encrypt a mime entity such as produced by smime_clear_sign(). */

/*
MIME-Version: 1.0
Content-Type: application/x-pkcs7-mime; name="smime.p7m"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7m"
Content-Description: S/MIME Encrypted Message

MIAGCSqGSIb3DQEHA6CAMIIIZQIBADGCATcwggEzAgEAMIGbMIGVMQswCQYDVQQG
EwJQVDEPMA0GA1UEBxMGTGlzYm9hMRcwFQYDVQQKEw5OZXVyb25pbywgTGRhLjEZ
G0DXAj0zd/4AAAAA==
 */

/* Called by:  smime_encrypt */
char*
encrypt1(X509* x509, const char* mime_entity)
{
  time_t t;
  char* b;
  char* b64;
  int   i, n;
  char  buf[4096];
  BIO*  p7bio = NULL;
  BIO*  rbio = NULL;
  BIO*  wbio = NULL;
  PKCS7* p7 = NULL;;
  
  t = time(NULL);
  RAND_seed(&t,sizeof(t));
#ifdef WINDOWS
  RAND_screen(); /* Loading video display memory into random state */
#endif

  LOG_PRINT3("encrypt1", x509, mime_entity);

  /* Set up BIOs and PKCS7 machinery */
  
  if (!(rbio = set_read_BIO_from_buf(mime_entity, -1))) goto err;
  
  if (!(p7=PKCS7_new())) GOTO_ERR("no memory?");
  PKCS7_set_type(p7,NID_pkcs7_enveloped);

#if 1
  if (!PKCS7_set_cipher(p7,EVP_des_ede3_cbc()))
    GOTO_ERR("PKCS7_set_cipher des-ede3-cbc");
#else
  /* SECURITY CAVEAT: weak cipher by default */
  if (!PKCS7_set_cipher(p7,EVP_rc2_40_cbc()))
    GOTO_ERR("PKCS7_set_cipher rc2-40-cbc");
#endif



( run in 2.789 seconds using v1.01-cache-2.11-cpan-5c0b1e786e0 )