int signRequest(char* pemRequest, int days, char* pemCAKey, char* pemCaCert,  int certType, char *url, char* result)  {

  BIO* bioReq = BIO_new_mem_buf(pemRequest, -1);
  BIO* bioCAKey = BIO_new_mem_buf(pemCAKey, -1);

  BIO* bioCert = BIO_new_mem_buf(pemCaCert, -1);
  X509* caCert = PEM_read_bio_X509(bioCert, NULL, NULL, NULL);

  int err = 0;

  X509_REQ *req=NULL;
  if (!(req=PEM_read_bio_X509_REQ(bioReq, NULL, NULL, NULL))) {
    BIO_free(bioReq);
    BIO_free(bioCert);
    BIO_free(bioCAKey);
    return ERR_peek_error();
  }

  EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioCAKey, NULL, NULL, NULL);
  if (!caKey) {
    BIO_free(bioReq);
    BIO_free(bioCert);
    BIO_free(bioCAKey);
    return ERR_peek_error();
  }

  X509* cert = X509_new();
  EVP_PKEY* reqPub;
  if(!(err =  X509_set_version(cert, 2)))
  {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return ERR_peek_error();
  }

  //redo all the certificate details, because OpenSSL wants us to work hard
  X509_set_issuer_name(cert, X509_get_subject_name(caCert));

  ASN1_UTCTIME *s=ASN1_UTCTIME_new();

  // Jira-issue: WP-37
  // This is temp solution for putting pzp validity 5 minutes before current time
  // If there is a small clock difference between machines, it results in cert_not_yet_valid
  // It does set GMT time but is relevant to machine time.
  // A better solution would be to have ntp server contacted to get a proper time.
  if(certType == 2) {
    X509_gmtime_adj(s, long(0-300));
  }
  else {
    X509_gmtime_adj(s, long(0));
  }
  // End of WP-37
  X509_set_notBefore(cert, s);

  X509_gmtime_adj(s, (long)60*60*24*days);
  X509_set_notAfter(cert, s);

  ASN1_UTCTIME_free(s);

  X509_set_subject_name(cert, X509_REQ_get_subject_name(req));
  reqPub = X509_REQ_get_pubkey(req);
  X509_set_pubkey(cert,reqPub);
  EVP_PKEY_free(reqPub);

  //create a serial number at random
  ASN1_INTEGER* serial = getRandomSN();
  X509_set_serialNumber(cert, serial);

  X509_EXTENSION *ex;
  X509V3_CTX ctx;
  X509V3_set_ctx_nodb(&ctx);
  X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);

  char *str = (char*)malloc(strlen("caIssuers;") + strlen(url) + 1);
  if (str == NULL) {
    return -10;
  }
  strcpy(str, "caIssuers;");
  strcat(str, url);

  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_info_access, (char*)str))) {
    free(str);
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }
  free(str);
  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, (char*)url))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }
  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_issuer_alt_name, (char*)"issuer:copy"))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }

  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }

  if( certType == 1) {
    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_basic_constraints, (char*)"critical, CA:FALSE"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_ext_key_usage, (char*)"critical, clientAuth, serverAuth"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }
  } else if( certType == 2) {
    if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:FALSE"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_ext_key_usage, (char*)"critical, clientAuth, serverAuth"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }
  }

  if (!(err = X509_sign(cert,caKey,EVP_sha1())))
  {
    BIO_free(bioReq);
    BIO_free(bioCert);
    BIO_free(bioCAKey);
    return err;
  }

  BIO *mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509(mem,cert);

  BUF_MEM *bptr;
  BIO_get_mem_ptr(mem, &bptr);
  BIO_read(mem, result, bptr->length);

  BIO_free(mem);
  BIO_free(bioReq);
  BIO_free(bioCert);
  BIO_free(bioCAKey);

  return 0;
}
int selfSignRequest(char* pemRequest, int days, char* pemCAKey, int certType, char *url, char* result)  {
  BIO* bioReq = BIO_new_mem_buf(pemRequest, -1);
  BIO* bioCAKey = BIO_new_mem_buf(pemCAKey, -1);

  int err = 0;

  X509_REQ *req=NULL;
  if (!(req=PEM_read_bio_X509_REQ(bioReq, NULL, NULL, NULL))) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return -5;
  }

  EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioCAKey, NULL, NULL, NULL);
  if (!caKey) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return -6;
  }

  X509* cert = X509_new();
  EVP_PKEY* reqPub;

  //redo all the certificate details, because OpenSSL wants us to work hard
  if(!(err =  X509_set_version(cert, 2)))
  {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return err;
  }

  if(!(err = X509_set_issuer_name(cert, X509_REQ_get_subject_name(req))))
  {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return err;
  }

  ASN1_UTCTIME *s=ASN1_UTCTIME_new();
  // Jira-issue: WP-37
  // This is temp solution for putting pzp validity 5 minutes before current time
  // If there is a small clock difference between machines, it results in cert_not_yet_valid
  // It does set GMT time but is relevant to machine time.
  // A better solution would be to have ntp server contacted to get proper time.
  if(certType == 2) {
    X509_gmtime_adj(s, long(0-300));
  }
  else {
    X509_gmtime_adj(s, long(0));
  }
  // End of WP-37
  X509_set_notBefore(cert, s);

  X509_gmtime_adj(s, (long)60*60*24*days);
  X509_set_notAfter(cert, s);

  ASN1_UTCTIME_free(s);

  if(!(err = X509_set_subject_name(cert, X509_REQ_get_subject_name(req)))) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return err;
  }

  if (!(reqPub = X509_REQ_get_pubkey(req))) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return -7;
  }
  err = X509_set_pubkey(cert,reqPub);
  EVP_PKEY_free(reqPub);
  if (!err) {
    return err; // an error occurred, this is terrible style.
  }

  //create a serial number at random
  ASN1_INTEGER* serial = getRandomSN();
  X509_set_serialNumber(cert, serial);

  // V3 extensions
  X509_EXTENSION *ex;
  X509V3_CTX ctx;
  X509V3_set_ctx_nodb(&ctx);
  X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);

  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, (char*)url))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }

  if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) {
    return ERR_peek_error();
  } else {
    X509_add_ext(cert, ex, -1);
  }

  if( certType == 0) {
    if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:TRUE"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_key_usage, (char*)"critical, keyCertSign, digitalSignature, cRLSign"))) { /* critical, keyCertSign,cRLSign, nonRepudiation,*/
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_ext_key_usage, (char*)"critical, serverAuth"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL,  &ctx, NID_inhibit_any_policy, (char*)"0"))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }

    if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_crl_distribution_points, (char*)url))) {
      return ERR_peek_error();
    } else {
      X509_add_ext(cert, ex, -1);
    }
  }

  if (!(err = X509_sign(cert,caKey,EVP_sha1()))) {
    BIO_free(bioReq);
    BIO_free(bioCAKey);
    return err;
  }

  BIO *mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509(mem,cert);

  BUF_MEM *bptr;
  BIO_get_mem_ptr(mem, &bptr);
  BIO_read(mem, result, bptr->length);

  BIO_free(mem);
  BIO_free(bioReq);
  BIO_free(bioCAKey);
  return 0;

}
Example #3
0
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
                               int offset_day, long offset_sec)
{
    char *p;
    struct tm *ts;
    struct tm data;
    size_t len = 20;
    int free_s = 0;

    if (s == NULL) {
        s = ASN1_UTCTIME_new();
        if (s == NULL)
            goto err;
        free_s = 1;
    }

    ts = OPENSSL_gmtime(&t, &data);
    if (ts == NULL)
        goto err;

    if (offset_day || offset_sec) {
        if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
            goto err;
    }

    if ((ts->tm_year < 50) || (ts->tm_year >= 150))
        goto err;

    p = (char *)s->data;
    if ((p == NULL) || ((size_t)s->length < len)) {
        p = OPENSSL_malloc(len);
        if (p == NULL) {
            ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE);
            goto err;
        }
        OPENSSL_free(s->data);
        s->data = (unsigned char *)p;
    }

    BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
                 ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
                 ts->tm_sec);
    s->length = strlen(p);
    s->type = V_ASN1_UTCTIME;
#ifdef CHARSET_EBCDIC_not
    ebcdic2ascii(s->data, s->data, s->length);
#endif
    return (s);
 err:
    if (free_s)
        ASN1_UTCTIME_free(s);
    return NULL;
}
Example #4
0
ASN1_UTCTIME *
ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
{
	ASN1_UTCTIME *tmp = NULL, *ret;

	if (s == NULL) {
		tmp = ASN1_UTCTIME_new();
		if (tmp == NULL)
			return NULL;
		s = tmp;
	}

	ret = ASN1_UTCTIME_adj_internal(s, t, offset_day, offset_sec);
	if (ret == NULL && tmp != NULL)
		ASN1_UTCTIME_free(tmp);

	return ret;
}
Example #5
0
static int
get_times(glite_renewal_core_context ctx, char *proxy_file,
	  time_t *not_after_x509, time_t *not_after_voms)
{
   X509 *cert = NULL;
   STACK_OF(X509) *chain = NULL;
   int ret, i;
   time_t now, end_time, end_time_x509;
   struct vomsdata *voms_data = NULL;
   struct voms **voms_cert = NULL;
   ASN1_UTCTIME *t;
   char *s, *c;

   ret = load_proxy(ctx, proxy_file, &cert, NULL, &chain, NULL); 
   if (ret)
      return ret;

   ret = get_voms_cert(ctx, cert, chain, &voms_data);
   if (ret)
      goto end;

   end_time = 0;
   if (voms_data != NULL) {
      for (voms_cert = voms_data->data; voms_cert && *voms_cert; voms_cert++) {
          t = ASN1_UTCTIME_new();
          if (t == NULL) {
             glite_renewal_core_set_err(ctx, "ASN1_UTCTIME_new() failed");
             ret = 1;
             goto end;
          }

          /* date2 contains a GENERALIZEDTIME format (YYYYMMDDHHSS[.fff]Z)
           * value, which must be converted to the UTC (YYMMDDHHSSZ) format */
          s = strdup((*voms_cert)->date2 + 2);
          if (s == NULL) {
             glite_renewal_core_set_err(ctx, "Not enough memory");
             ret = ENOMEM;
             goto end;
          }
          c = strchr(s, '.');
          if (c) {
             *c++ = 'Z';
             *c = '\0';
          }
          ret = ASN1_UTCTIME_set_string(t, s);
          if (ret == 0) {
             glite_renewal_core_set_err(ctx, "ASN1_UTCTIME_set_string() failed\n");
             ret = 1;
             free(s);
             goto end;
          }

          if (end_time == 0 || ASN1_UTCTIME_cmp_time_t(t, end_time) < 0)
             globus_gsi_cert_utils_make_time(t, &end_time);

          ASN1_UTCTIME_free(t);
          free(s);
      }
   }

   globus_gsi_cert_utils_make_time(X509_get_notAfter(cert), &end_time_x509);
   now = time(NULL);
   if (end_time_x509 + RENEWAL_CLOCK_SKEW < now) {
      glite_renewal_core_set_err(ctx, "Expired proxy in %s", proxy_file);
      ret = EDG_WLPR_PROXY_EXPIRED;
      goto end;
   }

   /* Myproxy seems not to do check on expiration and return expired proxies
      if credentials in repository are expired */
   for (i = 0; i < sk_X509_num(chain); i++) {
      t = X509_get_notAfter(sk_X509_value(chain, i));
      if (ASN1_UTCTIME_cmp_time_t(t, now - RENEWAL_CLOCK_SKEW) < 0) {
          glite_renewal_core_set_err(ctx, "Expired proxy in %s", proxy_file);
          ret = EDG_WLPR_PROXY_EXPIRED;
          goto end;
      }
   }

   *not_after_voms = end_time;
   *not_after_x509 = end_time_x509;
   ret = 0;

end:
   if (voms_data)
      VOMS_Destroy(voms_data);
   if (chain)
      sk_X509_pop_free(chain, X509_free);
   if (cert)
      X509_free(cert);

   return ret;
}
Example #6
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;
}
Example #7
0
KSSLCertificate*
KSSLCertificateFactory::generateSelfSigned(KSSLKeyType /*keytype*/) {
#if 0
  //#ifdef KSSL_HAVE_SSL
  X509_NAME *x509name = X509_NAME_new();
  X509      *x509;
  ASN1_UTCTIME *beforeafter;
  KSSLCertificate *newcert;
  int rc;

  // FIXME: generate the private key
  if (keytype == KEYTYPE_UNKNOWN || (key=EVP_PKEY_new()) == NULL) {
    X509_NAME_free(x509name);
    return NULL;
  }

  switch(keytype) {
  case KEYTYPE_RSA:
    if (!EVP_PKEY_assign_RSA(key, RSA_generate_key(newkey,0x10001,
						   req_cb,bio_err))) {
      
    } 
    break;
  case KEYTYPE_DSA:
    if (!DSA_generate_key(dsa_params)) goto end;
    if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end;
    dsa_params=NULL; 
    if (pkey->type == EVP_PKEY_DSA)
      digest=EVP_dss1();
    break;
  }

  // FIXME: dn doesn't exist
  // FIXME: allow the notAfter value to be parameterized
  // FIXME: allow a password to lock the key with

  // Fill in the certificate
  X509_NAME_add_entry_by_NID(x509name, OBJ_txt2nid("CN"), 0x1001,
                             (unsigned char *) dn, -1, -1, 0);

  x509 = X509_new();
  rc = X509_set_issuer_name(x509, x509name);
  if (rc != 0) {
    X509_free(x509);
    X509_NAME_free(x509name);
    return NULL;
  }
  rc = X509_set_subject_name(x509, x509name);
  if (rc != 0) {
    X509_free(x509);
    X509_NAME_free(x509name);
    return NULL;
  }
  ASN1_INTEGER_set(X509_get_serialNumber(*x509), 0);

  X509_NAME_free(x509name);

  // Make it a 1 year certificate
  beforeafter = ASN1_UTCTIME_new();
  if (!X509_gmtime_adj(beforeafter, -60*60*24)) {     // yesterday
    X509_free(x509);
    return NULL;
  }
  if (!X509_set_notBefore(x509, beforeafter)) {
    X509_free(x509);
    return NULL;
  }
  if (!X509_gmtime_adj(beforeafter, 60*60*24*364)) {  // a year from yesterday
    X509_free(x509);
    return NULL;
  }
  if (!X509_set_notAfter(x509, beforeafter)) {
    X509_free(x509);
    return NULL;
  }
  ASN1_UTCTIME_free(beforeafter);

  if (!X509_set_pubkey(x509, key)) {
    X509_free(x509);
    return NULL;
  }

  rc = X509_sign(x509, key, EVP_sha1());
  if (rc != 0) {
    X509_free(x509);
    return NULL;
  }

  newCert = new KSSLCertificate;
  newCert->setCert(x509);
  return newCert;  
#else
  return NULL;
#endif
}