Esempio n. 1
0
long  /* return serial on success, -1 on failure */
smime_get_signer_info(const char* signed_entity,
		      int info_ix,     /* 0 = first signer */
		      char** issuer)   /* DN of the issuer */
{
  int serial = -1;
  PKCS7* p7 = NULL;
  STACK_OF(PKCS7_SIGNER_INFO)* sigs = NULL;
  PKCS7_SIGNER_INFO* si;
  
  if (!signed_entity || !issuer) GOTO_ERR("NULL arg(s)");
  *issuer = NULL;
  
  if (!(p7 = get_pkcs7_from_pem(signed_entity))) goto err;
  if (!(sigs=PKCS7_get_signer_info(p7)))
    GOTO_ERR("13 no sigs? (PKCS7_get_signer_info)");

  if (info_ix >= sk_PKCS7_SIGNER_INFO_num(sigs))
    GOTO_ERR("No more signers. info_ix too large.");

  if (!(si=sk_PKCS7_SIGNER_INFO_value(sigs,info_ix)))
    GOTO_ERR("NULL signer info");
  
  *issuer = X509_NAME_oneline(si->issuer_and_serial->issuer, NULL,0);
  serial = ASN1_INTEGER_get(si->issuer_and_serial->serial);
  
err:
  if (p7) PKCS7_free(p7);
  return serial;
}
Esempio n. 2
0
char *
otp_gen(int len, otp_type_t type) 
{
	long int number = 0; 
	int i, fd = 0;
	char *otp = NULL;
	char *otp_type = NULL;

	otp_type = select_otp_type(type);

	if ((otp = (char *)malloc((len+1) * sizeof (char))) == NULL)
		return NULL;

	if ((fd = open("/dev/urandom", O_RDONLY)) < 0)
		GOTO_ERR(pam_data.pamh, "E: can't open /dev/urandom.");
		
	for (i=0; i<len; i++) {
		if (read(fd, &number, sizeof number) < 0)
			GOTO_ERR(pam_data.pamh, "E: can't read /dev/urandom.");
		otp[i] = otp_type[number % strlen(otp_type)];
	}
	otp[len] = '\0';
	close(fd);
	return otp;

err:
	if (otp != NULL) free(otp);
	if (fd > 0) close(fd);
	return NULL;
}
Esempio n. 3
0
int  /* return size of data, -1 on failure */
decrypt(X509* x509, EVP_PKEY* pkey, const char* enc_entity, char** data_out)
{
  char* p;
  char buf[4096];
  int  i,n;
  BIO* wbio = NULL;
  BIO* p7bio = NULL;
  PKCS7 *p7 = NULL;

  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;
}
Esempio n. 4
0
int  /* returns -1 if error, 0 if verfy fail, and 1 if verify OK */
verify_cert(X509* ca_cert, X509* cert)
{
  EVP_PKEY* pkey = NULL;
  if (!ca_cert || !cert) GOTO_ERR("NULL arg(s)");
  if (!(pkey=X509_get_pubkey(ca_cert))) GOTO_ERR("no memory?");
  return X509_verify(cert, pkey);
err:
  return -1;
}
Esempio n. 5
0
static PKCS7*
get_pkcs7_from_pem(const char* enc_entity)
{
  const char* p;
  char*  wrapped_enc_entity = NULL;
  BIO*   rbio = NULL;
  PKCS7* p7 = NULL;
 
  /* Check if encrypted entity is composed of raw data or if it has some
   * headers. In the latter case, just skip the headers. Headers are
   * separated from data by an empty line (hence sequence CRLF CRLF).*/
  
  if (p = strstr(enc_entity, CRLF CRLF)) {
    enc_entity = p+4;
  } else if (p = strstr(enc_entity, LF LF)) {
    enc_entity = p+2;
  } else if (p = strstr(enc_entity, CR CR)) {
    enc_entity = p+2;
  }
  
  /* Make sure the pem markers are there */
  
  LOG_PRINT("get_pkcs7_from_pem: wrapping in pem markers");

  if (!(wrapped_enc_entity = wrap_in_pem_markers(enc_entity, "PKCS7")))
    GOTO_ERR("no memory?");
  LOG_PRINT("get_pkcs7_from_pem: wrapped.");
  
  /* Set up BIO so encrypted/signed data can be read from pem file */
  
  if (!(rbio = set_read_BIO_from_buf(wrapped_enc_entity, -1))) goto err;
  
  LOG_PRINT("get_pkcs7_from_pem: ready to read PKCS7 bio...");

  /* Load the PKCS7 object from a pem file to internal representation.
   * this reads all of the data file. */
  
  if (!(p7=PEM_read_bio_PKCS7(rbio,NULL/*&x*/,NULL/*callback*/,NULL/*arg*/)))
    GOTO_ERR("11 corrupt PEM PKCS7 file? (PEM_read_bio_PKCS7)");

  LOG_PRINT("get_pkcs7_from_pem: bio read");

  BIO_free_all(rbio);
  Free(wrapped_enc_entity);
  return p7;
err:
  if (rbio) BIO_free_all(rbio);
  if (wrapped_enc_entity) Free(wrapped_enc_entity);
  return NULL;
}
Esempio n. 6
0
/* Called by:  mk_multipart */
char*
mime_mk_multipart(const char* text,
	  const char* file1, int len1, const char* type1, const char* name1,
	  const char* file2, int len2, const char* type2, const char* name2,
	  const char* file3, int len3, const char* type3, const char* name3)
{
  char* b;
  
  /* Concatenate all components into one message. This type of stuff
   * is sooo ugly in C. I'm missing perl. */
  
  if (!(b = strdup("Content-type: multipart/mixed; boundary=" SEP CRLF
		   CRLF
		   "--" SEP CRLF
		   "Content-type: text/plain" CRLF
		   "Content-transfer-encoding: 8bit" CRLF
		   CRLF))) GOTO_ERR("no memory?");
  if (!(b = concat(b, text))) goto err;
  if (!(b = concat(b, CRLF "--" SEP))) goto err;

  if (!(b = attach(b, file1, len1, type1, name1))) goto err;
  if (!(b = attach(b, file2, len2, type2, name2))) goto err;
  if (!(b = attach(b, file3, len3, type3, name3))) goto err;
  
  if (!(b = concat(b, "--" CRLF))) goto err;
  return b;
err:
  return NULL;
}
Esempio n. 7
0
/* Called by:  clear_sign, extract_certificate, extract_request, main, open_private_key, sign */
char*
mime_canon(const char* s)
{
  char* d;
  char* p;
  int len;
  len = strlen(s);
  p = d = (char*)OPENSSL_malloc(len + len);  /* Reserve spaces for CR's to be inserted. */
  if (!d) GOTO_ERR("no memory?");
  
  /* Scan and copy */

  for (; *s; s++) {
    if (s[0] != '\015' && s[0] != '\012')
      *(p++) = *s; /* pass thru */
    else {
      if (s[0] == '\015' && s[1] == '\012') s++;  /* already CRLF */
      *(p++) = '\015'; *(p++) = '\012';
    }
  }
  *(p++) = '\0';

  /* Shrink the buffer back to actual size (not very likely to fail) */

  return (char*)OPENSSL_realloc(d, (p-d));
err:
  return NULL;
}
Esempio n. 8
0
/* For this case, I will malloc the return strings */
static int
get_signed_seq2string(PKCS7_SIGNER_INFO *si, char **str1, char **str2) {
  ASN1_TYPE *so;
#if 0
  if (signed_seq2string_nid == -1)
    signed_seq2string_nid=
      OBJ_create("1.9.9999","OID_example","Our example OID");
  /* To retrieve */
  so=PKCS7_get_signed_attribute(si,signed_seq2string_nid);
  if (so && (so->type == V_ASN1_SEQUENCE))
    {
      ASN1_CTX c;
      ASN1_STRING *s;
      long length;
      ASN1_OCTET_STRING *os1,*os2;
      
      s=so->value.sequence;
      c.p=ASN1_STRING_data(s);
      c.max=c.p+ASN1_STRING_length(s);
      if (!asn1_GetSequence(&c,&length)) GOTO_ERR("") err;
      /* Length is the length of the seqence */
      
      c.q=c.p;
      if ((os1=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 
	GOTO_ERR("");
      c.slen-=(c.p-c.q);
      
      c.q=c.p;
      if ((os2=d2i_ASN1_OCTET_STRING(NULL,&c.p,c.slen)) == NULL) 
	GOTO_ERR("");
      c.slen-=(c.p-c.q);
      
      if (!asn1_Finish(&c)) GOTO_ERR("") err;
      *str1=Malloc(os1->length+1);
      *str2=Malloc(os2->length+1);
      memcpy(*str1,os1->data,os1->length);
      memcpy(*str2,os2->data,os2->length);
      (*str1)[os1->length]='\0';
      (*str2)[os2->length]='\0';
      ASN1_OCTET_STRING_free(os1);
      ASN1_OCTET_STRING_free(os2);
      return(1);
    }
#endif
 err:
  return(0);
}
Esempio n. 9
0
/* Called by:  main x3 */
char*
mime_base64_entity(const char* data, int len, const char* type)
{
  /*int n;*/
  char* b64;
  char* b;  
  if (!(b = strdup("Content-type: "))) GOTO_ERR("no memory?");
  if (!(b = concat(b, type))) goto err;
  if (!(b = concat(b, CRLF CRLF))) goto err;
  
  /*n =*/ smime_base64(1, data, len, &b64);
  if (!b64) GOTO_ERR("no memory?");
  if (!(b = concat(b, b64))) goto err;
  return b;
err:
  return NULL;
}
Esempio n. 10
0
/* Called by:  attach x9, encrypt1, get_req_attr x3, mime_base64_entity x3, mime_mk_multipart x3, mime_raw_entity x3, sign, smime_mk_multipart_signed x4 */
char*
concat(char* b, const char* s)
{
  if (!(b = (char*)OPENSSL_realloc(b, strlen(b)+strlen(s)+1))) GOTO_ERR("no memory?");
  strcat(b,s);
  return b;
err:
  return NULL;
}
Esempio n. 11
0
/* Called by:  get_req_attr */
char*
concatmem(char* b, const char* s, int len)
{
  int lb = strlen(b);
  if (!(b = (char*)OPENSSL_realloc(b, lb+len+1))) GOTO_ERR("no memory?");
  memcpy(b+lb, s, len);
  b[lb+len] = '\0';
  return b;
err:
  return NULL;
}
Esempio n. 12
0
/* Called by:  main */
char*
mime_raw_entity(const char* text, const char* type)
{
  char* b;  
  if (!(b = strdup("Content-type: "))) GOTO_ERR("no memory?");
  if (!(b = concat(b, type))) goto err;
  if (!(b = concat(b, CRLF CRLF))) goto err;
  if (!(b = concat(b, text))) goto err;
  return b;
err:
  return NULL;
}
Esempio n. 13
0
int  /* returns -1 if error, 0 if verfy fail, and 1 if verify OK */
smime_verify_cert(const char* ca_cert_pem, const char* cert_pem)
{
  X509* ca_cert = NULL;
  X509* cert = NULL;
  int ret = -1;
  if (!ca_cert_pem || !cert_pem) GOTO_ERR("NULL arg(s)");
  if (!(ca_cert = extract_certificate(ca_cert_pem))) goto err;
  if (!(cert = extract_certificate(cert_pem))) goto err;
  ret = verify_cert(ca_cert, cert);
err:
  if (ca_cert) X509_free(ca_cert);
  if (cert) X509_free(cert);
  return ret;
}
Esempio n. 14
0
/* Called by:  clear_sign */
char*  /* returns smime encoded clear sig blob, or NULL if error */
smime_mk_multipart_signed(const char* mime_entity, const char* sig_entity)
{
  char* b;
  
  if (!(b = strdup("Content-type: multipart/signed; protocol=\"application/x-pkcs7-signature\"; micalg=sha1; boundary=" SIG CRLF
		   CRLF
		   "--" SIG CRLF))) GOTO_ERR("no memory?");
  if (!(b = concat(b, mime_entity))) goto err;
  if (!(b = concat(b, CRLF "--" SIG CRLF
   "Content-Type: application/x-pkcs7-signature; name=\"smime.p7s\"" CRLF
   "Content-Transfer-Encoding: base64" CRLF
   "Content-Disposition: attachment; filename=\"smime.p7s\"" CRLF CRLF)))
    goto err;
  if (!(b = concat(b, sig_entity))) goto err;
  if (!(b = concat(b, CRLF "--" SIG "--" CRLF))) goto err;
  return b;

err:
  return NULL;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
/* Called by:  get_pkcs7_from_pem */
char*
wrap_in_pem_markers(const char* b, char* algo) {
  char* bb;
  int n;
  int algolen = strlen(algo);  
  n = strlen(b);
  if (!(bb = (char*)OPENSSL_malloc(5+6+algolen+6+ n +5+4+algolen+6 +1 +1)))
    GOTO_ERR("no memory?");
  strcpy(bb, "-----BEGIN ");
  strcat(bb, algo);
  strcat(bb, "-----\n");
  strcat(bb, b);
  if (b[n-1] != '\012' && b[n-1] != '\015')  /* supply \n if missing */
    strcat(bb, "\n");
  strcat(bb, "-----END ");
  strcat(bb, algo);
  strcat(bb, "-----\n");
  n = strlen(bb);
  return bb;
err:
  return NULL;
}
Esempio n. 17
0
char* /* returns contents of the signed message, NULL if error */
smime_verify_signature(const char* pubkey,
		       const char* sig_entity,     /* signed entity
						      or just the sigature */
		       const char* detached_data,  /* possibly NULL */
		       int detached_data_len)
{
  X509*  x509 = NULL;
  PKCS7* p7 = NULL;
  STACK_OF(PKCS7_SIGNER_INFO)* sigs = NULL;
  X509_STORE* certs=NULL;
  BIO*   detached = NULL;
  BIO*   p7bio = NULL;
  BIO*   wbio = NULL;
  char*  data = NULL;
  char   buf[4096];
  int    i,x;
  
  if (!sig_entity || !pubkey) GOTO_ERR("NULL arg(s)");
  if (!(p7 = get_pkcs7_from_pem(sig_entity))) goto err;

  /* Hmm, if its clear signed, we already provided the detached sig, but
   * if its one sig blob, may be PKCS7_get_detached() provides BIO connected
   * to the detached part. Go figure.
   */

  if (detached_data && detached_data_len) {
    if (!(detached = set_read_BIO_from_buf(detached_data, detached_data_len)))
      goto err;
  } else {
    if (!PKCS7_get_detached(p7))
      GOTO_ERR("15 cant extract signed data from signed entity (PKCS7_get_detached)");
  }
  if (!(p7bio=PKCS7_dataInit(p7,detached))) GOTO_ERR("PKCS7_dataInit");
  
  if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
  
  /* We now have to 'read' from p7bio to calculate message digest(s).
   * I also take the opportunity to save the signed data. */
  for (;;) {
    i = BIO_read(p7bio,buf,sizeof(buf));
    if (i <= 0) break;
    BIO_write(wbio, buf, i);
  }
  
  if (get_written_BIO_data(wbio, &data)==-1) goto err;
  BIO_free_all(wbio);
  wbio = NULL;
  
  /* We can now verify signatures */
  if (!(sigs=PKCS7_get_signer_info(p7)))
    GOTO_ERR("13 no sigs? (PKCS7_get_signer_info)");
  
  /* Ok, first we need to, for each subject entry, see if we can verify */
  for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sigs); i++) {
    X509_STORE_CTX cert_ctx;
    PKCS7_SIGNER_INFO *si;
    ASN1_UTCTIME *tm;
    char *str1,*str2;
    
    si=sk_PKCS7_SIGNER_INFO_value(sigs,i);
    
    /* The bio is needed here only to lookup the message digest context
     * which presumably now contains the message digest. It will not be
     * read, and hence its good for any number of iterations. This is so
     * because MD bios pass the data right thru so they can be stacked
     * to calculate multiple message digests simultaneously. Clever, eh?
     */

#if 0
    /* *** this is currently broken and thus disabled. --Sampo */
    /* verifies by looking up the certificate from certs database,
     * verifying the validity of the certificate, and finally
     * validity of the signature */

    x=PKCS7_dataVerify(certs, &cert_ctx, p7bio, p7, si);
#else
    /* just verify the signature, given that we already have certificate
     * candidate (see crypto/pk7_doit.c around line 675) */

    if (!(x509 = extract_certificate(pubkey))) goto err;
    x=PKCS7_signatureVerify(p7bio, p7, si, x509);
#endif
    if (x <= 0) GOTO_ERR("14 sig verify failed");
    
#if 0
    if ((tm=get_signed_time(si)) != NULL) {
      //fprintf(stderr,"Signed time:");
      //ASN1_UTCTIME_print(bio_out,tm);
      ASN1_UTCTIME_free(tm);
      //BIO_printf(bio_out,"\n");
    }
#endif
#if 0
    if (get_signed_seq2string(si,&str1,&str2)) {
      fprintf(stderr,"String 1 is %s\n",str1);
      fprintf(stderr,"String 2 is %s\n",str2);
    }
#endif
  }
  
  BIO_free_all(p7bio);
  PKCS7_free(p7);
  X509_STORE_free(certs);
  return data;    /* return the signed plain text */

err:
  if (wbio) BIO_free_all(wbio);
  if (p7bio) BIO_free_all(p7bio);
  if (p7) PKCS7_free(p7);
  if (certs) X509_STORE_free(certs);
  if (data) Free(data);
  return NULL;
}
Esempio n. 18
0
int  /* returns number of parts, -1 on error */
mime_split_multipart(const char* entity,
		     int max_parts,  /* how big following arrays are */
		     char* parts[],  /* NULL --> just count parts */
		     int lengths[])
{
  char separator[256];
  int nparts = -1;
  int sep_len, len;
  char* p;
  char* pp;
  char* ppp;
  char* start = NULL;  /* start of current sub entity */
  
  if (!entity || (parts && !lengths)) GOTO_ERR("NULL arg(s)");

  if (!(p = strstr(entity, "Content-type: multipart/")))
    GOTO_ERR("16 No `Content-type: multipart/...' header found");
  
  if (!(p = strstr(p, "boundary=")))
    GOTO_ERR("16 Badly formed multipart header. Didn't find `boundary='.");

  p+=9; /* strlen("boundary=") */
  sep_len = strcspn(p, "\015\012 ;");
  if (sep_len <= 0) GOTO_ERR("16 No boundary separator?");
  if (sep_len >= (int)sizeof(separator))
    GOTO_ERR("16 Too long boundary separator. Only 255 chars allowed.");
  
  separator[0] = separator[1] = '-';
  memcpy(separator+2, p, sep_len);
  sep_len+=2;
  separator[sep_len] = '\0';
  p+=sep_len;
  
  while ((p = strstr(p, separator))) {

    ppp = pp = p;
    p+=sep_len;
    if (*p != '\015' && *p != '\012' && *p != '-')
      continue;   /* False positive: separator appeared as line prefix */

    if (pp[-1] == '\012') pp--;  /* walk back and eat the CRLF */
    if (pp[-1] == '\015') pp--;
    if (pp == ppp)
      continue;  /* False positive: separator in middle of line */
    
    if (start && parts && nparts < max_parts) {      
      len = lengths[nparts] = pp-start;
      if (!(parts[nparts] = (char*)OPENSSL_malloc(len+1))) GOTO_ERR("no memory?");
      memcpy(parts[nparts], start, len);
      parts[nparts][len] = '\0';  /* Gratuitous nul termination */
    }
    
    nparts++;
    if (*p == '\015') p++;  /* Skip CRLF */
    if (*p == '\012') p++;  /* This is really mandatory */
    
    start = p;
  }
  return nparts;

/* Called by: */
err:
  if (parts) {
    /* free what we have allocated so far */
    for (sep_len = 0; sep_len < nparts; sep_len++)
      if (parts[sep_len])
	OPENSSL_free(parts[sep_len]);
  }
  return -1;
}