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; }
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; }
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; }
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; }
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; }
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 }