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; }
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 X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) { EVP_PKEY *xk=NULL; int ok=0; xk=X509_REQ_get_pubkey(x); switch (EVP_PKEY_cmp(xk, k)) { case 1: ok=1; break; case 0: OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH); break; case -1: OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH); break; case -2: if (k->type == EVP_PKEY_EC) { OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB); break; } if (k->type == EVP_PKEY_DH) { /* No idea */ OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY); break; } OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE); } EVP_PKEY_free(xk); return(ok); }
static LUA_FUNCTION(openssl_csr_parse) { X509_REQ * csr = CHECK_OBJECT(1, X509_REQ, "openssl.x509_req"); X509_NAME * subject = X509_REQ_get_subject_name(csr); STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(csr); lua_newtable(L); openssl_push_asn1(L, csr->signature, V_ASN1_BIT_STRING); lua_setfield(L, -2, "signature"); openssl_push_x509_algor(L, csr->sig_alg); lua_setfield(L, -2, "sig_alg"); lua_newtable(L); AUXILIAR_SET(L, -1, "version", X509_REQ_get_version(csr), integer); openssl_push_xname_asobject(L, subject); lua_setfield(L, -2, "subject"); if (exts) { lua_pushstring(L, "extensions"); openssl_sk_x509_extension_totable(L, exts); lua_rawset(L, -3); sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } { X509_REQ_INFO* ri = csr->req_info; int i, c; EVP_PKEY *pubkey = X509_REQ_get_pubkey(csr); lua_newtable(L); c = X509_REQ_get_attr_count(csr); if (c > 0) { lua_newtable(L); for (i = 0; i < c ; i++) { X509_ATTRIBUTE *attr = X509_REQ_get_attr(csr, i); attr = X509_ATTRIBUTE_dup(attr); PUSH_OBJECT(attr, "openssl.x509_attribute"); lua_rawseti(L, -2, i + 1); } lua_setfield(L, -2, "attributes"); } lua_newtable(L); openssl_push_asn1object(L, ri->pubkey->algor->algorithm); lua_setfield(L, -2, "algorithm"); AUXILIAR_SETOBJECT(L, pubkey , "openssl.evp_pkey", -1, "pubkey"); lua_setfield(L, -2, "pubkey"); lua_setfield(L, -2, "req_info"); } return 1; }
static LUA_FUNCTION(openssl_csr_sign) { X509_REQ * csr = CHECK_OBJECT(1, X509_REQ, "openssl.x509_req"); luaL_argcheck(L, csr->req_info->pubkey, 1, "has not set public key!!!"); if (auxiliar_isclass(L, "openssl.evp_pkey", 2)) { EVP_PKEY *pkey = CHECK_OBJECT(2, EVP_PKEY, "openssl.evp_pkey"); const EVP_MD* md = lua_isnone(L, 3) ? EVP_get_digestbyname("sha1") : get_digest(L, 3); int ret = 1; if (X509_REQ_get_pubkey(csr) == NULL) { BIO* bio = BIO_new(BIO_s_mem()); if ( ret = i2d_PUBKEY_bio(bio, pkey)) { ret = X509_REQ_set_pubkey(csr, d2i_PUBKEY_bio(bio, NULL)); } BIO_free(bio); } if (ret == 1) ret = X509_REQ_sign(csr, pkey, md); return openssl_pushresult(L, ret); } else if (lua_isstring(L, 2)) { size_t siglen; const unsigned char* sigdata = (const unsigned char*)luaL_checklstring(L, 2, &siglen); const EVP_MD* md = get_digest(L, 3); /* (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) ? V_ASN1_NULL : V_ASN1_UNDEF, */ X509_ALGOR_set0(csr->sig_alg, OBJ_nid2obj(md->pkey_type), V_ASN1_NULL, NULL); if (csr->signature->data != NULL) OPENSSL_free(csr->signature->data); csr->signature->data = OPENSSL_malloc(siglen); memcpy(csr->signature->data, sigdata, siglen); csr->signature->length = siglen; /* * In the interests of compatibility, I'll make sure that the bit string * has a 'not-used bits' value of 0 */ csr->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); csr->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; lua_pushboolean(L, 1); return 1; } else { unsigned char* tosign = NULL; const ASN1_ITEM *it = ASN1_ITEM_rptr(X509_REQ_INFO); int inl = ASN1_item_i2d((void*)csr->req_info, &tosign, it); if (inl > 0 && tosign) { lua_pushlstring(L, (const char*)tosign, inl); OPENSSL_free(tosign); return 1; } return openssl_pushresult(L, 0); } }
static LUA_FUNCTION(openssl_csr_verify) { X509_REQ *csr = CHECK_OBJECT(1, X509_REQ, "openssl.x509_req"); EVP_PKEY * self_key = X509_REQ_get_pubkey(csr); lua_pushboolean(L, X509_REQ_verify(csr, self_key) == 1); EVP_PKEY_free(self_key); return 1; };
int pki_x509req::verify() const { EVP_PKEY *pkey = X509_REQ_get_pubkey(request); bool x = X509_REQ_verify(request,pkey) > 0; pki_ign_openssl_error(); EVP_PKEY_free(pkey); return x; }
pki_key *pki_x509req::getPubKey() const { EVP_PKEY *pkey = X509_REQ_get_pubkey(request); pki_ign_openssl_error(); if (pkey == NULL) return NULL; pki_evp *key = new pki_evp(pkey); pki_openssl_error(); return key; }
static X509 *X509_REQ_to_X509_ex(X509_REQ *r, int days, EVP_PKEY *pkey, const EVP_MD* md) { X509 *ret = NULL; X509_CINF *xi = NULL; X509_NAME *xn; EVP_PKEY *pubkey = NULL; int res; if ((ret = X509_new()) == NULL) { X509err(X509_F_X509_REQ_TO_X509, ERR_R_MALLOC_FAILURE); return NULL; } /* duplicate the request */ xi = ret->cert_info; if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) { if ((xi->version = M_ASN1_INTEGER_new()) == NULL) goto err; if (!ASN1_INTEGER_set(xi->version, 2)) goto err; /*- xi->extensions=ri->attributes; <- bad, should not ever be done ri->attributes=NULL; */ } xn = X509_REQ_get_subject_name(r); if (X509_set_subject_name(ret, xn) == 0) goto err; if (X509_set_issuer_name(ret, xn) == 0) goto err; if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL) goto err; if (X509_gmtime_adj(xi->validity->notAfter, (long)60 * 60 * 24 * days) == NULL) goto err; pubkey = X509_REQ_get_pubkey(r); res = X509_set_pubkey(ret, pubkey); EVP_PKEY_free(pubkey); if (!md) goto err; if (!res || !X509_sign(ret, pkey, md)) goto err; if (0) { err: X509_free(ret); ret = NULL; } return (ret); }
/* * read client data * * this function reads the client private key and the client certificate * request from files */ static int read_clientstuff(scep_t *scep, char *requestfile, char *keyfile) { BIO *bio; /* read the public key from the request */ bio = BIO_new(BIO_s_file()); if (BIO_read_filename(bio, requestfile) <= 0) { BIO_printf(bio_err, "%s:%d: cannot open request file\n", __FILE__, __LINE__); goto err; } scep->clientreq = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL); if (scep->clientreq == NULL) { BIO_printf(bio_err, "%s:%d: couldn't read the request " "from %s\n", __FILE__, __LINE__, requestfile); goto err; } scep->clientpubkey = X509_REQ_get_pubkey(scep->clientreq); if (scep->clientpubkey == NULL) { BIO_printf(bio_err, "%s:%d: no public key available\n", __FILE__, __LINE__); } BIO_free(bio); if (debug) BIO_printf(bio_err, "%s:%d: public key decoded\n", __FILE__, __LINE__); /* read private key (this probably needs a password) */ bio = BIO_new(BIO_s_file()); if (BIO_read_filename(bio, keyfile) <= 0) { BIO_printf(bio_err, "%s:%d: cannot open private key " "file %s\n", __FILE__, __LINE__, keyfile); goto err; } scep->clientpkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); if (scep->clientpkey == NULL) { BIO_printf(bio_err, "%s:%d: no private key available\n", __FILE__, __LINE__); goto err; } BIO_free(bio); if (debug) BIO_printf(bio_err, "%s:%d: private key decoded @%p\n", __FILE__, __LINE__, scep->clientpkey); if (debug > 1) { /* dump the key information so we can check whether */ /* we have private and public key information in the */ /* clientpkey member */ } return 0; err: /* some error has occured */ ERR_print_errors(bio_err); return -1; }
int pki_x509req::verify() { EVP_PKEY *pkey = X509_REQ_get_pubkey(request); bool x; if (spki) { x = NETSCAPE_SPKI_verify(spki, pkey) > 0; } else { x = X509_REQ_verify(request,pkey) > 0; } pki_ign_openssl_error(); EVP_PKEY_free(pkey); return x; }
X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) { X509 *ret = NULL; X509_CINF *xi = NULL; X509_NAME *xn; if ((ret = X509_new()) == NULL) { OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE); goto err; } /* duplicate the request */ xi = ret->cert_info; if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) { if ((xi->version = M_ASN1_INTEGER_new()) == NULL) goto err; if (!ASN1_INTEGER_set(xi->version, 2)) goto err; /* * xi->extensions=ri->attributes; <- bad, should not ever be done * ri->attributes=NULL; */ } xn = X509_REQ_get_subject_name(r); if (X509_set_subject_name(ret, X509_NAME_dup(xn)) == 0) goto err; if (X509_set_issuer_name(ret, X509_NAME_dup(xn)) == 0) goto err; if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL) goto err; if (X509_gmtime_adj(xi->validity->notAfter, (long)60 * 60 * 24 * days) == NULL) goto err; X509_set_pubkey(ret, X509_REQ_get_pubkey(r)); if (!X509_sign(ret, pkey, EVP_md5())) goto err; if (0) { err: X509_free(ret); ret = NULL; } return (ret); }
static LUA_FUNCTION(openssl_csr_public) { X509_REQ *csr = CHECK_OBJECT(1, X509_REQ, "openssl.x509_req"); if (lua_isnone(L, 2)) { EVP_PKEY *pkey = X509_REQ_get_pubkey(csr); PUSH_OBJECT(pkey, "openssl.evp_pkey"); return 1; } else { EVP_PKEY *pkey = CHECK_OBJECT(2, EVP_PKEY, "openssl.evp_pkey"); int ret = X509_REQ_set_pubkey(csr, pkey); return openssl_pushresult(L, ret); } }
int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) { EVP_PKEY *xk = NULL; int ok = 0; xk = X509_REQ_get_pubkey(x); switch (EVP_PKEY_cmp(xk, k)) { case 1: ok = 1; break; case 0: X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_KEY_VALUES_MISMATCH); break; case -1: X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_KEY_TYPE_MISMATCH); break; case -2: #ifndef OPENSSL_NO_EC if (k->type == EVP_PKEY_EC) { X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, ERR_R_EC_LIB); break; } #endif #ifndef OPENSSL_NO_DH if (k->type == EVP_PKEY_DH) { /* No idea */ X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_CANT_CHECK_DH_KEY); break; } #endif X509err(X509_F_X509_REQ_CHECK_PRIVATE_KEY, X509_R_UNKNOWN_KEY_TYPE); } EVP_PKEY_free(xk); return (ok); }
/* * read requestor data * * for version 2 requests, the requestor and the SCEP client can be different * and the request does not need to be a PKCS#10 */ static int read_requestorstuff(scep_t *scep, int type, char *filename) { BIO *bio; NETSCAPE_SPKI *spki = NULL; X509_REQ *req = NULL; bio = BIO_new(BIO_s_file()); if (BIO_read_filename(bio, filename) < 0) { BIO_printf(bio_err, "%s:%d: cannot read request file '%s'\n", __FILE__, __LINE__, filename); goto err; } switch (type) { case 0: scep->requestorreq = d2i_X509_REQ_bio(bio, &req); if (scep->requestorreq == NULL) { BIO_printf(bio_err, "%s:%d: cannot decode X509_REQ\n", __FILE__, __LINE__); goto err; } scep->requestorpubkey = X509_REQ_get_pubkey(scep->requestorreq); break; case 1: scep->requestorspki = d2i_NETSCAPE_SPKI_bio(bio, &spki); if (scep->requestorspki == NULL) { BIO_printf(bio_err, "%s:%d: cannot decode SPKI\n", __FILE__, __LINE__); goto err; } scep->requestorpubkey = NETSCAPE_SPKI_get_pubkey(scep->requestorspki); break; default: goto err; } return 0; err: ERR_print_errors(bio_err); return -1; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; int ret=1; X509_REQ *req=NULL; X509 *x=NULL,*xca=NULL; ASN1_OBJECT *objtmp; STACK_OF(OPENSSL_STRING) *sigopts = NULL; EVP_PKEY *Upkey=NULL,*CApkey=NULL; ASN1_INTEGER *sno = NULL; int i,num,badops=0; BIO *out=NULL; BIO *STDout=NULL; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; int informat,outformat,keyformat,CAformat,CAkeyformat; char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL; char *CAkeyfile=NULL,*CAserial=NULL; char *alias=NULL; int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0; int next_serial=0; int subject_hash=0,issuer_hash=0,ocspid=0; #ifndef OPENSSL_NO_MD5 int subject_hash_old=0,issuer_hash_old=0; #endif int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0; int ocsp_uri=0; int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0; int C=0; int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0; int pprint = 0; const char **pp; X509_STORE *ctx=NULL; X509_REQ *rq=NULL; int fingerprint=0; char buf[256]; const EVP_MD *md_alg,*digest=NULL; CONF *extconf = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL; int need_rand = 0; int checkend=0,checkoffset=0; unsigned long nmflag = 0, certflag = 0; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif reqfile=0; apps_startup(); if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; STDout=BIO_new_fp(stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); STDout = BIO_push(tmpbio, STDout); } #endif informat=FORMAT_PEM; outformat=FORMAT_PEM; keyformat=FORMAT_PEM; CAformat=FORMAT_PEM; CAkeyformat=FORMAT_PEM; ctx=X509_STORE_new(); if (ctx == NULL) goto end; X509_STORE_set_verify_cb(ctx,callb); argc--; argv++; num=0; while (argc >= 1) { if (strcmp(*argv,"-inform") == 0) { if (--argc < 1) goto bad; informat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-outform") == 0) { if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) goto bad; keyformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-req") == 0) { reqfile=1; need_rand = 1; } else if (strcmp(*argv,"-CAform") == 0) { if (--argc < 1) goto bad; CAformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-CAkeyform") == 0) { if (--argc < 1) goto bad; CAkeyformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-sigopt") == 0) { if (--argc < 1) goto bad; if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) goto bad; } else if (strcmp(*argv,"-days") == 0) { if (--argc < 1) goto bad; days=atoi(*(++argv)); if (days == 0) { BIO_printf(STDout,"bad number of days\n"); goto bad; } } else if (strcmp(*argv,"-passin") == 0) { if (--argc < 1) goto bad; passargin= *(++argv); } else if (strcmp(*argv,"-extfile") == 0) { if (--argc < 1) goto bad; extfile= *(++argv); } else if (strcmp(*argv,"-extensions") == 0) { if (--argc < 1) goto bad; extsect= *(++argv); } else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; infile= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } else if (strcmp(*argv,"-signkey") == 0) { if (--argc < 1) goto bad; keyfile= *(++argv); sign_flag= ++num; need_rand = 1; } else if (strcmp(*argv,"-CA") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); CA_flag= ++num; need_rand = 1; } else if (strcmp(*argv,"-CAkey") == 0) { if (--argc < 1) goto bad; CAkeyfile= *(++argv); } else if (strcmp(*argv,"-CAserial") == 0) { if (--argc < 1) goto bad; CAserial= *(++argv); } else if (strcmp(*argv,"-set_serial") == 0) { if (--argc < 1) goto bad; if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv)))) goto bad; } else if (strcmp(*argv,"-addtrust") == 0) { if (--argc < 1) goto bad; if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { BIO_printf(bio_err, "Invalid trust object value %s\n", *argv); goto bad; } if (!trust) trust = sk_ASN1_OBJECT_new_null(); sk_ASN1_OBJECT_push(trust, objtmp); trustout = 1; } else if (strcmp(*argv,"-addreject") == 0) { if (--argc < 1) goto bad; if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { BIO_printf(bio_err, "Invalid reject object value %s\n", *argv); goto bad; } if (!reject) reject = sk_ASN1_OBJECT_new_null(); sk_ASN1_OBJECT_push(reject, objtmp); trustout = 1; } else if (strcmp(*argv,"-setalias") == 0) { if (--argc < 1) goto bad; alias= *(++argv); trustout = 1; } else if (strcmp(*argv,"-certopt") == 0) { if (--argc < 1) goto bad; if (!set_cert_ex(&certflag, *(++argv))) goto bad; } else if (strcmp(*argv,"-nameopt") == 0) { if (--argc < 1) goto bad; if (!set_name_ex(&nmflag, *(++argv))) goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-C") == 0) C= ++num; else if (strcmp(*argv,"-email") == 0) email= ++num; else if (strcmp(*argv,"-ocsp_uri") == 0) ocsp_uri= ++num; else if (strcmp(*argv,"-serial") == 0) serial= ++num; else if (strcmp(*argv,"-next_serial") == 0) next_serial= ++num; else if (strcmp(*argv,"-modulus") == 0) modulus= ++num; else if (strcmp(*argv,"-pubkey") == 0) pubkey= ++num; else if (strcmp(*argv,"-x509toreq") == 0) x509req= ++num; else if (strcmp(*argv,"-text") == 0) text= ++num; else if (strcmp(*argv,"-hash") == 0 || strcmp(*argv,"-subject_hash") == 0) subject_hash= ++num; #ifndef OPENSSL_NO_MD5 else if (strcmp(*argv,"-subject_hash_old") == 0) subject_hash_old= ++num; #endif else if (strcmp(*argv,"-issuer_hash") == 0) issuer_hash= ++num; #ifndef OPENSSL_NO_MD5 else if (strcmp(*argv,"-issuer_hash_old") == 0) issuer_hash_old= ++num; #endif else if (strcmp(*argv,"-subject") == 0) subject= ++num; else if (strcmp(*argv,"-issuer") == 0) issuer= ++num; else if (strcmp(*argv,"-fingerprint") == 0) fingerprint= ++num; else if (strcmp(*argv,"-dates") == 0) { startdate= ++num; enddate= ++num; } else if (strcmp(*argv,"-purpose") == 0) pprint= ++num; else if (strcmp(*argv,"-startdate") == 0) startdate= ++num; else if (strcmp(*argv,"-enddate") == 0) enddate= ++num; else if (strcmp(*argv,"-checkend") == 0) { if (--argc < 1) goto bad; checkoffset=atoi(*(++argv)); checkend=1; } else if (strcmp(*argv,"-noout") == 0) noout= ++num; else if (strcmp(*argv,"-trustout") == 0) trustout= 1; else if (strcmp(*argv,"-clrtrust") == 0) clrtrust= ++num; else if (strcmp(*argv,"-clrreject") == 0) clrreject= ++num; else if (strcmp(*argv,"-alias") == 0) aliasout= ++num; else if (strcmp(*argv,"-CAcreateserial") == 0) CA_createserial= ++num; else if (strcmp(*argv,"-clrext") == 0) clrext = 1; #if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */ else if (strcmp(*argv,"-crlext") == 0) { BIO_printf(bio_err,"use -clrext instead of -crlext\n"); clrext = 1; } #endif else if (strcmp(*argv,"-ocspid") == 0) ocspid= ++num; else if ((md_alg=EVP_get_digestbyname(*argv + 1))) { /* ok */ digest=md_alg; } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: for (pp=x509_usage; (*pp != NULL); pp++) BIO_printf(bio_err,"%s",*pp); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif if (need_rand) app_RAND_load_file(NULL, bio_err, 0); ERR_load_crypto_strings(); if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (!X509_STORE_set_default_paths(ctx)) { ERR_print_errors(bio_err); goto end; } if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { CAkeyfile=CAfile; } else if ((CA_flag) && (CAkeyfile == NULL)) { BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n"); goto end; } if (extfile) { long errorline = -1; X509V3_CTX ctx2; extconf = NCONF_new(NULL); if (!NCONF_load(extconf, extfile,&errorline)) { if (errorline <= 0) BIO_printf(bio_err, "error loading the config file '%s'\n", extfile); else BIO_printf(bio_err, "error on line %ld of config file '%s'\n" ,errorline,extfile); goto end; } if (!extsect) { extsect = NCONF_get_string(extconf, "default", "extensions"); if (!extsect) { ERR_clear_error(); extsect = "default"; } } X509V3_set_ctx_test(&ctx2); X509V3_set_nconf(&ctx2, extconf); if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { BIO_printf(bio_err, "Error Loading extension section %s\n", extsect); ERR_print_errors(bio_err); goto end; } } if (reqfile) { EVP_PKEY *pkey; BIO *in; if (!sign_flag && !CA_flag) { BIO_printf(bio_err,"We need a private key to sign with\n"); goto end; } in=BIO_new(BIO_s_file()); if (in == NULL) { ERR_print_errors(bio_err); goto end; } if (infile == NULL) BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT); else { if (BIO_read_filename(in,infile) <= 0) { perror(infile); BIO_free(in); goto end; } } req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL); BIO_free(in); if (req == NULL) { ERR_print_errors(bio_err); goto end; } if ( (req->req_info == NULL) || (req->req_info->pubkey == NULL) || (req->req_info->pubkey->public_key == NULL) || (req->req_info->pubkey->public_key->data == NULL)) { BIO_printf(bio_err,"The certificate request appears to corrupted\n"); BIO_printf(bio_err,"It does not contain a public key\n"); goto end; } if ((pkey=X509_REQ_get_pubkey(req)) == NULL) { BIO_printf(bio_err,"error unpacking public key\n"); goto end; } i=X509_REQ_verify(req,pkey); EVP_PKEY_free(pkey); if (i < 0) { BIO_printf(bio_err,"Signature verification error\n"); ERR_print_errors(bio_err); goto end; } if (i == 0) { BIO_printf(bio_err,"Signature did not match the certificate request\n"); goto end; } else BIO_printf(bio_err,"Signature ok\n"); print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag); if ((x=X509_new()) == NULL) goto end; if (sno == NULL) { sno = ASN1_INTEGER_new(); if (!sno || !rand_serial(NULL, sno)) goto end; if (!X509_set_serialNumber(x, sno)) goto end; ASN1_INTEGER_free(sno); sno = NULL; } else if (!X509_set_serialNumber(x, sno)) goto end; if (!X509_set_issuer_name(x,req->req_info->subject)) goto end; if (!X509_set_subject_name(x,req->req_info->subject)) goto end; X509_gmtime_adj(X509_get_notBefore(x),0); X509_time_adj_ex(X509_get_notAfter(x),days, 0, NULL); pkey = X509_REQ_get_pubkey(req); X509_set_pubkey(x,pkey); EVP_PKEY_free(pkey); } else x=load_cert(bio_err,infile,informat,NULL,e,"Certificate"); if (x == NULL) goto end; if (CA_flag) { xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate"); if (xca == NULL) goto end; } if (!noout || text || next_serial) { OBJ_create("2.99999.3", "SET.ex3","SET x509v3 extension 3"); out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } } if (alias) X509_alias_set1(x, (unsigned char *)alias, -1); if (clrtrust) X509_trust_clear(x); if (clrreject) X509_reject_clear(x); if (trust) { for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { objtmp = sk_ASN1_OBJECT_value(trust, i); X509_add1_trust_object(x, objtmp); } } if (reject) { for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { objtmp = sk_ASN1_OBJECT_value(reject, i); X509_add1_reject_object(x, objtmp); } } if (num) { for (i=1; i<=num; i++) { if (issuer == i) { print_name(STDout, "issuer= ", X509_get_issuer_name(x), nmflag); } else if (subject == i) { print_name(STDout, "subject= ", X509_get_subject_name(x), nmflag); } else if (serial == i) { BIO_printf(STDout,"serial="); i2a_ASN1_INTEGER(STDout, X509_get_serialNumber(x)); BIO_printf(STDout,"\n"); } else if (next_serial == i) { BIGNUM *bnser; ASN1_INTEGER *ser; ser = X509_get_serialNumber(x); bnser = ASN1_INTEGER_to_BN(ser, NULL); if (!bnser) goto end; if (!BN_add_word(bnser, 1)) goto end; ser = BN_to_ASN1_INTEGER(bnser, NULL); if (!ser) goto end; BN_free(bnser); i2a_ASN1_INTEGER(out, ser); ASN1_INTEGER_free(ser); BIO_puts(out, "\n"); } else if ((email == i) || (ocsp_uri == i)) { int j; STACK_OF(OPENSSL_STRING) *emlst; if (email == i) emlst = X509_get1_email(x); else emlst = X509_get1_ocsp(x); for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) BIO_printf(STDout, "%s\n", sk_OPENSSL_STRING_value(emlst, j)); X509_email_free(emlst); } else if (aliasout == i) { unsigned char *alstr; alstr = X509_alias_get0(x, NULL); if (alstr) BIO_printf(STDout,"%s\n", alstr); else BIO_puts(STDout,"<No Alias>\n"); } else if (subject_hash == i) { BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (subject_hash_old == i) { BIO_printf(STDout,"%08lx\n",X509_subject_name_hash_old(x)); } #endif else if (issuer_hash == i) { BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (issuer_hash_old == i) { BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash_old(x)); } #endif else if (pprint == i) { X509_PURPOSE *ptmp; int j; BIO_printf(STDout, "Certificate purposes:\n"); for (j = 0; j < X509_PURPOSE_get_count(); j++) { ptmp = X509_PURPOSE_get0(j); purpose_print(STDout, x, ptmp); } } else if (modulus == i) { EVP_PKEY *pkey; pkey=X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err,"Modulus=unavailable\n"); ERR_print_errors(bio_err); goto end; } BIO_printf(STDout,"Modulus="); #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) BN_print(STDout,pkey->pkey.rsa->n); else #endif #ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) BN_print(STDout,pkey->pkey.dsa->pub_key); else #endif BIO_printf(STDout,"Wrong Algorithm type"); BIO_printf(STDout,"\n"); EVP_PKEY_free(pkey); } else if (pubkey == i) { EVP_PKEY *pkey; pkey=X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err,"Error getting public key\n"); ERR_print_errors(bio_err); goto end; } PEM_write_bio_PUBKEY(STDout, pkey); EVP_PKEY_free(pkey); } else if (C == i) { unsigned char *d; char *m; int y,z; X509_NAME_oneline(X509_get_subject_name(x), buf,sizeof buf); BIO_printf(STDout,"/* subject:%s */\n",buf); m=X509_NAME_oneline( X509_get_issuer_name(x),buf, sizeof buf); BIO_printf(STDout,"/* issuer :%s */\n",buf); z=i2d_X509(x,NULL); m=OPENSSL_malloc(z); d=(unsigned char *)m; z=i2d_X509_NAME(X509_get_subject_name(x),&d); BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d); BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); z=i2d_X509(x,&d); BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); OPENSSL_free(m); } else if (text == i) { X509_print_ex(out,x,nmflag, certflag); } else if (startdate == i) { BIO_puts(STDout,"notBefore="); ASN1_TIME_print(STDout,X509_get_notBefore(x)); BIO_puts(STDout,"\n"); } else if (enddate == i) { BIO_puts(STDout,"notAfter="); ASN1_TIME_print(STDout,X509_get_notAfter(x)); BIO_puts(STDout,"\n"); } else if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; const EVP_MD *fdig = digest; if (!fdig) fdig = EVP_sha1(); if (!X509_digest(x,fdig,md,&n)) { BIO_printf(bio_err,"out of memory\n"); goto end; } BIO_printf(STDout,"%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(fdig))); for (j=0; j<(int)n; j++) { BIO_printf(STDout,"%02X%c",md[j], (j+1 == (int)n) ?'\n':':'); } } /* should be in the library */ else if ((sign_flag == i) && (x509req == 0)) { BIO_printf(bio_err,"Getting Private key\n"); if (Upkey == NULL) { Upkey=load_key(bio_err, keyfile, keyformat, 0, passin, e, "Private key"); if (Upkey == NULL) goto end; } assert(need_rand); if (!sign(x,Upkey,days,clrext,digest, extconf, extsect)) goto end; } else if (CA_flag == i) { BIO_printf(bio_err,"Getting CA Private Key\n"); if (CAkeyfile != NULL) { CApkey=load_key(bio_err, CAkeyfile, CAkeyformat, 0, passin, e, "CA Private Key"); if (CApkey == NULL) goto end; } assert(need_rand); if (!x509_certify(ctx,CAfile,digest,x,xca, CApkey, sigopts, CAserial,CA_createserial,days, clrext, extconf, extsect, sno)) goto end; } else if (x509req == i) { EVP_PKEY *pk; BIO_printf(bio_err,"Getting request Private Key\n"); if (keyfile == NULL) { BIO_printf(bio_err,"no request key file specified\n"); goto end; } else { pk=load_key(bio_err, keyfile, keyformat, 0, passin, e, "request key"); if (pk == NULL) goto end; } BIO_printf(bio_err,"Generating certificate request\n"); rq=X509_to_X509_REQ(x,pk,digest); EVP_PKEY_free(pk); if (rq == NULL) { ERR_print_errors(bio_err); goto end; } if (!noout) { X509_REQ_print(out,rq); PEM_write_bio_X509_REQ(out,rq); } noout=1; } else if (ocspid == i) { X509_ocspid_print(out, x); } } } if (checkend) { time_t tcheck=time(NULL) + checkoffset; if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) { BIO_printf(out,"Certificate will expire\n"); ret=1; } else { BIO_printf(out,"Certificate will not expire\n"); ret=0; } goto end; } if (noout) { ret=0; goto end; } if (outformat == FORMAT_ASN1) i=i2d_X509_bio(out,x); else if (outformat == FORMAT_PEM) { if (trustout) i=PEM_write_bio_X509_AUX(out,x); else i=PEM_write_bio_X509(out,x); } else if (outformat == FORMAT_NETSCAPE) { NETSCAPE_X509 nx; ASN1_OCTET_STRING hdr; hdr.data=(unsigned char *)NETSCAPE_CERT_HDR; hdr.length=strlen(NETSCAPE_CERT_HDR); nx.header= &hdr; nx.cert=x; i=ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509),out,&nx); } else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write certificate\n"); ERR_print_errors(bio_err); goto end; } ret=0; end: if (need_rand) app_RAND_write_file(NULL, bio_err); OBJ_cleanup(); NCONF_free(extconf); BIO_free_all(out); BIO_free_all(STDout); X509_STORE_free(ctx); X509_REQ_free(req); X509_free(x); X509_free(xca); EVP_PKEY_free(Upkey); EVP_PKEY_free(CApkey); if (sigopts) sk_OPENSSL_STRING_free(sigopts); X509_REQ_free(rq); ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); if (passin) OPENSSL_free(passin); apps_shutdown(); OPENSSL_EXIT(ret); }
/*** sign x509_req object @function sign @tparam evp_pkey pkey private key which to sign x509_req object @tparam number|string|evp_md md message digest alg used to sign @treturn boolean result true for suceess */ static LUA_FUNCTION(openssl_csr_sign) { X509_REQ * csr = CHECK_OBJECT(1, X509_REQ, "openssl.x509_req"); EVP_PKEY *pubkey = X509_REQ_get_pubkey(csr); if (auxiliar_getclassudata(L, "openssl.evp_pkey", 2)) { EVP_PKEY *pkey = CHECK_OBJECT(2, EVP_PKEY, "openssl.evp_pkey"); const EVP_MD* md = get_digest(L, 3, "sha256"); int ret = 1; if (pubkey == NULL) { BIO* bio = BIO_new(BIO_s_mem()); if ((ret = i2d_PUBKEY_bio(bio, pkey)) == 1) { pubkey = d2i_PUBKEY_bio(bio, NULL); if (pubkey) { ret = X509_REQ_set_pubkey(csr, pubkey); EVP_PKEY_free(pubkey); } else { ret = 0; } } BIO_free(bio); } else { EVP_PKEY_free(pubkey); } if (ret == 1) ret = X509_REQ_sign(csr, pkey, md); return openssl_pushresult(L, ret); } else if (lua_isstring(L, 2)) { size_t siglen; unsigned char* sigdata = (unsigned char*)luaL_checklstring(L, 2, &siglen); const EVP_MD* md = get_digest(L, 3, NULL); ASN1_BIT_STRING *sig = NULL; X509_ALGOR *alg = NULL; luaL_argcheck(L, pubkey != NULL, 1, "has not set public key!!!"); X509_REQ_get0_signature(csr, (const ASN1_BIT_STRING **)&sig, (const X509_ALGOR **)&alg); /* (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) ? V_ASN1_NULL : V_ASN1_UNDEF, */ X509_ALGOR_set0((X509_ALGOR *)alg, OBJ_nid2obj(EVP_MD_pkey_type(md)), V_ASN1_NULL, NULL); ASN1_BIT_STRING_set((ASN1_BIT_STRING *)sig, sigdata, siglen); /* * In the interests of compatibility, I'll make sure that the bit string * has a 'not-used bits' value of 0 */ sig->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); sig->flags |= ASN1_STRING_FLAG_BITS_LEFT; lua_pushboolean(L, 1); return 1; } else { int inl; unsigned char* tosign = NULL; luaL_argcheck(L, pubkey != NULL, 1, "has not set public key!!!"); inl = i2d_re_X509_REQ_tbs(csr, &tosign); if (inl > 0 && tosign) { lua_pushlstring(L, (const char*)tosign, inl); OPENSSL_free(tosign); return 1; } return openssl_pushresult(L, 0); } }
int X509_REQ_print_ex(BIO *bio, X509_REQ *x, unsigned long nmflags, unsigned long cflag) { long l; EVP_PKEY *pkey; STACK_OF(X509_ATTRIBUTE) * sk; char mlch = ' '; int nmindent = 0; if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { mlch = '\n'; nmindent = 12; } if (nmflags == X509_FLAG_COMPAT) { nmindent = 16; } X509_REQ_INFO *ri = x->req_info; if (!(cflag & X509_FLAG_NO_HEADER)) { if (BIO_write(bio, "Certificate Request:\n", 21) <= 0 || BIO_write(bio, " Data:\n", 10) <= 0) { goto err; } } if (!(cflag & X509_FLAG_NO_VERSION)) { l = X509_REQ_get_version(x); if (BIO_printf(bio, "%8sVersion: %ld (0x%lx)\n", "", l + 1, l) <= 0) { goto err; } } if (!(cflag & X509_FLAG_NO_SUBJECT)) { if (BIO_printf(bio, " Subject:%c", mlch) <= 0 || X509_NAME_print_ex(bio, ri->subject, nmindent, nmflags) < 0 || BIO_write(bio, "\n", 1) <= 0) { goto err; } } if (!(cflag & X509_FLAG_NO_PUBKEY)) { if (BIO_write(bio, " Subject Public Key Info:\n", 33) <= 0 || BIO_printf(bio, "%12sPublic Key Algorithm: ", "") <= 0 || i2a_ASN1_OBJECT(bio, ri->pubkey->algor->algorithm) <= 0 || BIO_puts(bio, "\n") <= 0) { goto err; } pkey = X509_REQ_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio, "%12sUnable to load Public Key\n", ""); ERR_print_errors(bio); } else { EVP_PKEY_print_public(bio, pkey, 16, NULL); EVP_PKEY_free(pkey); } } if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) { if (BIO_printf(bio, "%8sAttributes:\n", "") <= 0) { goto err; } sk = x->req_info->attributes; if (sk_X509_ATTRIBUTE_num(sk) == 0) { if (BIO_printf(bio, "%12sa0:00\n", "") <= 0) { goto err; } } else { size_t i; for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { X509_ATTRIBUTE *a = sk_X509_ATTRIBUTE_value(sk, i); ASN1_OBJECT *aobj = X509_ATTRIBUTE_get0_object(a); if (X509_REQ_extension_nid(OBJ_obj2nid(aobj))) { continue; } if (BIO_printf(bio, "%12s", "") <= 0) { goto err; } const int num_attrs = X509_ATTRIBUTE_count(a); const int obj_str_len = i2a_ASN1_OBJECT(bio, aobj); if (obj_str_len <= 0) { if (BIO_puts(bio, "(Unable to print attribute ID.)\n") < 0) { goto err; } else { continue; } } int j; for (j = 0; j < num_attrs; j++) { const ASN1_TYPE *at = X509_ATTRIBUTE_get0_type(a, j); const int type = at->type; ASN1_BIT_STRING *bs = at->value.asn1_string; int k; for (k = 25 - obj_str_len; k > 0; k--) { if (BIO_write(bio, " ", 1) != 1) { goto err; } } if (BIO_puts(bio, ":") <= 0) { goto err; } if (type == V_ASN1_PRINTABLESTRING || type == V_ASN1_UTF8STRING || type == V_ASN1_IA5STRING || type == V_ASN1_T61STRING) { if (BIO_write(bio, (char *)bs->data, bs->length) != bs->length) { goto err; } BIO_puts(bio, "\n"); } else { BIO_puts(bio, "unable to print attribute\n"); } } } } } if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(x); if (exts) { BIO_printf(bio, "%8sRequested Extensions:\n", ""); size_t i; for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i); if (BIO_printf(bio, "%12s", "") <= 0) { goto err; } ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex); i2a_ASN1_OBJECT(bio, obj); const int is_critical = X509_EXTENSION_get_critical(ex); if (BIO_printf(bio, ": %s\n", is_critical ? "critical" : "") <= 0) { goto err; } if (!X509V3_EXT_print(bio, ex, cflag, 16)) { BIO_printf(bio, "%16s", ""); ASN1_STRING_print(bio, X509_EXTENSION_get_data(ex)); } if (BIO_write(bio, "\n", 1) <= 0) { goto err; } } sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } } if (!(cflag & X509_FLAG_NO_SIGDUMP) && !X509_signature_print(bio, x->sig_alg, x->signature)) { goto err; } return 1; err: OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB); return 0; }
/* * initialize ssl engine, load certs and initialize openssl internals */ void init_ssl(void) { const SSL_METHOD *ssl_method; RSA *rsa=NULL; X509_REQ *req = NULL; X509 *cer = NULL; EVP_PKEY *pk = NULL; EVP_PKEY *req_pkey = NULL; X509_NAME *name = NULL; FILE *fp; char buf[SIZ]; int rv = 0; if (!access("/var/run/egd-pool", F_OK)) { RAND_egd("/var/run/egd-pool"); } if (!RAND_status()) { syslog(LOG_WARNING, "PRNG not adequately seeded, won't do SSL/TLS\n"); return; } SSLCritters = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *)); if (!SSLCritters) { syslog(LOG_ERR, "citserver: can't allocate memory!!\n"); /* Nothing's been initialized, just die */ ShutDownWebcit(); exit(WC_EXIT_SSL); } else { int a; for (a = 0; a < CRYPTO_num_locks(); a++) { SSLCritters[a] = malloc(sizeof(pthread_mutex_t)); if (!SSLCritters[a]) { syslog(LOG_EMERG, "citserver: can't allocate memory!!\n"); /** Nothing's been initialized, just die */ ShutDownWebcit(); exit(WC_EXIT_SSL); } pthread_mutex_init(SSLCritters[a], NULL); } } /* * Initialize SSL transport layer */ SSL_library_init(); SSL_load_error_strings(); ssl_method = SSLv23_server_method(); if (!(ssl_ctx = SSL_CTX_new(ssl_method))) { syslog(LOG_WARNING, "SSL_CTX_new failed: %s\n", ERR_reason_error_string(ERR_get_error())); return; } syslog(LOG_INFO, "Requesting cipher list: %s\n", ssl_cipher_list); if (!(SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher_list))) { syslog(LOG_WARNING, "SSL_CTX_set_cipher_list failed: %s\n", ERR_reason_error_string(ERR_get_error())); return; } CRYPTO_set_locking_callback(ssl_lock); CRYPTO_set_id_callback(id_callback); /* * Get our certificates in order. (FIXME: dirify. this is a setup job.) * First, create the key/cert directory if it's not there already... */ mkdir(CTDL_CRYPTO_DIR, 0700); /* * Before attempting to generate keys/certificates, first try * link to them from the Citadel server if it's on the same host. * We ignore any error return because it either meant that there * was nothing in Citadel to link from (in which case we just * generate new files) or the target files already exist (which * is not fatal either). */ if (!strcasecmp(ctdlhost, "uds")) { sprintf(buf, "%s/keys/citadel.key", ctdlport); rv = symlink(buf, CTDL_KEY_PATH); if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno)); sprintf(buf, "%s/keys/citadel.csr", ctdlport); rv = symlink(buf, CTDL_CSR_PATH); if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno)); sprintf(buf, "%s/keys/citadel.cer", ctdlport); rv = symlink(buf, CTDL_CER_PATH); if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno)); } /* * If we still don't have a private key, generate one. */ if (access(CTDL_KEY_PATH, R_OK) != 0) { syslog(LOG_INFO, "Generating RSA key pair.\n"); rsa = RSA_generate_key(1024, /* modulus size */ 65537, /* exponent */ NULL, /* no callback */ NULL /* no callback */ ); if (rsa == NULL) { syslog(LOG_WARNING, "Key generation failed: %s\n", ERR_reason_error_string(ERR_get_error())); } if (rsa != NULL) { fp = fopen(CTDL_KEY_PATH, "w"); if (fp != NULL) { chmod(CTDL_KEY_PATH, 0600); if (PEM_write_RSAPrivateKey(fp, /* the file */ rsa, /* the key */ NULL, /* no enc */ NULL, /* no passphr */ 0, /* no passphr */ NULL, /* no callbk */ NULL /* no callbk */ ) != 1) { syslog(LOG_WARNING, "Cannot write key: %s\n", ERR_reason_error_string(ERR_get_error())); unlink(CTDL_KEY_PATH); } fclose(fp); } else { syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_KEY_PATH); ShutDownWebcit(); exit(0); } RSA_free(rsa); } } /* * If there is no certificate file on disk, we will be generating a self-signed certificate * in the next step. Therefore, if we have neither a CSR nor a certificate, generate * the CSR in this step so that the next step may commence. */ if ( (access(CTDL_CER_PATH, R_OK) != 0) && (access(CTDL_CSR_PATH, R_OK) != 0) ) { syslog(LOG_INFO, "Generating a certificate signing request.\n"); /* * Read our key from the file. No, we don't just keep this * in memory from the above key-generation function, because * there is the possibility that the key was already on disk * and we didn't just generate it now. */ fp = fopen(CTDL_KEY_PATH, "r"); if (fp) { rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); } if (rsa) { /** Create a public key from the private key */ if (pk=EVP_PKEY_new(), pk != NULL) { EVP_PKEY_assign_RSA(pk, rsa); if (req = X509_REQ_new(), req != NULL) { const char *env; /* Set the public key */ X509_REQ_set_pubkey(req, pk); X509_REQ_set_version(req, 0L); name = X509_REQ_get_subject_name(req); /* Tell it who we are */ /* * We used to add these fields to the subject, but * now we don't. Someone doing this for real isn't * going to use the webcit-generated CSR anyway. * X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, "US", -1, -1, 0); * X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, "New York", -1, -1, 0); * X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, "Mount Kisco", -1, -1, 0); */ env = getenv("O"); if (env == NULL) env = "Organization name", X509_NAME_add_entry_by_txt( name, "O", MBSTRING_ASC, (unsigned char*)env, -1, -1, 0 ); env = getenv("OU"); if (env == NULL) env = "Citadel server"; X509_NAME_add_entry_by_txt( name, "OU", MBSTRING_ASC, (unsigned char*)env, -1, -1, 0 ); env = getenv("CN"); if (env == NULL) env = "*"; X509_NAME_add_entry_by_txt( name, "CN", MBSTRING_ASC, (unsigned char*)env, -1, -1, 0 ); X509_REQ_set_subject_name(req, name); /* Sign the CSR */ if (!X509_REQ_sign(req, pk, EVP_md5())) { syslog(LOG_WARNING, "X509_REQ_sign(): error\n"); } else { /* Write it to disk. */ fp = fopen(CTDL_CSR_PATH, "w"); if (fp != NULL) { chmod(CTDL_CSR_PATH, 0600); PEM_write_X509_REQ(fp, req); fclose(fp); } else { syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_CSR_PATH); ShutDownWebcit(); exit(0); } } X509_REQ_free(req); } } RSA_free(rsa); } else { syslog(LOG_WARNING, "Unable to read private key.\n"); } } /* * Generate a self-signed certificate if we don't have one. */ if (access(CTDL_CER_PATH, R_OK) != 0) { syslog(LOG_INFO, "Generating a self-signed certificate.\n"); /* Same deal as before: always read the key from disk because * it may or may not have just been generated. */ fp = fopen(CTDL_KEY_PATH, "r"); if (fp) { rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); } /* This also holds true for the CSR. */ req = NULL; cer = NULL; pk = NULL; if (rsa) { if (pk=EVP_PKEY_new(), pk != NULL) { EVP_PKEY_assign_RSA(pk, rsa); } fp = fopen(CTDL_CSR_PATH, "r"); if (fp) { req = PEM_read_X509_REQ(fp, NULL, NULL, NULL); fclose(fp); } if (req) { if (cer = X509_new(), cer != NULL) { ASN1_INTEGER_set(X509_get_serialNumber(cer), 0); X509_set_issuer_name(cer, req->req_info->subject); X509_set_subject_name(cer, req->req_info->subject); X509_gmtime_adj(X509_get_notBefore(cer), 0); X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS); req_pkey = X509_REQ_get_pubkey(req); X509_set_pubkey(cer, req_pkey); EVP_PKEY_free(req_pkey); /* Sign the cert */ if (!X509_sign(cer, pk, EVP_md5())) { syslog(LOG_WARNING, "X509_sign(): error\n"); } else { /* Write it to disk. */ fp = fopen(CTDL_CER_PATH, "w"); if (fp != NULL) { chmod(CTDL_CER_PATH, 0600); PEM_write_X509(fp, cer); fclose(fp); } else { syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_CER_PATH); ShutDownWebcit(); exit(0); } } X509_free(cer); } } RSA_free(rsa); } } /* * Now try to bind to the key and certificate. * Note that we use SSL_CTX_use_certificate_chain_file() which allows * the certificate file to contain intermediate certificates. */ SSL_CTX_use_certificate_chain_file(ssl_ctx, CTDL_CER_PATH); SSL_CTX_use_PrivateKey_file(ssl_ctx, CTDL_KEY_PATH, SSL_FILETYPE_PEM); if ( !SSL_CTX_check_private_key(ssl_ctx) ) { syslog(LOG_WARNING, "Cannot install certificate: %s\n", ERR_reason_error_string(ERR_get_error())); } }
int x509_main(int argc, char **argv) { ASN1_INTEGER *sno = NULL; ASN1_OBJECT *objtmp; BIO *out = NULL; CONF *extconf = NULL; EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; STACK_OF(OPENSSL_STRING) *sigopts = NULL; X509 *x = NULL, *xca = NULL; X509_REQ *req = NULL, *rq = NULL; X509_STORE *ctx = NULL; const EVP_MD *digest = NULL; char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL; char *checkhost = NULL, *checkemail = NULL, *checkip = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; char buf[256], *prog; int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0; int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM; int fingerprint = 0, reqfile = 0, need_rand = 0, checkend = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0; int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0; int checkoffset = 0, enddate = 0; unsigned long nmflag = 0, certflag = 0; OPTION_CHOICE o; ENGINE *e = NULL; #ifndef OPENSSL_NO_MD5 int subject_hash_old = 0, issuer_hash_old = 0; #endif ctx = X509_STORE_new(); if (ctx == NULL) goto end; X509_STORE_set_verify_cb(ctx, callb); prog = opt_init(argc, argv, x509_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(x509_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) goto opthelp; break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) goto opthelp; break; case OPT_CAFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat)) goto opthelp; break; case OPT_CAKEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAkeyformat)) goto opthelp; break; case OPT_OUT: outfile = opt_arg(); break; case OPT_REQ: reqfile = need_rand = 1; break; case OPT_SIGOPT: if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto opthelp; break; #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL case OPT_FORCE_VERSION: force_version = atoi(opt_arg()) - 1; break; #endif case OPT_DAYS: days = atoi(opt_arg()); break; case OPT_PASSIN: passinarg = opt_arg(); break; case OPT_EXTFILE: extfile = opt_arg(); break; case OPT_EXTENSIONS: extsect = opt_arg(); break; case OPT_SIGNKEY: keyfile = opt_arg(); sign_flag = ++num; need_rand = 1; break; case OPT_CA: CAfile = opt_arg(); CA_flag = ++num; need_rand = 1; break; case OPT_CAKEY: CAkeyfile = opt_arg(); break; case OPT_CASERIAL: CAserial = opt_arg(); break; case OPT_SET_SERIAL: if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) goto opthelp; break; case OPT_FORCE_PUBKEY: fkeyfile = opt_arg(); break; case OPT_ADDTRUST: if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { BIO_printf(bio_err, "%s: Invalid trust object value %s\n", prog, opt_arg()); goto opthelp; } if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) goto end; sk_ASN1_OBJECT_push(trust, objtmp); trustout = 1; break; case OPT_ADDREJECT: if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { BIO_printf(bio_err, "%s: Invalid reject object value %s\n", prog, opt_arg()); goto opthelp; } if (reject == NULL && (reject = sk_ASN1_OBJECT_new_null()) == NULL) goto end; sk_ASN1_OBJECT_push(reject, objtmp); trustout = 1; break; case OPT_SETALIAS: alias = opt_arg(); trustout = 1; break; case OPT_CERTOPT: if (!set_cert_ex(&certflag, opt_arg())) goto opthelp; break; case OPT_NAMEOPT: if (!set_name_ex(&nmflag, opt_arg())) goto opthelp; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; case OPT_C: C = ++num; break; case OPT_EMAIL: email = ++num; break; case OPT_OCSP_URI: ocsp_uri = ++num; break; case OPT_SERIAL: serial = ++num; break; case OPT_NEXT_SERIAL: next_serial = ++num; break; case OPT_MODULUS: modulus = ++num; break; case OPT_PUBKEY: pubkey = ++num; break; case OPT_X509TOREQ: x509req = ++num; break; case OPT_TEXT: text = ++num; break; case OPT_SUBJECT: subject = ++num; break; case OPT_ISSUER: issuer = ++num; break; case OPT_FINGERPRINT: fingerprint = ++num; break; case OPT_HASH: subject_hash = ++num; break; case OPT_ISSUER_HASH: issuer_hash = ++num; break; case OPT_PURPOSE: pprint = ++num; break; case OPT_STARTDATE: startdate = ++num; break; case OPT_ENDDATE: enddate = ++num; break; case OPT_NOOUT: noout = ++num; break; case OPT_NOCERT: nocert = 1; break; case OPT_TRUSTOUT: trustout = 1; break; case OPT_CLRTRUST: clrtrust = ++num; break; case OPT_CLRREJECT: clrreject = ++num; break; case OPT_ALIAS: aliasout = ++num; break; case OPT_CACREATESERIAL: CA_createserial = ++num; break; case OPT_CLREXT: clrext = 1; break; case OPT_OCSPID: ocspid = ++num; break; case OPT_BADSIG: badsig = 1; break; #ifndef OPENSSL_NO_MD5 case OPT_SUBJECT_HASH_OLD: subject_hash_old = ++num; break; case OPT_ISSUER_HASH_OLD: issuer_hash_old = ++num; break; #endif case OPT_DATES: startdate = ++num; enddate = ++num; break; case OPT_CHECKEND: checkoffset = atoi(opt_arg()); checkend = 1; break; case OPT_CHECKHOST: checkhost = opt_arg(); break; case OPT_CHECKEMAIL: checkemail = opt_arg(); break; case OPT_CHECKIP: checkip = opt_arg(); break; case OPT_MD: if (!opt_md(opt_unknown(), &digest)) goto opthelp; } } argc = opt_num_rest(); argv = opt_rest(); if (argc != 0) { BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]); goto opthelp; } out = bio_open_default(outfile, "w"); if (out == NULL) goto end; if (need_rand) app_RAND_load_file(NULL, 0); if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (!X509_STORE_set_default_paths(ctx)) { ERR_print_errors(bio_err); goto end; } if (fkeyfile) { fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key"); if (fkey == NULL) goto end; } if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { CAkeyfile = CAfile; } else if ((CA_flag) && (CAkeyfile == NULL)) { BIO_printf(bio_err, "need to specify a CAkey if using the CA command\n"); goto end; } if (extfile) { long errorline = -1; X509V3_CTX ctx2; extconf = NCONF_new(NULL); if (!NCONF_load(extconf, extfile, &errorline)) { if (errorline <= 0) BIO_printf(bio_err, "error loading the config file '%s'\n", extfile); else BIO_printf(bio_err, "error on line %ld of config file '%s'\n", errorline, extfile); goto end; } if (!extsect) { extsect = NCONF_get_string(extconf, "default", "extensions"); if (!extsect) { ERR_clear_error(); extsect = "default"; } } X509V3_set_ctx_test(&ctx2); X509V3_set_nconf(&ctx2, extconf); if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { BIO_printf(bio_err, "Error Loading extension section %s\n", extsect); ERR_print_errors(bio_err); goto end; } } if (reqfile) { EVP_PKEY *pkey; BIO *in; if (!sign_flag && !CA_flag) { BIO_printf(bio_err, "We need a private key to sign with\n"); goto end; } in = bio_open_default(infile, "r"); if (in == NULL) goto end; req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); BIO_free(in); if (req == NULL) { ERR_print_errors(bio_err); goto end; } if ((req->req_info == NULL) || (req->req_info->pubkey == NULL) || (req->req_info->pubkey->public_key == NULL) || (req->req_info->pubkey->public_key->data == NULL)) { BIO_printf(bio_err, "The certificate request appears to corrupted\n"); BIO_printf(bio_err, "It does not contain a public key\n"); goto end; } if ((pkey = X509_REQ_get_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); goto end; } i = X509_REQ_verify(req, pkey); EVP_PKEY_free(pkey); if (i < 0) { BIO_printf(bio_err, "Signature verification error\n"); ERR_print_errors(bio_err); goto end; } if (i == 0) { BIO_printf(bio_err, "Signature did not match the certificate request\n"); goto end; } else BIO_printf(bio_err, "Signature ok\n"); print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag); if ((x = X509_new()) == NULL) goto end; if (sno == NULL) { sno = ASN1_INTEGER_new(); if (!sno || !rand_serial(NULL, sno)) goto end; if (!X509_set_serialNumber(x, sno)) goto end; ASN1_INTEGER_free(sno); sno = NULL; } else if (!X509_set_serialNumber(x, sno)) goto end; if (!X509_set_issuer_name(x, req->req_info->subject)) goto end; if (!X509_set_subject_name(x, req->req_info->subject)) goto end; X509_gmtime_adj(X509_get_notBefore(x), 0); X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL); if (fkey) X509_set_pubkey(x, fkey); else { pkey = X509_REQ_get_pubkey(req); X509_set_pubkey(x, pkey); EVP_PKEY_free(pkey); } } else x = load_cert(infile, informat, NULL, e, "Certificate"); if (x == NULL) goto end; if (CA_flag) { xca = load_cert(CAfile, CAformat, NULL, e, "CA Certificate"); if (xca == NULL) goto end; } if (!noout || text || next_serial) { OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); } if (alias) X509_alias_set1(x, (unsigned char *)alias, -1); if (clrtrust) X509_trust_clear(x); if (clrreject) X509_reject_clear(x); if (trust) { for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { objtmp = sk_ASN1_OBJECT_value(trust, i); X509_add1_trust_object(x, objtmp); } } if (reject) { for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { objtmp = sk_ASN1_OBJECT_value(reject, i); X509_add1_reject_object(x, objtmp); } } if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { print_name(out, "issuer= ", X509_get_issuer_name(x), nmflag); } else if (subject == i) { print_name(out, "subject= ", X509_get_subject_name(x), nmflag); } else if (serial == i) { BIO_printf(out, "serial="); i2a_ASN1_INTEGER(out, X509_get_serialNumber(x)); BIO_printf(out, "\n"); } else if (next_serial == i) { BIGNUM *bnser; ASN1_INTEGER *ser; ser = X509_get_serialNumber(x); bnser = ASN1_INTEGER_to_BN(ser, NULL); if (!bnser) goto end; if (!BN_add_word(bnser, 1)) goto end; ser = BN_to_ASN1_INTEGER(bnser, NULL); if (!ser) goto end; BN_free(bnser); i2a_ASN1_INTEGER(out, ser); ASN1_INTEGER_free(ser); BIO_puts(out, "\n"); } else if ((email == i) || (ocsp_uri == i)) { int j; STACK_OF(OPENSSL_STRING) *emlst; if (email == i) emlst = X509_get1_email(x); else emlst = X509_get1_ocsp(x); for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) BIO_printf(out, "%s\n", sk_OPENSSL_STRING_value(emlst, j)); X509_email_free(emlst); } else if (aliasout == i) { unsigned char *alstr; alstr = X509_alias_get0(x, NULL); if (alstr) BIO_printf(out, "%s\n", alstr); else BIO_puts(out, "<No Alias>\n"); } else if (subject_hash == i) { BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (subject_hash_old == i) { BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); } #endif else if (issuer_hash == i) { BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (issuer_hash_old == i) { BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); } #endif else if (pprint == i) { X509_PURPOSE *ptmp; int j; BIO_printf(out, "Certificate purposes:\n"); for (j = 0; j < X509_PURPOSE_get_count(); j++) { ptmp = X509_PURPOSE_get0(j); purpose_print(out, x, ptmp); } } else if (modulus == i) { EVP_PKEY *pkey; pkey = X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err, "Modulus=unavailable\n"); ERR_print_errors(bio_err); goto end; } BIO_printf(out, "Modulus="); #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) BN_print(out, pkey->pkey.rsa->n); else #endif #ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) BN_print(out, pkey->pkey.dsa->pub_key); else #endif BIO_printf(out, "Wrong Algorithm type"); BIO_printf(out, "\n"); EVP_PKEY_free(pkey); } else if (pubkey == i) { EVP_PKEY *pkey; pkey = X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err, "Error getting public key\n"); ERR_print_errors(bio_err); goto end; } PEM_write_bio_PUBKEY(out, pkey); EVP_PKEY_free(pkey); } else if (C == i) { unsigned char *d; char *m; int len; X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf); BIO_printf(out, "/*\n" " * Subject: %s\n", buf); m = X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf); BIO_printf(out, " * Issuer: %s\n" " */\n", buf); len = i2d_X509(x, NULL); m = app_malloc(len, "x509 name buffer"); d = (unsigned char *)m; len = i2d_X509_NAME(X509_get_subject_name(x), &d); print_array(out, "the_subject_name", len, (unsigned char *)m); d = (unsigned char *)m; len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); print_array(out, "the_public_key", len, (unsigned char *)m); d = (unsigned char *)m; len = i2d_X509(x, &d); print_array(out, "the_certificate", len, (unsigned char *)m); OPENSSL_free(m); } else if (text == i) { X509_print_ex(out, x, nmflag, certflag); } else if (startdate == i) { BIO_puts(out, "notBefore="); ASN1_TIME_print(out, X509_get_notBefore(x)); BIO_puts(out, "\n"); } else if (enddate == i) { BIO_puts(out, "notAfter="); ASN1_TIME_print(out, X509_get_notAfter(x)); BIO_puts(out, "\n"); } else if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; const EVP_MD *fdig = digest; if (!fdig) fdig = EVP_sha1(); if (!X509_digest(x, fdig, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(fdig))); for (j = 0; j < (int)n; j++) { BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } /* should be in the library */ else if ((sign_flag == i) && (x509req == 0)) { BIO_printf(bio_err, "Getting Private key\n"); if (Upkey == NULL) { Upkey = load_key(keyfile, keyformat, 0, passin, e, "Private key"); if (Upkey == NULL) goto end; } assert(need_rand); if (!sign(x, Upkey, days, clrext, digest, extconf, extsect)) goto end; } else if (CA_flag == i) { BIO_printf(bio_err, "Getting CA Private Key\n"); if (CAkeyfile != NULL) { CApkey = load_key(CAkeyfile, CAkeyformat, 0, passin, e, "CA Private Key"); if (CApkey == NULL) goto end; } assert(need_rand); if (!x509_certify(ctx, CAfile, digest, x, xca, CApkey, sigopts, CAserial, CA_createserial, days, clrext, extconf, extsect, sno, reqfile)) goto end; } else if (x509req == i) { EVP_PKEY *pk; BIO_printf(bio_err, "Getting request Private Key\n"); if (keyfile == NULL) { BIO_printf(bio_err, "no request key file specified\n"); goto end; } else { pk = load_key(keyfile, keyformat, 0, passin, e, "request key"); if (pk == NULL) goto end; } BIO_printf(bio_err, "Generating certificate request\n"); rq = X509_to_X509_REQ(x, pk, digest); EVP_PKEY_free(pk); if (rq == NULL) { ERR_print_errors(bio_err); goto end; } if (!noout) { X509_REQ_print(out, rq); PEM_write_bio_X509_REQ(out, rq); } noout = 1; } else if (ocspid == i) { X509_ocspid_print(out, x); } } } if (checkend) { time_t tcheck = time(NULL) + checkoffset; if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) { BIO_printf(out, "Certificate will expire\n"); ret = 1; } else { BIO_printf(out, "Certificate will not expire\n"); ret = 0; } goto end; } print_cert_checks(out, x, checkhost, checkemail, checkip); if (noout || nocert) { ret = 0; goto end; } if (badsig) x->signature->data[x->signature->length - 1] ^= 0x1; if (outformat == FORMAT_ASN1) i = i2d_X509_bio(out, x); else if (outformat == FORMAT_PEM) { if (trustout) i = PEM_write_bio_X509_AUX(out, x); else i = PEM_write_bio_X509(out, x); } else if (outformat == FORMAT_NETSCAPE) { NETSCAPE_X509 nx; ASN1_OCTET_STRING hdr; hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; hdr.length = strlen(NETSCAPE_CERT_HDR); nx.header = &hdr; nx.cert = x; i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx); } else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err, "unable to write certificate\n"); ERR_print_errors(bio_err); goto end; } ret = 0; end: if (need_rand) app_RAND_write_file(NULL); OBJ_cleanup(); NCONF_free(extconf); BIO_free_all(out); X509_STORE_free(ctx); X509_REQ_free(req); X509_free(x); X509_free(xca); EVP_PKEY_free(Upkey); EVP_PKEY_free(CApkey); EVP_PKEY_free(fkey); sk_OPENSSL_STRING_free(sigopts); X509_REQ_free(rq); ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); OPENSSL_free(passin); return (ret); }
int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags, unsigned long cflag) { unsigned long l; int i; const char *neg; X509_REQ_INFO *ri; EVP_PKEY *pkey; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(X509_EXTENSION) *exts; char mlch = ' '; int nmindent = 0; if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { mlch = '\n'; nmindent = 12; } if(nmflags == X509_FLAG_COMPAT) nmindent = 16; ri=x->req_info; if(!(cflag & X509_FLAG_NO_HEADER)) { if (BIO_write(bp,"Certificate Request:\n",21) <= 0) goto err; if (BIO_write(bp," Data:\n",10) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_VERSION)) { neg=(ri->version->type == V_ASN1_NEG_INTEGER)?"-":""; l=0; for (i=0; i<ri->version->length; i++) { l<<=8; l+=ri->version->data[i]; } if(BIO_printf(bp,"%8sVersion: %s%lu (%s0x%lx)\n","",neg,l,neg, l) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_SUBJECT)) { if (BIO_printf(bp," Subject:%c",mlch) <= 0) goto err; if (X509_NAME_print_ex(bp,ri->subject,nmindent, nmflags) < 0) goto err; if (BIO_write(bp,"\n",1) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_PUBKEY)) { if (BIO_write(bp," Subject Public Key Info:\n",33) <= 0) goto err; if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0) goto err; if (i2a_ASN1_OBJECT(bp, ri->pubkey->algor->algorithm) <= 0) goto err; if (BIO_puts(bp, "\n") <= 0) goto err; pkey=X509_REQ_get_pubkey(x); if (pkey == NULL) { BIO_printf(bp,"%12sUnable to load Public Key\n",""); ERR_print_errors(bp); } else #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { BIO_printf(bp,"%12sRSA Public Key: (%d bit)\n","", BN_num_bits(pkey->pkey.rsa->n)); RSA_print(bp,pkey->pkey.rsa,16); } else #endif #ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { BIO_printf(bp,"%12sDSA Public Key:\n",""); DSA_print(bp,pkey->pkey.dsa,16); } else #endif #ifndef OPENSSL_NO_EC if (pkey->type == EVP_PKEY_EC) { BIO_printf(bp, "%12sEC Public Key: \n",""); EC_KEY_print(bp, pkey->pkey.ec, 16); } else #endif BIO_printf(bp,"%12sUnknown Public Key:\n",""); EVP_PKEY_free(pkey); } if(!(cflag & X509_FLAG_NO_ATTRIBUTES)) { /* may not be */ if(BIO_printf(bp,"%8sAttributes:\n","") <= 0) goto err; sk=x->req_info->attributes; if (sk_X509_ATTRIBUTE_num(sk) == 0) { if(BIO_printf(bp,"%12sa0:00\n","") <= 0) goto err; } else { for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) { ASN1_TYPE *at; X509_ATTRIBUTE *a; ASN1_BIT_STRING *bs=NULL; ASN1_TYPE *t; int j,type=0,count=1,ii=0; a=sk_X509_ATTRIBUTE_value(sk,i); if(X509_REQ_extension_nid(OBJ_obj2nid(a->object))) continue; if(BIO_printf(bp,"%12s","") <= 0) goto err; if ((j=i2a_ASN1_OBJECT(bp,a->object)) > 0) { if (a->single) { t=a->value.single; type=t->type; bs=t->value.bit_string; } else { ii=0; count=sk_ASN1_TYPE_num(a->value.set); get_next: at=sk_ASN1_TYPE_value(a->value.set,ii); type=at->type; bs=at->value.asn1_string; } } for (j=25-j; j>0; j--) if (BIO_write(bp," ",1) != 1) goto err; if (BIO_puts(bp,":") <= 0) goto err; if ( (type == V_ASN1_PRINTABLESTRING) || (type == V_ASN1_T61STRING) || (type == V_ASN1_IA5STRING)) { if (BIO_write(bp,(char *)bs->data,bs->length) != bs->length) goto err; BIO_puts(bp,"\n"); } else { BIO_puts(bp,"unable to print attribute\n"); } if (++ii < count) goto get_next; } } } if(!(cflag & X509_FLAG_NO_EXTENSIONS)) { exts = X509_REQ_get_extensions(x); if(exts) { BIO_printf(bp,"%8sRequested Extensions:\n",""); for (i=0; i<sk_X509_EXTENSION_num(exts); i++) { ASN1_OBJECT *obj; X509_EXTENSION *ex; int j; ex=sk_X509_EXTENSION_value(exts, i); if (BIO_printf(bp,"%12s","") <= 0) goto err; obj=X509_EXTENSION_get_object(ex); i2a_ASN1_OBJECT(bp,obj); j=X509_EXTENSION_get_critical(ex); if (BIO_printf(bp,": %s\n",j?"critical":"") <= 0) goto err; if(!X509V3_EXT_print(bp, ex, cflag, 16)) { BIO_printf(bp, "%16s", ""); M_ASN1_OCTET_STRING_print(bp,ex->value); } if (BIO_write(bp,"\n",1) <= 0) goto err; } sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } } if(!(cflag & X509_FLAG_NO_SIGDUMP)) { if(!X509_signature_print(bp, x->sig_alg, x->signature)) goto err; } return(1); err: X509err(X509_F_X509_REQ_PRINT_EX,ERR_R_BUF_LIB); return(0); }
/*** parse x509_req object as table @function parse @tparam[opt=true] shortname default will use short object name @treturn table result */ static LUA_FUNCTION(openssl_csr_parse) { X509_REQ *csr = CHECK_OBJECT(1, X509_REQ, "openssl.x509_req"); X509_NAME *subject = X509_REQ_get_subject_name(csr); STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(csr); lua_newtable(L); { const ASN1_BIT_STRING *sig = NULL; const X509_ALGOR *alg = NULL; X509_REQ_get0_signature(csr, &sig, &alg); openssl_push_asn1(L, sig, V_ASN1_BIT_STRING); lua_setfield(L, -2, "signature"); alg = X509_ALGOR_dup((X509_ALGOR *)alg); PUSH_OBJECT(alg, "openssl.x509_algor"); lua_setfield(L, -2, "sig_alg"); } lua_newtable(L); AUXILIAR_SET(L, -1, "version", X509_REQ_get_version(csr), integer); openssl_push_xname_asobject(L, subject); lua_setfield(L, -2, "subject"); if (exts) { lua_pushstring(L, "extensions"); openssl_sk_x509_extension_totable(L, exts); lua_rawset(L, -3); sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } { X509_PUBKEY *xpub = X509_REQ_get_X509_PUBKEY(csr); ASN1_OBJECT *oalg = NULL; int c; EVP_PKEY *pubkey = X509_REQ_get_pubkey(csr); lua_newtable(L); c = X509_REQ_get_attr_count(csr); if (c > 0) { int i; lua_newtable(L); for (i = 0; i < c ; i++) { X509_ATTRIBUTE *attr = X509_REQ_get_attr(csr, i); attr = X509_ATTRIBUTE_dup(attr); PUSH_OBJECT(attr, "openssl.x509_attribute"); lua_rawseti(L, -2, i + 1); } lua_setfield(L, -2, "attributes"); } lua_newtable(L); if (X509_PUBKEY_get0_param(&oalg, NULL, NULL, NULL, xpub)) { openssl_push_asn1object(L, oalg); lua_setfield(L, -2, "algorithm"); } AUXILIAR_SETOBJECT(L, pubkey, "openssl.evp_pkey", -1, "pubkey"); lua_setfield(L, -2, "pubkey"); lua_setfield(L, -2, "req_info"); } return 1; }
int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags, unsigned long cflag) { long l; int i; X509_REQ_INFO *ri; EVP_PKEY *pkey; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(X509_EXTENSION) *exts; char mlch = ' '; int nmindent = 0; if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { mlch = '\n'; nmindent = 12; } if (nmflags == X509_FLAG_COMPAT) nmindent = 16; ri = x->req_info; if (!(cflag & X509_FLAG_NO_HEADER)) { if (BIO_write(bp, "Certificate Request:\n", 21) <= 0) goto err; if (BIO_write(bp, " Data:\n", 10) <= 0) goto err; } if (!(cflag & X509_FLAG_NO_VERSION)) { l = X509_REQ_get_version(x); if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, l) <= 0) goto err; } if (!(cflag & X509_FLAG_NO_SUBJECT)) { if (BIO_printf(bp, " Subject:%c", mlch) <= 0) goto err; if (X509_NAME_print_ex(bp, ri->subject, nmindent, nmflags) < 0) goto err; if (BIO_write(bp, "\n", 1) <= 0) goto err; } if (!(cflag & X509_FLAG_NO_PUBKEY)) { if (BIO_write(bp, " Subject Public Key Info:\n", 33) <= 0) goto err; if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0) goto err; if (i2a_ASN1_OBJECT(bp, ri->pubkey->algor->algorithm) <= 0) goto err; if (BIO_puts(bp, "\n") <= 0) goto err; pkey = X509_REQ_get_pubkey(x); if (pkey == NULL) { BIO_printf(bp, "%12sUnable to load Public Key\n", ""); ERR_print_errors(bp); } else { EVP_PKEY_print_public(bp, pkey, 16, NULL); EVP_PKEY_free(pkey); } } if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) { /* may not be */ if (BIO_printf(bp, "%8sAttributes:\n", "") <= 0) goto err; sk = x->req_info->attributes; if (sk_X509_ATTRIBUTE_num(sk) == 0) { if (BIO_printf(bp, "%12sa0:00\n", "") <= 0) goto err; } else { for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { ASN1_TYPE *at; X509_ATTRIBUTE *a; ASN1_BIT_STRING *bs = NULL; ASN1_OBJECT *aobj; int j, type = 0, count = 1, ii = 0; a = sk_X509_ATTRIBUTE_value(sk, i); aobj = X509_ATTRIBUTE_get0_object(a); if (X509_REQ_extension_nid(OBJ_obj2nid(aobj))) continue; if (BIO_printf(bp, "%12s", "") <= 0) goto err; if ((j = i2a_ASN1_OBJECT(bp, aobj)) > 0) { ii = 0; count = X509_ATTRIBUTE_count(a); get_next: at = X509_ATTRIBUTE_get0_type(a, ii); type = at->type; bs = at->value.asn1_string; } for (j = 25 - j; j > 0; j--) if (BIO_write(bp, " ", 1) != 1) goto err; if (BIO_puts(bp, ":") <= 0) goto err; if ((type == V_ASN1_PRINTABLESTRING) || (type == V_ASN1_T61STRING) || (type == V_ASN1_IA5STRING)) { if (BIO_write(bp, (char *)bs->data, bs->length) != bs->length) goto err; BIO_puts(bp, "\n"); } else { BIO_puts(bp, "unable to print attribute\n"); } if (++ii < count) goto get_next; } } } if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { exts = X509_REQ_get_extensions(x); if (exts) { BIO_printf(bp, "%8sRequested Extensions:\n", ""); for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { ASN1_OBJECT *obj; X509_EXTENSION *ex; int j; ex = sk_X509_EXTENSION_value(exts, i); if (BIO_printf(bp, "%12s", "") <= 0) goto err; obj = X509_EXTENSION_get_object(ex); i2a_ASN1_OBJECT(bp, obj); j = X509_EXTENSION_get_critical(ex); if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0) goto err; if (!X509V3_EXT_print(bp, ex, cflag, 16)) { BIO_printf(bp, "%16s", ""); ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex)); } if (BIO_write(bp, "\n", 1) <= 0) goto err; } sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } } if (!(cflag & X509_FLAG_NO_SIGDUMP)) { if (!X509_signature_print(bp, x->sig_alg, x->signature)) goto err; } return (1); err: X509err(X509_F_X509_REQ_PRINT_EX, ERR_R_BUF_LIB); return (0); }
inline pkey::pkey certificate_request::public_key() const { return pkey::pkey(X509_REQ_get_pubkey(ptr().get())); }
TU_RET TuProtocol::HandleCertRequest( PTU_MEMBERINFO pMemberInfo, uchar *dataBuffer, UINT32 dataLen, uchar **message, UINT32 *msgLen) { TU_RET err = TU_ERROR_CRYPTO_FAILED; tu_member *member; UINT32 hours; char role[MAX_NAME_SIZE]; char memberName[MAX_NAME_SIZE]; UINT32 serialLen; uchar *serialCert; UINT32 CACertLength ; uchar *CACert; uchar *msgPtr; EVP_PKEY *pkey; X509_REQ *req; FILE *fp; pMemberInfo->state = State_App; //Store the data buffer into a temporary file to extract the request if(!(fp = fopen("protofile", "wb"))) { TUTRACE((TUTRACE_ERR, "PROTO: Error opening file for writing Cert Request.\n")); err = TU_ERROR_FILEOPEN; goto EXIT; } fwrite(dataBuffer, 1, dataLen, fp); fclose(fp); if(!(fp = fopen("protofile", "r"))) { TUTRACE((TUTRACE_ERR, "PROTO: Error opening file for reading Cert Request.\n")); err = TU_ERROR_FILEOPEN; goto EXIT; } if(!(req = PEM_read_X509_REQ(fp, NULL, NULL, NULL))) { TUTRACE((TUTRACE_ERR, "PROTO: Error reading Cert Request.\n")); fclose(fp); err = TU_ERROR_FILEREAD; goto EXIT; } fclose(fp); //Amol #if 0 //verify the signature with the key we have stored DEVICE_NAME(pMemberInfo->domainName, pMemberInfo->Name); err = GetPublicKey(DEVICE_NAME_BUF, TU_KEY_SIGN, &pkey); if(TU_SUCCESS != err) { TUTRACE((TUTRACE_ERR, "PROTO: Error getting enrollee's public key.\n")); err = TU_ERROR_FILEOPEN; goto ERR_REQ; } #endif if(!(pkey = X509_REQ_get_pubkey(req))) { ERR_print_errors_fp(stdout); TUTRACE((TUTRACE_ERR, "PROTO: Error extracting public key\n")); err = TU_ERROR_SIGN_VERIFY_FAILURE; goto ERR_PKEY; } if(X509_REQ_verify(req, pkey) != 1) { ERR_print_errors_fp(stdout); TUTRACE((TUTRACE_ERR, "PROTO: Verification failed for Cert Request.\n")); err = TU_ERROR_SIGN_VERIFY_FAILURE; goto ERR_PKEY; } if(pMemberInfo->role == guest) { hours = 24; } else { hours = 365*24; } //Finally, create a certificate err = m_pDomainMgr->SignAndStoreCertRequest(req, pMemberInfo->pDomain, hours, &serialCert, (unsigned long *)&serialLen); if(TU_SUCCESS != err) { TUTRACE((TUTRACE_ERR, "PROTO: Error signing Cert Request.\n")); goto ERR_PKEY; } //We now have the cert. Now serialize the CA cert //Open the CA cert file. The name can be derived from the device name //stored in the oobData name FILE_CERT(pMemberInfo->oobData.name); if(!(fp = fopen(NAME_BUF, "rb"))) { TUTRACE((TUTRACE_ERR, "PROTO: Error opening CA Cert file.\n")); err = TU_ERROR_FILEOPEN; goto ERR_CERT; } //Now check the size of the file fseek(fp, 0, SEEK_END); CACertLength = (UINT32)ftell(fp); if(CACertLength == (UINT32) -1) { TUTRACE((TUTRACE_ERR, "PROTO: Error getting CA Cert length.\n")); fclose(fp); err = TU_ERROR_FILEREAD; goto ERR_CERT; } CACert = (uchar *)calloc(CACertLength , 1); if(!CACert) { TUTRACE((TUTRACE_ERR, "PROTO: Error allocating memory for CA Cert.\n")); fclose(fp); err = TU_ERROR_OUT_OF_MEMORY; goto ERR_CERT; } rewind(fp); if(CACertLength != fread(CACert, 1, CACertLength, fp)) { TUTRACE((TUTRACE_ERR, "PROTO: Error reading CA Cert.\n")); fclose(fp); err = TU_ERROR_FILEREAD; goto ERR_CA; } fclose(fp); //Now construct the certificate chain - we simply lump all certs together //copy the current certificate and its length in the message buffer //Also, allocate space for a message length at the start of the buffer *message = (uchar *)malloc(sizeof(UINT32) + sizeof(serialLen) + serialLen + sizeof(CACertLength) + CACertLength); if(!*message) { TUTRACE((TUTRACE_ERR, "PROTO: Error allocating memory.\n")); err = TU_ERROR_OUT_OF_MEMORY; goto ERR_CA; } //The structure of the message is: MessageLength|CertLen|Cert|CertLen|Cert... //The reason for having an extra message length is to help reassemble fragmented packets *msgLen = sizeof(UINT32) + sizeof(serialLen) + serialLen + sizeof(CACertLength) + CACertLength; msgPtr = *message; memcpy(msgPtr, msgLen, sizeof(UINT32)); msgPtr += sizeof(UINT32); memcpy(msgPtr, &serialLen, sizeof(serialLen)); msgPtr += sizeof(serialLen); memcpy(msgPtr, serialCert, serialLen); msgPtr += serialLen; memcpy(msgPtr, &CACertLength, sizeof(CACertLength)); msgPtr += sizeof(CACertLength); memcpy(msgPtr, CACert, CACertLength); //TBD: Add a serial number...get the context, then extract the serial # err = m_pDomainMgr->AddMember(pMemberInfo->Name, pMemberInfo->pDomain, (uchar *)&pMemberInfo->enrolleeAddr, NULL, &member); if(TU_SUCCESS != err) { TUTRACE((TUTRACE_ERR, "PROTO: Error Adding member.\n")); free(*message); } else { //Finally, notify the UI of the new member pUpdateCB(pMemberInfo->Name, pMemberInfo->pDomain->Name); err = TU_SUCCESS; } ERR_CA: if(CACert) free(CACert); ERR_CERT: if(serialCert) free(serialCert); ERR_PKEY: EVP_PKEY_free(pkey); ERR_REQ: X509_REQ_free(req); EXIT: return err; }//HandleCertRequest
/* Creates an X509 certificate from a certificate request. */ EXPORT int IssueUserCertificate(unsigned char *certbuf, int *certlen, unsigned char *reqbuf, int reqlen) { X509_REQ *req = NULL; EVP_PKEY *cakey = NULL, *rakey = NULL, *usrkey = NULL; X509 *cacert = NULL, *racert = NULL, *usrcert = NULL; X509_NAME *subject = NULL, *issuer = NULL; unsigned char *p = NULL; int ret = OPENSSLCA_NO_ERR, len; if (certbuf == NULL || certlen == NULL || reqbuf == NULL || reqlen == 0) return OPENSSLCA_ERR_ARGS; /* Decode request */ if ((req = X509_REQ_new()) == NULL) { ret = OPENSSLCA_ERR_REQ_NEW; goto err; } p = reqbuf; if (d2i_X509_REQ(&req, &p, reqlen) == NULL) { ret = OPENSSLCA_ERR_REQ_DECODE; goto err; } /* Get public key from request */ if ((usrkey = X509_REQ_get_pubkey(req)) == NULL) { ret = OPENSSLCA_ERR_REQ_GET_PUBKEY; goto err; } if (caIni.verifyRequests) { /* Get RA's public key */ /* TODO: Validate RA certificate */ ret = read_cert(&racert, CA_PATH(caIni.raCertFile)); if (ret != OPENSSLCA_NO_ERR) goto err; if ((rakey = X509_get_pubkey(racert)) == NULL) { ret = OPENSSLCA_ERR_CERT_GET_PUBKEY; goto err; } /* Verify signature on request */ if (X509_REQ_verify(req, rakey) != 1) { ret = OPENSSLCA_ERR_REQ_VERIFY; goto err; } } /* Get CA certificate */ /* TODO: Validate CA certificate */ ret = read_cert(&cacert, CA_PATH(caIni.caCertFile)); if (ret != OPENSSLCA_NO_ERR) goto err; /* Get CA private key */ ret = read_key(&cakey, CA_PATH(caIni.caKeyFile), caIni.caKeyPasswd); if (ret != OPENSSLCA_NO_ERR) goto err; /* Create user certificate */ if ((usrcert = X509_new()) == NULL) return OPENSSLCA_ERR_CERT_NEW; /* Set version and serial number for certificate */ if (X509_set_version(usrcert, 2) != 1) { /* V3 */ ret = OPENSSLCA_ERR_CERT_SET_VERSION; goto err; } if (ASN1_INTEGER_set(X509_get_serialNumber(usrcert), get_serial()) != 1) { ret = OPENSSLCA_ERR_CERT_SET_SERIAL; goto err; } /* Set duration for certificate */ if (X509_gmtime_adj(X509_get_notBefore(usrcert), 0) == NULL) { ret = OPENSSLCA_ERR_CERT_SET_NOTBEFORE; goto err; } if (X509_gmtime_adj(X509_get_notAfter(usrcert), EXPIRE_SECS(caIni.daysTillExpire)) == NULL) { ret = OPENSSLCA_ERR_CERT_SET_NOTAFTER; goto err; } /* Set public key */ if (X509_set_pubkey(usrcert, usrkey) != 1) { ret = OPENSSLCA_ERR_CERT_SET_PUBKEY; goto err; } /* Set subject name */ subject = X509_REQ_get_subject_name(req); if (subject == NULL) { ret = OPENSSLCA_ERR_REQ_GET_SUBJECT; goto err; } if (X509_set_subject_name(usrcert, subject) != 1) { ret = OPENSSLCA_ERR_CERT_SET_SUBJECT; goto err; } /* Set issuer name */ issuer = X509_get_issuer_name(cacert); if (issuer == NULL) { ret = OPENSSLCA_ERR_CERT_GET_ISSUER; goto err; } if (X509_set_issuer_name(usrcert, issuer) != 1) { ret = OPENSSLCA_ERR_CERT_SET_ISSUER; goto err; } /* Add extensions */ ret = add_ext(cacert, usrcert); if (ret != OPENSSLCA_NO_ERR) goto err; /* Sign user certificate with CA's private key */ if (!X509_sign(usrcert, cakey, EVP_sha1())) return OPENSSLCA_ERR_CERT_SIGN; if (caIni.verifyAfterSign) { if (X509_verify(usrcert, cakey) != 1) { ret = OPENSSLCA_ERR_CERT_VERIFY; goto err; } } #ifdef _DEBUG /* Output certificate in DER and PEM format */ { FILE *fp = fopen(DBG_PATH("usrcert.der"), "wb"); if (fp != NULL) { i2d_X509_fp(fp, usrcert); fclose(fp); } fp = fopen(DBG_PATH("usrcert.pem"), "w"); if (fp != NULL) { X509_print_fp(fp, usrcert); PEM_write_X509(fp, usrcert); fclose(fp); } } #endif /* Encode user certificate into DER format */ len = i2d_X509(usrcert, NULL); if (len < 0) { ret = OPENSSLCA_ERR_CERT_ENCODE; goto err; } if (len > *certlen) { ret = OPENSSLCA_ERR_BUF_TOO_SMALL; goto err; } *certlen = len; p = certbuf; i2d_X509(usrcert, &p); if (caIni.addToIndex) add_to_index(usrcert); if (caIni.addToNewCerts) write_cert(usrcert); err: print_err("IssueUserCertificate()", ret); /* Clean up */ if (cacert) X509_free(cacert); if (cakey) EVP_PKEY_free(cakey); if (racert) X509_free(racert); if (rakey) EVP_PKEY_free(rakey); if (req) X509_REQ_free(req); if (usrcert != NULL) X509_free(usrcert); if (usrkey) EVP_PKEY_free(usrkey); return ret; }