/* * Modifies a certificate by deleting extensions and copying the issuer and * AKID from the presigner certificate, if necessary. * Returns 1 on success, 0 otherwise. */ __owur static int ct_x509_cert_fixup(X509 *cert, X509 *presigner) { int preidx, certidx; int pre_akid_ext_is_dup, cert_akid_ext_is_dup; if (presigner == NULL) return 1; preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier, &pre_akid_ext_is_dup); certidx = ct_x509_get_ext(cert, NID_authority_key_identifier, &cert_akid_ext_is_dup); /* An error occurred whilst searching for the extension */ if (preidx < -1 || certidx < -1) return 0; /* Invalid certificate if they contain duplicate extensions */ if (pre_akid_ext_is_dup || cert_akid_ext_is_dup) return 0; /* AKID must be present in both certificate or absent in both */ if (preidx >= 0 && certidx == -1) return 0; if (preidx == -1 && certidx >= 0) return 0; /* Copy issuer name */ if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner))) return 0; if (preidx != -1) { /* Retrieve and copy AKID encoding */ X509_EXTENSION *preext = X509_get_ext(presigner, preidx); X509_EXTENSION *certext = X509_get_ext(cert, certidx); ASN1_OCTET_STRING *preextdata; /* Should never happen */ if (preext == NULL || certext == NULL) return 0; preextdata = X509_EXTENSION_get_data(preext); if (preextdata == NULL || !X509_EXTENSION_set_data(certext, preextdata)) return 0; } return 1; }
void mkcert(X509_REQ* req, const char* rootkey, const char* rootcert, const char* passwd) { RSA* rsa_key = EVP_PKEY_get1_RSA(X509_PUBKEY_get(req->req_info->pubkey)); int key_length = RSA_size(rsa_key); if (key_len != 128) { fprintf(stderr, "CA::key length of req is %d, not long enough\n"); return NULL; } X509* cacert = X509_new(); assert(cacert != NULL); load_cacert(&cacert, rootcert); EVP_PKEY* cakey = EVP_PKEY_new(); load_cakey(&cakey, rootkey, passwd); PEM_write_PrivateKey(stdout, cakey, NULL, NULL, 0, NULL, NULL); PEM_write_PUBKEY(stdout, cakey); X509* x = X509_new(); X509_set_version(x, 3); ASN1_INTEGER_set(X509_get_serialNumber(x), 1024); X509_gmtime_adj(X509_get_notBefore(x), 0); X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * 365); X509_set_pubkey(x, X509_PUBKEY_get(req->req_info->pubkey)); X509_set_subject_name(x, X509_REQ_get_subject_name(req)); X509_set_issuer_name(x, X509_get_subject_name(cacert)); assert(X509_sign(x, cakey, EVP_sha1()) > 0); FILE* f = fopen("usercert.pem", "wb"); PEM_write_X509(f, x); fclose(f); X509_print_fp(stdout, x); PEM_write_X509(stdout, x); X509_free(cacert); EVP_PKEY_free(cakey); }
static X509 * getcert(void) { /* Dummy code to make a quick-and-dirty valid certificate with OpenSSL. Don't copy this code into your own program! It does a number of things in a stupid and insecure way. */ X509 *x509 = NULL; X509_NAME *name = NULL; EVP_PKEY *key = getkey(); int nid; time_t now = time(NULL); tt_assert(key); x509 = X509_new(); tt_assert(x509); tt_assert(0 != X509_set_version(x509, 2)); tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)now)); name = X509_NAME_new(); tt_assert(name); nid = OBJ_txt2nid("commonName"); tt_assert(NID_undef != nid); tt_assert(0 != X509_NAME_add_entry_by_NID( name, nid, MBSTRING_ASC, (unsigned char*)"example.com", -1, -1, 0)); X509_set_subject_name(x509, name); X509_set_issuer_name(x509, name); X509_time_adj(X509_get_notBefore(x509), 0, &now); now += 3600; X509_time_adj(X509_get_notAfter(x509), 0, &now); X509_set_pubkey(x509, key); tt_assert(0 != X509_sign(x509, key, EVP_sha1())); return x509; end: X509_free(x509); return NULL; }
X509 * ssl_update_certificate(X509 *oldcert, EVP_PKEY *pkey, EVP_PKEY *capkey, X509 *cacert) { char name[2][TLS_NAME_SIZE]; X509 *cert = NULL; name[0][0] = name[1][0] = '\0'; if (!X509_NAME_oneline(X509_get_subject_name(oldcert), name[0], sizeof(name[0])) || !X509_NAME_oneline(X509_get_issuer_name(oldcert), name[1], sizeof(name[1]))) goto done; if ((cert = X509_dup(oldcert)) == NULL) goto done; /* Update certificate key and use our CA as the issuer */ X509_set_pubkey(cert, pkey); X509_set_issuer_name(cert, X509_get_subject_name(cacert)); /* Sign with our CA */ if (!X509_sign(cert, capkey, EVP_sha1())) { X509_free(cert); cert = NULL; } #if DEBUG_CERT log_debug("%s: subject %s", __func__, name[0]); log_debug("%s: issuer %s", __func__, name[1]); #if DEBUG > 2 X509_print_fp(stdout, cert); #endif #endif done: if (cert == NULL) ssl_error(__func__, name[0]); return (cert); }
/* self sign */ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, CONF *conf, char *section) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(x); EVP_PKEY_copy_parameters(pktmp,pkey); EVP_PKEY_save_parameters(pktmp,1); EVP_PKEY_free(pktmp); if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err; if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err; /* Lets just make it 12:00am GMT, Jan 1 1970 */ /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */ /* 28 days to be certified */ if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) goto err; if (!X509_set_pubkey(x,pkey)) goto err; if (clrext) { while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); } if (conf) { X509V3_CTX ctx; X509_set_version(x,2); /* version 3 certificate */ X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); X509V3_set_nconf(&ctx, conf); if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err; } if (!X509_sign(x,pkey,digest)) goto err; return 1; err: ERR_print_errors(bio_err); return 0; }
//Self signed X509* generate_x509(EVP_PKEY* pkey) { printf("....Generating Cert....\n"); X509 * x509; x509 = X509_new(); // Set serial no to 1 for now ASN1_INTEGER_set(X509_get_serialNumber(x509), 1); // Set validity X509_gmtime_adj(X509_get_notBefore(x509), 0); X509_gmtime_adj(X509_get_notAfter(x509), 3153600L); // Set pubkey X509_set_pubkey(x509, pkey); X509_NAME *name; name = X509_get_subject_name(x509); // Country X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*)"IE", -1, -1, 0); // Company/Organization X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*)"MyCompany Inc.", -1, -1, 0); // Common Name X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)"localhost", -1, -1, 0); // Set issuer name X509_set_issuer_name(x509, name); // Self-signed for now X509_sign(x509, pkey, EVP_sha1()); if(x509 == NULL) { printf("!!!!!!!X509 IS NULL!!!!!!!"); } return x509; }
sqbind::SQINT COsslCert::SetNameField( const sqbind::stdString &sField, const sqbind::stdString &sValue ) {_STT(); if ( !m_pX509 ) return 0; if ( !sField.length() ) return 0; // Get name object X509_NAME *pName = X509_get_subject_name( m_pX509 ); if ( !pName ) return 0; // Set specified field X509_NAME_add_entry_by_txt( pName, sField.c_str(), MBSTRING_ASC, (const unsigned char *)sValue.c_str(), -1, -1, 0 ); // Set issuer name to be the same X509_set_subject_name( m_pX509, pName ); X509_set_issuer_name( m_pX509, pName ); return 1; }
wi_x509_t * wi_x509_init_with_common_name(wi_x509_t *x509, wi_rsa_t *rsa, wi_string_t *common_name) { X509_REQ *req; EVP_PKEY *pkey = NULL; X509_NAME *name = NULL; BIGNUM *bn = NULL; req = X509_REQ_new(); if(!req) goto err; if(X509_REQ_set_version(req, 0) != 1) goto err; name = X509_NAME_new(); if(X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC, (unsigned char *) wi_string_cstring(common_name), -1, -1, 0) != 1) goto err; if(X509_REQ_set_subject_name(req, name) != 1) goto err; pkey = EVP_PKEY_new(); EVP_PKEY_set1_RSA(pkey, wi_rsa_rsa(rsa)); if(X509_REQ_set_pubkey(req, pkey) != 1) goto err; x509->x509 = X509_new(); if(!x509->x509) goto err; bn = BN_new(); if(!bn) goto err; if(BN_pseudo_rand(bn, 64, 0, 0) != 1) goto err; if(!BN_to_ASN1_INTEGER(bn, X509_get_serialNumber(x509->x509))) goto err; if(X509_set_issuer_name(x509->x509, X509_REQ_get_subject_name(req)) != 1) goto err; if(!X509_gmtime_adj(X509_get_notBefore(x509->x509), 0)) goto err; if(!X509_gmtime_adj(X509_get_notAfter(x509->x509), 3600 * 24 * 365)) goto err; if(X509_set_subject_name(x509->x509, X509_REQ_get_subject_name(req)) != 1) goto end; if(X509_set_pubkey(x509->x509, pkey) != 1) goto err; if(X509_sign(x509->x509, pkey, EVP_sha1()) == 0) goto err; goto end; err: wi_error_set_openssl_error(); wi_release(x509); x509 = NULL; end: if(req) X509_REQ_free(req); if(pkey) EVP_PKEY_free(pkey); if(name) X509_NAME_free(name); if(bn) BN_free(bn); return x509; }
static ERL_NIF_TERM x509_make_cert_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int expiry, serial; ASN1_INTEGER *asn1serial = NULL; BIGNUM *bn_rsa_genkey=NULL; BIO *bio_signing_private=NULL, *bio_issuer_cert = NULL, *bio_newcert_public = NULL; BIO *bio_x509=NULL; char *issuer_cert_pem=NULL; X509 *pX509 = NULL; X509 *pIssuerX509 = NULL; X509_NAME *pX509Name = NULL; X509_NAME *pIssuerName = NULL; x509_subject_entry *subject_entries; int num_subject_entries; int iret = 0; RSA *rsa=NULL; unsigned long f4=RSA_F4; unsigned args_len=-1; char *signing_keys[2], *cert_keys[2]; ERL_NIF_TERM tail, *arg_terms=NULL; int idx; ERL_NIF_TERM ret, x509term; int x509len; unsigned char *x509data; EVP_PKEY *evp_signing_private = EVP_PKEY_new(); EVP_PKEY *evp_newcert_public_key = EVP_PKEY_new(); /* set RSA key gen type */ bn_rsa_genkey = BN_new(); BN_set_word(bn_rsa_genkey, f4); // // 1. stick subject of CA cert into NewCert // 2. stick public key of NewKeypair into NewCert // 3. sign NewCert with CA keypair /* Should be 6 elements in the list of X509 parameters. We'll check each */ if(!enif_get_list_length(env, argv[0], &args_len) || args_len != 6 || NULL == (arg_terms = (ERL_NIF_TERM*)malloc(args_len * sizeof(ERL_NIF_TERM)))) return enif_make_badarg(env); enif_get_list_cell(env, argv[0], &arg_terms[0], &tail); for(idx=1; idx<args_len; idx++){ if(!enif_get_list_cell(env, tail, &arg_terms[idx], &tail)){ free(arg_terms); return enif_make_badarg(env); } } idx=0; /* get the signing private key */ x509_parse_keypair(env, "signing_key", arg_terms[idx++], signing_keys); /* get the issuer cert */ x509_parse_issuer_cert(env, arg_terms[idx++], &issuer_cert_pem); /* get the soon-to-be cert's public key */ x509_parse_keypair(env, "newcert_public_key", arg_terms[idx++], cert_keys); /* get the subject */ x509_parse_subject(env, arg_terms[idx++], &num_subject_entries, &subject_entries); /* get the serial number */ x509_parse_int_tuple(env, arg_terms[idx++], "serial", &serial); /* get the expiry */ x509_parse_int_tuple(env, arg_terms[idx++], "expiry", &expiry); /* work the OpenSSL cert creation magic */ if ((bio_signing_private = BIO_new_mem_buf(signing_keys[1], -1)) && (rsa = PEM_read_bio_RSAPrivateKey(bio_signing_private, NULL, NULL, NULL)) && (iret = EVP_PKEY_assign_RSA(evp_signing_private, rsa)) && (bio_newcert_public = BIO_new_mem_buf(cert_keys[0], -1)) && (evp_newcert_public_key = PEM_read_bio_PUBKEY(bio_newcert_public, NULL, NULL, NULL)) && (bio_issuer_cert = BIO_new_mem_buf(issuer_cert_pem, -1)) && (pIssuerX509 = PEM_read_bio_X509(bio_issuer_cert, NULL, NULL, NULL)) && (pX509 = X509_new())) { /* if we've managed to generate a key and allocate structure memory, set X509 fields */ asn1serial = ASN1_INTEGER_new(); X509_set_version(pX509, 2); /* cert_helper uses '3' here */ ASN1_INTEGER_set(asn1serial, serial); X509_set_serialNumber(pX509, asn1serial); X509_gmtime_adj(X509_get_notBefore(pX509),0); X509_gmtime_adj(X509_get_notAfter(pX509),(long)60*60*24*expiry); X509_set_pubkey(pX509, evp_newcert_public_key); pX509Name = X509_get_subject_name(pX509); while(--num_subject_entries >= 0){ X509_NAME_add_entry_by_txt(pX509Name, (subject_entries[num_subject_entries]).name, MBSTRING_ASC, (unsigned char*)(subject_entries[num_subject_entries]).value, -1, -1, 0); } pIssuerName = X509_get_issuer_name(pIssuerX509); X509_set_issuer_name(pX509, pIssuerName); X509_sign(pX509, evp_signing_private, digest); bio_x509 = BIO_new(BIO_s_mem()); PEM_write_bio_X509(bio_x509, pX509); x509len = BIO_get_mem_data(bio_x509, &x509data); memcpy(enif_make_new_binary(env, x509len, &x509term), x509data, x509len); ret = enif_make_tuple2(env, atom_x509_cert, x509term); } done: if(arg_terms) free(arg_terms); free_keys(signing_keys); free_keys(cert_keys); free_subject_entries(num_subject_entries, subject_entries); if(pX509) X509_free(pX509); if(pIssuerX509) X509_free(pIssuerX509); if(issuer_cert_pem) free(issuer_cert_pem); if(bio_issuer_cert) { BIO_set_close(bio_issuer_cert, BIO_NOCLOSE); BIO_free_all(bio_issuer_cert); } if(bio_signing_private) { BIO_set_close(bio_signing_private, BIO_NOCLOSE); BIO_free_all(bio_signing_private); } if(bio_newcert_public) { BIO_set_close(bio_newcert_public, BIO_NOCLOSE); BIO_free_all(bio_newcert_public); } if(bio_x509) BIO_free_all(bio_x509); if(asn1serial) ASN1_INTEGER_free(asn1serial); if(bn_rsa_genkey) BN_free(bn_rsa_genkey); if(rsa) RSA_free(rsa); return ret; }
static int autoca_gencert( Operation *op, genargs *args ) { X509_NAME *subj_name, *issuer_name; X509 *subj_cert; struct berval derdn; unsigned char *pp; EVP_PKEY *evpk = NULL; int rc; if ((subj_cert = X509_new()) == NULL) return -1; autoca_dnbv2der( op, args->subjectDN, &derdn ); pp = (unsigned char *)derdn.bv_val; subj_name = d2i_X509_NAME( NULL, (const unsigned char **)&pp, derdn.bv_len ); op->o_tmpfree( derdn.bv_val, op->o_tmpmemctx ); if ( subj_name == NULL ) { fail1: X509_free( subj_cert ); return -1; } rc = autoca_genpkey( args->keybits, &evpk ); if ( rc <= 0 ) { fail2: if ( subj_name ) X509_NAME_free( subj_name ); goto fail1; } /* encode DER in PKCS#8 */ { PKCS8_PRIV_KEY_INFO *p8inf; if (( p8inf = EVP_PKEY2PKCS8( evpk )) == NULL ) goto fail2; args->derpkey.bv_len = i2d_PKCS8_PRIV_KEY_INFO( p8inf, NULL ); args->derpkey.bv_val = op->o_tmpalloc( args->derpkey.bv_len, op->o_tmpmemctx ); pp = (unsigned char *)args->derpkey.bv_val; i2d_PKCS8_PRIV_KEY_INFO( p8inf, &pp ); PKCS8_PRIV_KEY_INFO_free( p8inf ); } args->newpkey = evpk; /* set random serial */ { BIGNUM *bn = BN_new(); if ( bn == NULL ) { fail3: EVP_PKEY_free( evpk ); goto fail2; } if (!BN_pseudo_rand(bn, SERIAL_BITS, 0, 0)) { BN_free( bn ); goto fail3; } if (!BN_to_ASN1_INTEGER(bn, X509_get_serialNumber(subj_cert))) { BN_free( bn ); goto fail3; } BN_free(bn); } if (args->issuer_cert) { issuer_name = X509_get_subject_name(args->issuer_cert); } else { issuer_name = subj_name; args->issuer_cert = subj_cert; args->issuer_pkey = evpk; } if (!X509_set_version(subj_cert, 2) || /* set version to V3 */ !X509_set_issuer_name(subj_cert, issuer_name) || !X509_set_subject_name(subj_cert, subj_name) || !X509_gmtime_adj(X509_get_notBefore(subj_cert), 0) || !X509_time_adj_ex(X509_get_notAfter(subj_cert), args->days, 0, NULL) || !X509_set_pubkey(subj_cert, evpk)) { goto fail3; } X509_NAME_free(subj_name); subj_name = NULL; /* set cert extensions */ { X509V3_CTX ctx; X509_EXTENSION *ext; int i; X509V3_set_ctx(&ctx, args->issuer_cert, subj_cert, NULL, NULL, 0); for (i=0; args->cert_exts[i].name; i++) { ext = X509V3_EXT_nconf(NULL, &ctx, args->cert_exts[i].name, args->cert_exts[i].value); if ( ext == NULL ) goto fail3; rc = X509_add_ext(subj_cert, ext, -1); X509_EXTENSION_free(ext); if ( !rc ) goto fail3; } if (args->more_exts) { for (i=0; args->more_exts[i].name; i++) { ext = X509V3_EXT_nconf(NULL, &ctx, args->more_exts[i].name, args->more_exts[i].value); if ( ext == NULL ) goto fail3; rc = X509_add_ext(subj_cert, ext, -1); X509_EXTENSION_free(ext); if ( !rc ) goto fail3; } } } rc = autoca_signcert( subj_cert, args->issuer_pkey ); if ( rc < 0 ) goto fail3; args->dercert.bv_len = i2d_X509( subj_cert, NULL ); args->dercert.bv_val = op->o_tmpalloc( args->dercert.bv_len, op->o_tmpmemctx ); pp = (unsigned char *)args->dercert.bv_val; i2d_X509( subj_cert, &pp ); args->newcert = subj_cert; return 0; }
// Creates a X509 certificate, if rootcert is NULL this creates a root (self-signed) certificate. // Is the name parameter is NULL, the hex value of the hash of the public key will be the subject name. int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, int bits, int days, char* name, enum CERTIFICATE_TYPES certtype, struct util_cert* initialcert) { X509 *x = NULL; X509_EXTENSION *ex = NULL; EVP_PKEY *pk = NULL; RSA *rsa = NULL; X509_NAME *cname=NULL; X509 **x509p = NULL; EVP_PKEY **pkeyp = NULL; char hash[UTIL_HASHSIZE]; char serial[8]; char nameStr[(UTIL_HASHSIZE * 2) + 2]; BIGNUM *oBigNbr; CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); if (initialcert != NULL) { pk = X509_get_pubkey(initialcert->x509); rsa = EVP_PKEY_get1_RSA(initialcert->pkey); if ((x=X509_new()) == NULL) goto err; } else { if ((pkeyp == NULL) || (*pkeyp == NULL)) { if ((pk = EVP_PKEY_new()) == NULL) return 0; } else pk = *pkeyp; if ((x509p == NULL) || (*x509p == NULL)) { if ((x=X509_new()) == NULL) goto err; } else x = *x509p; oBigNbr = BN_new(); rsa = RSA_new(); BN_set_word(oBigNbr, RSA_F4); if (RSA_generate_key_ex(rsa, bits, oBigNbr, NULL) == -1) { RSA_free(rsa); BN_free(oBigNbr); abort(); goto err; } BN_free(oBigNbr); } if (!EVP_PKEY_assign_RSA(pk, rsa)) { RSA_free(rsa); abort(); goto err; } rsa = NULL; util_randomtext(8, serial); X509_set_version(x, 2); ASN1_STRING_set(X509_get_serialNumber(x), serial, 8); X509_gmtime_adj(X509_get_notBefore(x),(long)60*60*24*-2); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_set_pubkey(x, pk); // Set the subject name cname = X509_get_subject_name(x); if (name == NULL) { // Computer the hash of the public key util_sha256((char*)x->cert_info->key->public_key->data, x->cert_info->key->public_key->length, hash); util_tohex(hash, UTIL_HASHSIZE, nameStr); X509_NAME_add_entry_by_txt(cname,"CN", MBSTRING_ASC, (unsigned char*)nameStr, -1, -1, 0); } else { // This function creates and adds the entry, working out the correct string type and performing checks on its length. Normally we'd check the return value for errors... X509_NAME_add_entry_by_txt(cname,"CN", MBSTRING_ASC, (unsigned char*)name, -1, -1, 0); } if (rootcert == NULL) { // Its self signed so set the issuer name to be the same as the subject. X509_set_issuer_name(x,cname); // Add various extensions: standard extensions util_add_ext(x, NID_basic_constraints, "critical,CA:TRUE"); util_add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign"); util_add_ext(x, NID_subject_key_identifier, "hash"); //util_add_ext(x, NID_netscape_cert_type, "sslCA"); //util_add_ext(x, NID_netscape_comment, "example comment extension"); if (!X509_sign(x, pk, EVP_sha256())) goto err; } else { // This is a sub-certificate cname=X509_get_subject_name(rootcert->x509); X509_set_issuer_name(x, cname); // Add usual cert stuff ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, "digitalSignature, keyEncipherment, keyAgreement"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); // Add usages: TLS server, TLS client, Intel(R) AMT Console //ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication, TLS Web Client Authentication, 2.16.840.1.113741.1.2.1, 2.16.840.1.113741.1.2.2"); if (certtype == CERTIFICATE_TLS_SERVER) { // TLS server ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); } else if (certtype == CERTIFICATE_TLS_CLIENT) { // TLS client ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Client Authentication"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); } if (!X509_sign(x, rootcert->pkey, EVP_sha256())) goto err; } cert->x509 = x; cert->pkey = pk; return(1); err: return(0); }
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); }
static int cert_init() { X509 *x509 = NULL; EVP_PKEY *pkey = NULL; BIGNUM *exponent = NULL, *serial_number = NULL; RSA *rsa = NULL; ASN1_INTEGER *asn1_serial_number; X509_NAME *name; struct dtls_cert *new_cert; ilog(LOG_INFO, "Generating new DTLS certificate"); /* objects */ pkey = EVP_PKEY_new(); exponent = BN_new(); rsa = RSA_new(); serial_number = BN_new(); name = X509_NAME_new(); x509 = X509_new(); if (!exponent || !pkey || !rsa || !serial_number || !name || !x509) goto err; /* key */ if (!BN_set_word(exponent, 0x10001)) goto err; if (!RSA_generate_key_ex(rsa, 1024, exponent, NULL)) goto err; if (!EVP_PKEY_assign_RSA(pkey, rsa)) goto err; /* x509 cert */ if (!X509_set_pubkey(x509, pkey)) goto err; /* serial */ if (!BN_pseudo_rand(serial_number, 64, 0, 0)) goto err; asn1_serial_number = X509_get_serialNumber(x509); if (!asn1_serial_number) goto err; if (!BN_to_ASN1_INTEGER(serial_number, asn1_serial_number)) goto err; /* version 1 */ if (!X509_set_version(x509, 0L)) goto err; /* common name */ if (!X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_UTF8, (unsigned char *) "rtpengine", -1, -1, 0)) goto err; if (!X509_set_subject_name(x509, name)) goto err; if (!X509_set_issuer_name(x509, name)) goto err; /* cert lifetime */ if (!X509_gmtime_adj(X509_get_notBefore(x509), -60*60*24)) goto err; if (!X509_gmtime_adj(X509_get_notAfter(x509), CERT_EXPIRY_TIME)) goto err; /* sign it */ if (!X509_sign(x509, pkey, EVP_sha1())) goto err; /* digest */ new_cert = obj_alloc0("dtls_cert", sizeof(*new_cert), cert_free); new_cert->fingerprint.hash_func = &hash_funcs[0]; dtls_fingerprint_hash(&new_cert->fingerprint, x509); new_cert->x509 = x509; new_cert->pkey = pkey; new_cert->expires = time(NULL) + CERT_EXPIRY_TIME; dump_cert(new_cert); /* swap out certs */ rwlock_lock_w(&__dtls_cert_lock); if (__dtls_cert) obj_put(__dtls_cert); __dtls_cert = new_cert; rwlock_unlock_w(&__dtls_cert_lock); /* cleanup */ BN_free(exponent); BN_free(serial_number); X509_NAME_free(name); return 0; err: ilog(LOG_ERROR, "Failed to generate DTLS certificate"); if (pkey) EVP_PKEY_free(pkey); if (exponent) BN_free(exponent); if (rsa) RSA_free(rsa); if (x509) X509_free(x509); if (serial_number) BN_free(serial_number); return -1; }
/* * 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())); } }
static std::string generateCertificate (EVP_PKEY *private_key) { std::shared_ptr <X509> x509; std::shared_ptr <BIO> bio; X509_NAME *name = nullptr; int rc = 0; unsigned long err = 0; BUF_MEM *mem; std::string pem; x509 = std::shared_ptr<X509> (X509_new (), [] (X509 * obj) { X509_free (obj); }); if (x509 == nullptr) { GST_ERROR ("X509 not created"); return pem; } X509_set_version (x509.get(), 2L); ASN1_INTEGER_set (X509_get_serialNumber (x509.get() ), 0); X509_gmtime_adj (X509_get_notBefore (x509.get() ), 0); X509_gmtime_adj (X509_get_notAfter (x509.get() ), 31536000L); /* A year */ X509_set_pubkey (x509.get(), private_key); name = X509_get_subject_name (x509.get() ); X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *) "SE", -1, -1, 0); X509_NAME_add_entry_by_txt (name, "CN", MBSTRING_ASC, (unsigned char *) "Kurento", -1, -1, 0); X509_set_issuer_name (x509.get(), name); name = nullptr; if (!X509_sign (x509.get(), private_key, EVP_sha256 () ) ) { GST_ERROR ("Failed to sign certificate"); return pem; } bio = std::shared_ptr<BIO> (BIO_new (BIO_s_mem () ), [] (BIO * obj) { BIO_free_all (obj); }); if (bio == nullptr) { GST_ERROR ("BIO not created"); return pem; } rc = PEM_write_bio_X509 (bio.get(), x509.get() ); if (rc != 1) { err = ERR_get_error(); GST_ERROR ("PEM_write_bio_X509 failed, error %ld", err); return pem; } BIO_get_mem_ptr (bio.get(), &mem); if (!mem || !mem->data || !mem->length) { err = ERR_get_error(); GST_ERROR ("BIO_get_mem_ptr failed, error %ld", err); return pem; } pem = std::string (mem->data, mem->length); return pem; }
void Server::initializeCert() { QByteArray crt, key, pass; crt = getConf("certificate", QString()).toByteArray(); key = getConf("key", QString()).toByteArray(); pass = getConf("passphrase", QByteArray()).toByteArray(); QList<QSslCertificate> ql; if (! key.isEmpty()) { qskKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(key, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (qskKey.isNull() && ! crt.isEmpty()) { qskKey = QSslKey(crt, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(crt, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (! qskKey.isNull()) { ql << QSslCertificate::fromData(crt); ql << QSslCertificate::fromData(key); for (int i=0;i<ql.size();++i) { const QSslCertificate &c = ql.at(i); if (isKeyForCert(qskKey, c)) { qscCert = c; ql.removeAt(i); } } qlCA = ql; } QString issuer; #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName); if (! issuerNames.isEmpty()) { issuer = issuerNames.first(); } #else issuer = qscCert.issuerInfo(QSslCertificate::CommonName); #endif if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } if (!qscCert.isNull() && issuer == QString::fromUtf8("Murmur Autogenerated Certificate v2") && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) { qscCert = Meta::mp.qscCert; qskKey = Meta::mp.qskKey; } if (qscCert.isNull() || qskKey.isNull()) { if (! key.isEmpty() || ! crt.isEmpty()) { log("Certificate specified, but failed to load."); } qskKey = Meta::mp.qskKey; qscCert = Meta::mp.qscCert; if (qscCert.isNull() || qskKey.isNull()) { log("Generating new server certificate."); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); X509 *x509 = X509_new(); EVP_PKEY *pkey = EVP_PKEY_new(); RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL); EVP_PKEY_assign_RSA(pkey, rsa); X509_set_version(x509, 2); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20); X509_set_pubkey(x509, pkey); X509_NAME *name=X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0); X509_set_issuer_name(x509, name); add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")); add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth")); add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")); add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur")); X509_sign(x509, pkey, EVP_sha1()); crt.resize(i2d_X509(x509, NULL)); unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); qscCert = QSslCertificate(crt, QSsl::Der); if (qscCert.isNull()) log("Certificate generation failed"); key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); if (qskKey.isNull()) log("Key generation failed"); setConf("certificate", qscCert.toPem()); setConf("key", qskKey.toPem()); } } }
/* cr_make_cert generates a server public/private keys * cert : X509 instance * pkey : private key instance * bits : RSA key length * serial : serial number * days : how many days the certificate is valid */ int cr_make_cert(X509 **cert,EVP_PKEY **pkey,int bits,int serial,int days) { X509 *x; EVP_PKEY *pk; RSA *rsa; X509_NAME *name = NULL; if((pkey == NULL) || (*pkey == NULL)) { pk = EVP_PKEY_new(); if(pk == NULL) { perrx("EVP_PKEY_new() failed\n"); return -1; } } else pk = *pkey; if((cert == NULL) || (*cert == NULL)) { x = X509_new(); if ((x == NULL)) { perrx("X509_new() failed\n"); return -1; } }else x= *cert; /* generate RSA key */ rsa = RSA_generate_key(bits,RSA_F4,NULL,NULL); if(!EVP_PKEY_assign_RSA(pk, rsa)) { perrx("X509_new() failed\n"); return -1; } rsa = NULL; X509_set_version(x,2); ASN1_INTEGER_set(X509_get_serialNumber(x),serial); X509_gmtime_adj(X509_get_notBefore(x),0); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_set_pubkey(x,pk); name=X509_get_subject_name(x); X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, (const unsigned char *)"UK", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const unsigned char*)"VPNPivot", -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(x, name); if(!X509_sign(x, pk, EVP_md5())) // secured more with sha1? md5/sha1? sha256? abort(); *cert = x; *pkey = pk; return 1; }
void Server::initializeCert() { QByteArray crt, key, pass, dhparams; crt = getConf("certificate", QString()).toByteArray(); key = getConf("key", QString()).toByteArray(); pass = getConf("passphrase", QByteArray()).toByteArray(); dhparams = getConf("sslDHParams", Meta::mp.qbaDHParams).toByteArray(); QList<QSslCertificate> ql; if (! key.isEmpty()) { qskKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(key, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (qskKey.isNull() && ! crt.isEmpty()) { qskKey = QSslKey(crt, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(crt, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } if (! qskKey.isNull()) { ql << QSslCertificate::fromData(crt); ql << QSslCertificate::fromData(key); for (int i=0;i<ql.size();++i) { const QSslCertificate &c = ql.at(i); if (isKeyForCert(qskKey, c)) { qscCert = c; ql.removeAt(i); } } qlCA = ql; } #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) if (! dhparams.isEmpty()) { QSslDiffieHellmanParameters qdhp = QSslDiffieHellmanParameters(dhparams); if (qdhp.isValid()) { qsdhpDHParams = qdhp; } else { log(QString::fromLatin1("Unable to use specified Diffie-Hellman parameters (sslDHParams): %1").arg(qdhp.errorString())); } } #else if (! dhparams.isEmpty()) { log("Diffie-Hellman parameters (sslDHParams) were specified, but will not be used. This version of Murmur does not support Diffie-Hellman parameters."); } #endif QString issuer; #if QT_VERSION >= 0x050000 QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName); if (! issuerNames.isEmpty()) { issuer = issuerNames.first(); } #else issuer = qscCert.issuerInfo(QSslCertificate::CommonName); #endif if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } if (!qscCert.isNull() && issuer == QString::fromUtf8("Murmur Autogenerated Certificate v2") && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) { qscCert = Meta::mp.qscCert; qskKey = Meta::mp.qskKey; } if (qscCert.isNull() || qskKey.isNull()) { if (! key.isEmpty() || ! crt.isEmpty()) { log("Certificate specified, but failed to load."); } qskKey = Meta::mp.qskKey; qscCert = Meta::mp.qscCert; if (qscCert.isNull() || qskKey.isNull()) { log("Generating new server certificate."); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); X509 *x509 = X509_new(); EVP_PKEY *pkey = EVP_PKEY_new(); RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL); EVP_PKEY_assign_RSA(pkey, rsa); X509_set_version(x509, 2); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20); X509_set_pubkey(x509, pkey); X509_NAME *name=X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0); X509_set_issuer_name(x509, name); add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")); add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth")); add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")); add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur")); X509_sign(x509, pkey, EVP_sha1()); crt.resize(i2d_X509(x509, NULL)); unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); qscCert = QSslCertificate(crt, QSsl::Der); if (qscCert.isNull()) log("Certificate generation failed"); key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); if (qskKey.isNull()) log("Key generation failed"); setConf("certificate", qscCert.toPem()); setConf("key", qskKey.toPem()); } } #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) if (qsdhpDHParams.isEmpty()) { log("Generating new server 2048-bit Diffie-Hellman parameters. This could take a while..."); DH *dh = DH_new(); if (dh == NULL) { qFatal("DH_new failed: unable to generate Diffie-Hellman parameters for virtual server"); } // Generate DH params. // We register a status callback in order to update the UI // for Murmur on Windows. We don't show the actual status, // but we do it to keep Murmur on Windows responsive while // generating the parameters. BN_GENCB cb; memset(&cb, 0, sizeof(BN_GENCB)); BN_GENCB_set(&cb, dh_progress, NULL); if (DH_generate_parameters_ex(dh, 2048, 2, &cb) == 0) { qFatal("DH_generate_parameters_ex failed: unable to generate Diffie-Hellman parameters for virtual server"); } BIO *mem = BIO_new(BIO_s_mem()); if (PEM_write_bio_DHparams(mem, dh) == 0) { qFatal("PEM_write_bio_DHparams failed: unable to write generated Diffie-Hellman parameters to memory"); } char *pem = NULL; long len = BIO_get_mem_data(mem, &pem); if (len <= 0) { qFatal("BIO_get_mem_data returned an empty or invalid buffer"); } QByteArray pemdh(pem, len); QSslDiffieHellmanParameters qdhp(pemdh); if (!qdhp.isValid()) { qFatal("QSslDiffieHellmanParameters: unable to import generated Diffie-HellmanParameters: %s", qdhp.errorString().toStdString().c_str()); } qsdhpDHParams = qdhp; setConf("sslDHParams", pemdh); BIO_free(mem); DH_free(dh); } #endif }
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days) { X509 *x; EVP_PKEY *pk; RSA *rsa; X509_NAME *name=NULL; switch_assert(pkeyp); switch_assert(x509p); if (*pkeyp == NULL) { if ((pk = EVP_PKEY_new()) == NULL) { abort(); } } else { pk = *pkeyp; } if (*x509p == NULL) { if ((x = X509_new()) == NULL) { goto err; } } else { x = *x509p; } rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL); if (!EVP_PKEY_assign_RSA(pk, rsa)) { abort(); goto err; } rsa = NULL; X509_set_version(x, 0); ASN1_INTEGER_set(X509_get_serialNumber(x), serial); X509_gmtime_adj(X509_get_notBefore(x), -(long)60*60*24*7); X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days); X509_set_pubkey(x, pk); name = X509_get_subject_name(x); /* This function creates and adds the entry, working out the * correct string type and performing checks on its length. * Normally we'd check the return value for errors... */ X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"FreeSWITCH", -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(x, name); if (!X509_sign(x, pk, EVP_sha1())) goto err; *x509p = x; *pkeyp = pk; return(1); err: return(0); }
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create, int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno) { int ret=0; ASN1_INTEGER *bs=NULL; X509_STORE_CTX xsc; EVP_PKEY *upkey; upkey = X509_get_pubkey(xca); EVP_PKEY_copy_parameters(upkey,pkey); EVP_PKEY_free(upkey); if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL)) { BIO_printf(bio_err,"Error initialising X509 store\n"); goto end; } if (sno) bs = sno; else if (!(bs = load_serial(CAfile, serialfile, create))) goto end; if (!X509_STORE_add_cert(ctx,x)) goto end; /* NOTE: this certificate can/should be self signed, unless it was * a certificate request in which case it is not. */ X509_STORE_CTX_set_cert(&xsc,x); if (!reqfile && !X509_verify_cert(&xsc)) goto end; if (!X509_check_private_key(xca,pkey)) { BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); goto end; } if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end; if (!X509_set_serialNumber(x,bs)) goto end; if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL) goto end; /* hardwired expired */ if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) goto end; if (clrext) { while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); } if (conf) { X509V3_CTX ctx2; X509_set_version(x,2); /* version 3 certificate */ X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); X509V3_set_nconf(&ctx2, conf); if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end; } if (!X509_sign(x,pkey,digest)) goto end; ret=1; end: X509_STORE_CTX_cleanup(&xsc); if (!ret) ERR_print_errors(bio_err); if (!sno) ASN1_INTEGER_free(bs); return ret; }
LWS_VISIBLE LWS_EXTERN int lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, const char *san_b) { GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null(); GENERAL_NAME *gen = NULL; ASN1_IA5STRING *ia5 = NULL; X509_NAME *name; if (!gens) return 1; vhost->tls.ss = lws_zalloc(sizeof(*vhost->tls.ss), "sni cert"); if (!vhost->tls.ss) { GENERAL_NAMES_free(gens); return 1; } vhost->tls.ss->x509 = X509_new(); if (!vhost->tls.ss->x509) goto bail; ASN1_INTEGER_set(X509_get_serialNumber(vhost->tls.ss->x509), 1); X509_gmtime_adj(X509_get_notBefore(vhost->tls.ss->x509), 0); X509_gmtime_adj(X509_get_notAfter(vhost->tls.ss->x509), 3600); vhost->tls.ss->pkey = EVP_PKEY_new(); if (!vhost->tls.ss->pkey) goto bail0; if (lws_tls_openssl_rsa_new_key(&vhost->tls.ss->rsa, 4096)) goto bail1; if (!EVP_PKEY_assign_RSA(vhost->tls.ss->pkey, vhost->tls.ss->rsa)) goto bail2; X509_set_pubkey(vhost->tls.ss->x509, vhost->tls.ss->pkey); name = X509_get_subject_name(vhost->tls.ss->x509); X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"GB", -1, -1, 0); X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"somecompany", -1, -1, 0); if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_UTF8, (unsigned char *)"temp.acme.invalid", -1, -1, 0) != 1) { lwsl_notice("failed to add CN\n"); goto bail2; } X509_set_issuer_name(vhost->tls.ss->x509, name); /* add the SAN payloads */ gen = GENERAL_NAME_new(); ia5 = ASN1_IA5STRING_new(); if (!ASN1_STRING_set(ia5, san_a, -1)) { lwsl_notice("failed to set ia5\n"); GENERAL_NAME_free(gen); goto bail2; } GENERAL_NAME_set0_value(gen, GEN_DNS, ia5); sk_GENERAL_NAME_push(gens, gen); if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name, gens, 0, X509V3_ADD_APPEND) != 1) goto bail2; GENERAL_NAMES_free(gens); if (san_b && san_b[0]) { gens = sk_GENERAL_NAME_new_null(); gen = GENERAL_NAME_new(); ia5 = ASN1_IA5STRING_new(); if (!ASN1_STRING_set(ia5, san_a, -1)) { lwsl_notice("failed to set ia5\n"); GENERAL_NAME_free(gen); goto bail2; } GENERAL_NAME_set0_value(gen, GEN_DNS, ia5); sk_GENERAL_NAME_push(gens, gen); if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name, gens, 0, X509V3_ADD_APPEND) != 1) goto bail2; GENERAL_NAMES_free(gens); } /* sign it with our private key */ if (!X509_sign(vhost->tls.ss->x509, vhost->tls.ss->pkey, EVP_sha256())) goto bail2; #if 0 {/* useful to take a sample of a working cert for mbedtls to crib */ FILE *fp = fopen("/tmp/acme-temp-cert", "w+"); i2d_X509_fp(fp, vhost->tls.ss->x509); fclose(fp); } #endif /* tell the vhost to use our crafted certificate */ SSL_CTX_use_certificate(vhost->tls.ssl_ctx, vhost->tls.ss->x509); /* and to use our generated private key */ SSL_CTX_use_PrivateKey(vhost->tls.ssl_ctx, vhost->tls.ss->pkey); return 0; bail2: RSA_free(vhost->tls.ss->rsa); bail1: EVP_PKEY_free(vhost->tls.ss->pkey); bail0: X509_free(vhost->tls.ss->x509); bail: lws_free(vhost->tls.ss); GENERAL_NAMES_free(gens); return 1; }
int32_t mkcert(X509 **x509p, EVP_PKEY **pkeyp, int32_t bits, int32_t serial, int32_t days) { bool bCreatedKey = false; bool bCreatedX509 = false; // ----------------- X509 * x = NULL; EVP_PKEY * pk = NULL; RSA * rsa = NULL; X509_NAME * name = NULL; if ((pkeyp == NULL) || (*pkeyp == NULL)) { if ((pk = EVP_PKEY_new()) == NULL) { abort(); // todo //return(0); unneeded after abort. } bCreatedKey = true; } else pk = *pkeyp; // ----------------------------------------- if ((x509p == NULL) || (*x509p == NULL)) { if ((x = X509_new()) == NULL) { if (bCreatedKey) { EVP_PKEY_free(pk); } return(0); } bCreatedX509 = true; } else x = *x509p; // ----------------------------------------- // pRsaKey = RSA_generate_key(1024, 0x010001, NULL, NULL); #ifdef ANDROID rsa = RSA_new(); BIGNUM * e1 = BN_new(); if ((NULL == rsa) || (NULL == e1)) abort(); // todo // BN_set_word(e1, 65537); BN_set_word(e1, RSA_F4); if (!RSA_generate_key_ex(rsa, bits, e1, NULL)) abort(); // todo BN_free(e1); #else rsa = RSA_generate_key(bits, RSA_F4, callback, NULL); #endif // ----------------------------------------- if (!EVP_PKEY_assign_RSA(pk, rsa)) { abort(); // todo //return(0); undeeded after abort. } // ------------------------------ rsa = NULL; X509_set_version(x, 2); ASN1_INTEGER_set(X509_get_serialNumber(x), serial); X509_gmtime_adj (X509_get_notBefore(x), 0); X509_gmtime_adj (X509_get_notAfter (x), static_cast<int64_t>(60*60*24*days)); X509_set_pubkey (x, pk); name = X509_get_subject_name(x); /* This function creates and adds the entry, working out the * correct string type and performing checks on its length. * Normally we'd check the return value for errors... */ X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, (const uint8_t *)"UK", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const uint8_t *)"OpenSSL Group", -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(x, name); // ---------------------------------------------------------------------------- /* Add various extensions: standard extensions */ char * szConstraints = new char[100](); char * szKeyUsage = new char[100](); char * szSubjectKeyID = new char[100](); char * szCertType = new char[100](); char * szComment = new char[100](); // ---------------------------------------------------------------------------- opentxs::OTString::safe_strcpy(szConstraints, "critical,CA:TRUE", 99); opentxs::OTString::safe_strcpy(szKeyUsage, "critical,keyCertSign,cRLSign", 99); opentxs::OTString::safe_strcpy(szSubjectKeyID, "hash", 99); opentxs::OTString::safe_strcpy(szCertType, "sslCA", 99); opentxs::OTString::safe_strcpy(szComment, "example comment extension", 99); // ---------------------------------------------------------------------------- add_ext(x, NID_basic_constraints, szConstraints); add_ext(x, NID_key_usage, szKeyUsage); add_ext(x, NID_subject_key_identifier, szSubjectKeyID); add_ext(x, NID_netscape_cert_type, szCertType); // Some Netscape specific extensions add_ext(x, NID_netscape_comment, szComment); // Some Netscape specific extensions // ---------------------------------------------------------------------------- delete [] szConstraints; szConstraints = NULL; delete [] szKeyUsage; szKeyUsage = NULL; delete [] szSubjectKeyID; szSubjectKeyID = NULL; delete [] szCertType; szCertType = NULL; delete [] szComment; szComment = NULL; // ---------------------------------------------------------------------------- #ifdef CUSTOM_EXT // Maybe even add our own extension based on existing { int32_t nid; nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension"); X509V3_EXT_add_alias(nid, NID_netscape_comment); add_ext(x, nid, "example comment alias"); } #endif // ------------------------------ if (!X509_sign(x, pk, EVP_md5()) || // TODO security: md5 ??? (NULL == x509p) || (NULL == pkeyp)) { // ERROR // if (bCreatedX509) X509_free(x); // NOTE: not sure if x owns pk, in which case pk is already freed above. // Todo: find out and then determine whether or not to uncomment this. // (Presumably this would be a rare occurrence anyway.) // // if (bCreatedKey) // EVP_PKEY_free(pk); x = NULL; pk = NULL; return 0; } // ------------------------------ *x509p = x; *pkeyp = pk; return(1); }
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); }
PKI_X509_CERT * PKI_X509_CERT_new (const PKI_X509_CERT * ca_cert, const PKI_X509_KEYPAIR * kPair, const PKI_X509_REQ * req, const char * subj_s, const char * serial_s, uint64_t validity, const PKI_X509_PROFILE * conf, const PKI_ALGOR * algor, const PKI_CONFIG * oids, HSM *hsm ) { PKI_X509_CERT *ret = NULL; PKI_X509_CERT_VALUE *val = NULL; PKI_X509_NAME *subj = NULL; PKI_X509_NAME *issuer = NULL; PKI_DIGEST_ALG *digest = NULL; PKI_X509_KEYPAIR_VALUE *signingKey = NULL; PKI_TOKEN *tk = NULL; PKI_X509_KEYPAIR_VALUE *certPubKeyVal = NULL; int rv = 0; int ver = 2; int64_t notBeforeVal = 0; ASN1_INTEGER *serial = NULL; char *ver_s = NULL; /* Check if the REQUIRED PKEY has been passed */ if (!kPair || !kPair->value) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return (NULL); }; signingKey = kPair->value; /* TODO: This has to be fixed, to work on every option */ if ( subj_s ) { subj = PKI_X509_NAME_new ( subj_s ); } else if (conf || req) { char *tmp_s = NULL; // Let's use the configuration option first if (conf) { // Get the value of the DN, if present if ((tmp_s = PKI_CONFIG_get_value( conf, "/profile/subject/dn")) != NULL ) { // Builds from the DN in the config subj = PKI_X509_NAME_new(tmp_s); PKI_Free ( tmp_s ); } } // If we still do not have a name, let's check // the request for one if (req && !subj) { const PKI_X509_NAME * req_subj = NULL; // Copy the name from the request if ((req_subj = PKI_X509_REQ_get_data(req, PKI_X509_DATA_SUBJECT)) != NULL) { subj = PKI_X509_NAME_dup(req_subj); } } // If no name is provided, let's use an empty one // TODO: Shall we remove this and fail instead ? if (!subj) subj = PKI_X509_NAME_new( "" ); } else { struct utsname myself; char tmp_name[1024]; if (uname(&myself) < 0) { subj = PKI_X509_NAME_new( "" ); } else { sprintf( tmp_name, "CN=%s", myself.nodename ); subj = PKI_X509_NAME_new( tmp_name ); } } if (!subj) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_SUBJECT, subj_s ); goto err; } if( ca_cert ) { const PKI_X509_NAME *ca_subject = NULL; /* Let's get the ca_cert subject and dup that data */ // ca_subject = (PKI_X509_NAME *) // X509_get_subject_name( (X509 *) ca_cert ); ca_subject = PKI_X509_CERT_get_data( ca_cert, PKI_X509_DATA_SUBJECT ); if( ca_subject ) { issuer = (PKI_X509_NAME *) X509_NAME_dup((X509_NAME *)ca_subject); } else { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_ISSUER, NULL); goto err; } } else { issuer = (PKI_X509_NAME *) X509_NAME_dup((X509_NAME *) subj); } if( !issuer ) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_ISSUER, NULL); goto err; } if(( ret = PKI_X509_CERT_new_null()) == NULL ) { PKI_ERROR(PKI_ERR_OBJECT_CREATE, NULL); goto err; } /* Alloc memory structure for the Certificate */ if((ret->value = ret->cb->create()) == NULL ) { PKI_ERROR(PKI_ERR_OBJECT_CREATE, NULL); return (NULL); } val = ret->value; if(( ver_s = PKI_CONFIG_get_value( conf, "/profile/version")) != NULL ) { ver = atoi( ver_s ) - 1; if ( ver < 0 ) ver = 0; PKI_Free ( ver_s ); } else { ver = 2; }; if (!X509_set_version(val,ver)) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_VERSION, NULL); goto err; } if (serial_s) { char * tmp_s = (char *) serial_s; serial = s2i_ASN1_INTEGER(NULL, tmp_s); } else { // If cacert we assume it is a normal cert - let's create a // random serial number, otherwise - it's a self-signed, use // the usual 'fake' 0 if ( ca_cert ) { unsigned char bytes[11]; RAND_bytes(bytes, sizeof(bytes)); bytes[0] = 0; serial = PKI_INTEGER_new_bin(bytes, sizeof(bytes)); } else { serial = s2i_ASN1_INTEGER( NULL, "0"); }; }; if(!X509_set_serialNumber( val, serial )) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_SERIAL, serial_s); goto err; } /* Set the issuer Name */ // rv = X509_set_issuer_name((X509 *) ret, (X509_NAME *) issuer); if(!X509_set_issuer_name( val, (X509_NAME *) issuer)) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_ISSUER, NULL); goto err; } /* Set the subject Name */ if(!X509_set_subject_name(val, (X509_NAME *) subj)) { PKI_ERROR(PKI_ERR_X509_CERT_CREATE_SUBJECT, NULL); goto err; } /* Set the start date (notBefore) */ if (conf) { int years = 0; int days = 0; int hours = 0; int mins = 0; int secs = 0; char *tmp_s = NULL; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/years")) != NULL ) { years = atoi( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/days")) != NULL ) { days = atoi( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/hours")) != NULL ) { hours = atoi( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/minutes")) != NULL ) { mins = atoi( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/notBefore/seconds")) != NULL ) { secs = atoi( tmp_s ); PKI_Free ( tmp_s ); }; notBeforeVal = secs + ( mins * 60 ) + ( hours * 3600 ) + ( days * 3600 * 24 ) + ( years * 3600 * 24 * 365 ); }; /* Set the validity (notAfter) */ if( conf && validity == 0 ) { long long years = 0; long long days = 0; long long hours = 0; long long mins = 0; long long secs = 0; char *tmp_s = NULL; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/years")) != NULL ) { years = atoll( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/days")) != NULL ) { days = atoll( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/hours")) != NULL ) { hours = atoll( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/minutes")) != NULL ) { mins = atoll( tmp_s ); PKI_Free ( tmp_s ); }; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/validity/minutes")) != NULL ) { secs = atoll( tmp_s ); PKI_Free ( tmp_s ); }; validity = (unsigned long long) secs + (unsigned long long) ( mins * 60 ) + (unsigned long long) ( hours * 3600 ) + (unsigned long long) ( days * 3600 * 24 ) + (unsigned long long) ( years * 3600 * 24 * 365 ); }; if (validity <= 0) validity = 30 * 3600 * 24; #if ( LIBPKI_OS_BITS == LIBPKI_OS32 ) long notBeforeVal32 = (long) notBeforeVal; if (X509_gmtime_adj(X509_get_notBefore(val), notBeforeVal32 ) == NULL) { #else if (X509_gmtime_adj(X509_get_notBefore(val), notBeforeVal ) == NULL) { #endif PKI_ERROR(PKI_ERR_X509_CERT_CREATE_NOTBEFORE, NULL); goto err; } /* Set the end date in a year */ if (X509_gmtime_adj(X509_get_notAfter(val),(long int) validity) == NULL) { PKI_DEBUG("ERROR: can not set notAfter field!"); goto err; } /* Copy the PKEY if it is in the request, otherwise use the public part of the PKI_X509_CERT */ if (req) { certPubKeyVal = (PKI_X509_KEYPAIR_VALUE *) PKI_X509_REQ_get_data(req, PKI_X509_DATA_KEYPAIR_VALUE); if( !certPubKeyVal ) { PKI_DEBUG("ERROR, can not get pubkey from req!"); goto err; } } else { /* Self Signed -- Same Public Key! */ certPubKeyVal = signingKey; } if (!ca_cert && conf) { char *tmp_s = NULL; if(( tmp_s = PKI_X509_PROFILE_get_value( conf, "/profile/keyParams/algorithm")) != NULL ) { PKI_ALGOR *myAlg = NULL; PKI_DIGEST_ALG *dgst = NULL; if((myAlg = PKI_ALGOR_get_by_name( tmp_s )) != NULL ) { if(!algor) algor = myAlg; if((dgst = PKI_ALGOR_get_digest( myAlg )) != NULL ) { PKI_DEBUG("Got Signing Algorithm: %s, %s", PKI_DIGEST_ALG_get_parsed(dgst), PKI_ALGOR_get_parsed(myAlg)); digest = dgst; } else { PKI_DEBUG("Can not parse digest algorithm from %s", tmp_s); } } else { PKI_DEBUG("Can not parse key algorithm from %s", tmp_s); } PKI_Free ( tmp_s ); } } if (conf) { PKI_KEYPARAMS *kParams = NULL; PKI_SCHEME_ID scheme; scheme = PKI_ALGOR_get_scheme( algor ); kParams = PKI_KEYPARAMS_new(scheme, conf); if (kParams) { /* Sets the point compression */ switch ( kParams->scheme ) { #ifdef ENABLE_ECDSA case PKI_SCHEME_ECDSA: if ( (int) kParams->ec.form > 0 ) { # if OPENSSL_VERSION_NUMBER < 0x1010000fL EC_KEY_set_conv_form(certPubKeyVal->pkey.ec, (point_conversion_form_t) kParams->ec.form); # else EC_KEY_set_conv_form(EVP_PKEY_get0_EC_KEY(certPubKeyVal), (point_conversion_form_t) kParams->ec.form); # endif } if ( kParams->ec.asn1flags > -1 ) { # if OPENSSL_VERSION_NUMBER < 0x1010000fL EC_KEY_set_asn1_flag(certPubKeyVal->pkey.ec, kParams->ec.asn1flags ); # else EC_KEY_set_asn1_flag(EVP_PKEY_get0_EC_KEY(certPubKeyVal), kParams->ec.asn1flags ); # endif } break; #endif case PKI_SCHEME_RSA: case PKI_SCHEME_DSA: break; default: // Nothing to do PKI_ERROR(PKI_ERR_GENERAL, "Signing Scheme Uknown %d!", kParams->scheme); break; } } } if (!X509_set_pubkey(val, certPubKeyVal)) { PKI_DEBUG("ERROR, can not set pubkey in cert!"); goto err; } if (conf) { if((tk = PKI_TOKEN_new_null()) == NULL ) { PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL); goto err; } PKI_TOKEN_set_cert(tk, ret); if (ca_cert) { PKI_TOKEN_set_cacert(tk, (PKI_X509_CERT *)ca_cert); } else { PKI_TOKEN_set_cacert(tk, (PKI_X509_CERT *)ret); } if (req) PKI_TOKEN_set_req(tk, (PKI_X509_REQ *)req ); if (kPair) PKI_TOKEN_set_keypair ( tk, (PKI_X509_KEYPAIR *)kPair ); rv = PKI_X509_EXTENSIONS_cert_add_profile(conf, oids, ret, tk); if (rv != PKI_OK) { PKI_DEBUG( "ERROR, can not set extensions!"); tk->cert = NULL; tk->cacert = NULL; tk->req = NULL; tk->keypair = NULL; PKI_TOKEN_free ( tk ); goto err; } // Cleanup for the token (used only to add extensions) tk->cert = NULL; tk->cacert = NULL; tk->req = NULL; tk->keypair = NULL; PKI_TOKEN_free ( tk ); } if (!digest) { if (!algor) { PKI_log_debug("Getting the Digest Algorithm from the CA cert"); // Let's get the Digest Algorithm from the CA Cert if (ca_cert) { if((algor = PKI_X509_CERT_get_data(ca_cert, PKI_X509_DATA_ALGORITHM )) == NULL) { PKI_log_err("Can not retrieve DATA algorithm from CA cert"); } } } // If we have an Algor from either the passed argument or // the CA Certificate, extract the digest from it. Otherwise // get the digest from the signing key if (algor) { if((digest = PKI_ALGOR_get_digest(algor)) == NULL ) { PKI_log_err("Can not get digest from algor"); } } // Check, if still no digest, let's try from the signing Key if (digest == NULL) { if ((digest = PKI_DIGEST_ALG_get_by_key( kPair )) == NULL) { PKI_log_err("Can not infer digest algor from the key pair"); } } } // No Digest Here ? We failed... if (digest == NULL) { PKI_log_err("PKI_X509_CERT_new()::Can not get the digest!"); return( NULL ); } // Sign the data if (PKI_X509_sign(ret, digest, kPair) == PKI_ERR) { PKI_log_err ("Can not sign certificate [%s]", ERR_error_string(ERR_get_error(), NULL )); PKI_X509_CERT_free ( ret ); return NULL; } #if ( OPENSSL_VERSION_NUMBER >= 0x0090900f ) # if OPENSSL_VERSION_NUMBER < 0x1010000fL PKI_X509_CERT_VALUE *cVal = (PKI_X509_CERT_VALUE *) ret->value; if (cVal && cVal->cert_info) { PKI_log_debug("Signature = %s", PKI_ALGOR_get_parsed(cVal->cert_info->signature)); } # endif // PKI_X509_CINF_FULL *cFull = NULL; // cFull = (PKI_X509_CINF_FULL *) cVal->cert_info; // cFull->enc.modified = 1; #endif return ret; err: if (ret) PKI_X509_CERT_free(ret); if (subj) PKI_X509_NAME_free(subj); if (issuer) PKI_X509_NAME_free(issuer); return NULL; } /*! * \brief Signs a PKI_X509_CERT */ int PKI_X509_CERT_sign(PKI_X509_CERT *cert, PKI_X509_KEYPAIR *kp, PKI_DIGEST_ALG *digest) { const PKI_ALGOR *alg = NULL; if( !cert || !cert->value || !kp || !kp->value ) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return PKI_ERR; } if(!digest) { if((alg = PKI_X509_CERT_get_data(cert, PKI_X509_DATA_ALGORITHM))!=NULL) { digest = PKI_ALGOR_get_digest ( alg ); } } if(!digest) { if((digest = PKI_DIGEST_ALG_get_by_key(kp)) == NULL) { PKI_log_err("PKI_X509_CERT_new()::Can not get digest algor " "from key"); return PKI_ERR; } } if( PKI_X509_sign(cert, digest, kp) == PKI_ERR) { PKI_log_err ("PKI_X509_CERT_new()::Can not sign certificate [%s]", ERR_error_string(ERR_get_error(), NULL )); return PKI_ERR; } return PKI_OK; }; /*! * \brief Signs a PKI_X509_CERT by using a configured PKI_TOKEN */ int PKI_X509_CERT_sign_tk ( PKI_X509_CERT *cert, PKI_TOKEN *tk, PKI_DIGEST_ALG *digest) { PKI_X509_KEYPAIR *kp = NULL; if( !cert || !cert->value || !tk ) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return PKI_ERR; }; if( PKI_TOKEN_login( tk ) == PKI_ERR ) { PKI_ERROR(PKI_ERR_HSM_LOGIN, NULL); return PKI_ERR; }; if((kp = PKI_TOKEN_get_keypair( tk )) == NULL ) { return PKI_ERR; }; return PKI_X509_CERT_sign ( cert, kp, digest ); };
DVT_STATUS CERTIFICATE_CLASS::generateFiles(LOG_CLASS* logger_ptr, const char* signerCredentialsFile_ptr, const char* credentialsPassword_ptr, const char* keyPassword_ptr, const char* keyFile_ptr, const char* certificateFile_ptr) // DESCRIPTION : Generate a certificate and key files from this class. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : If signerCredentialsFile_ptr is NULL, a self signed // : certificate will be generated. // : // : Returns: MSG_OK, MSG_LIB_NOT_EXIST, MSG_FILE_NOT_EXIST, // : MSG_ERROR, MSG_INVALID_PASSWORD //<<=========================================================================== { DVT_STATUS ret = MSG_ERROR; unsigned long err; OPENSSL_CLASS* openSsl_ptr; BIO* caBio_ptr = NULL; EVP_PKEY* caPrivateKey_ptr = NULL; X509* caCertificate_ptr = NULL; EVP_PKEY* key_ptr = NULL; X509* cert_ptr = NULL; X509_NAME* name_ptr; time_t effectiveTime; time_t expirationTime; EVP_PKEY* tmpKey_ptr; const EVP_MD *digest_ptr; BIO* pkBio_ptr = NULL; const EVP_CIPHER *cipher_ptr; BIO* certBio_ptr = NULL; // check for the existence of the OpenSSL DLLs openSsl_ptr = OPENSSL_CLASS::getInstance(); if (openSsl_ptr == NULL) { return MSG_LIB_NOT_EXIST; } // clear the error queue ERR_clear_error(); if (signerCredentialsFile_ptr != NULL) { // open the credentials file caBio_ptr = BIO_new(BIO_s_file_internal()); if (caBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to read CA credentials file"); goto end; } if (BIO_read_filename(caBio_ptr, signerCredentialsFile_ptr) <= 0) { err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_SYS) && (ERR_GET_REASON(err) == ERROR_FILE_NOT_FOUND)) { // file does not exist ERR_clear_error(); // eat any errors ret = MSG_FILE_NOT_EXIST; } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening CA credentials file for reading"); } goto end; } // read the certificate authority's private key caPrivateKey_ptr = PEM_read_bio_PrivateKey(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr); if (caPrivateKey_ptr == NULL) { err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_EVP) && (ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT)) { // bad password ERR_clear_error(); // eat any errors ret = MSG_INVALID_PASSWORD; } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading private key from CA credentials file"); } goto end; } // read the certificate authority's certificate caCertificate_ptr = PEM_read_bio_X509(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr); if (caCertificate_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading CA certificate from CA credentials file"); goto end; } } // generate the new private/public key pair if (signatureAlgorithmM.compare("RSA") == 0) { // RSA key RSA* rsa_key; rsa_key = RSA_generate_key(signatureKeyLengthM, RSA_3, NULL, 0); if (rsa_key == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating RSA key"); goto end; } key_ptr = EVP_PKEY_new(); if (key_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating RSA key"); RSA_free(rsa_key); goto end; } EVP_PKEY_assign_RSA(key_ptr, rsa_key); } else { // DSA key DSA* dsa_key; dsa_key = DSA_generate_parameters(signatureKeyLengthM, NULL, 0, NULL, NULL, NULL, 0); if (dsa_key == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating DSA parameters"); goto end; } if (DSA_generate_key(dsa_key) == 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "generating DSA key"); DSA_free(dsa_key); goto end; } key_ptr = EVP_PKEY_new(); if (key_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating DSA key"); DSA_free(dsa_key); goto end; } EVP_PKEY_assign_DSA(key_ptr, dsa_key); } // create the certificate cert_ptr = X509_new(); if (cert_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "creating certificate object"); goto end; } // version if (X509_set_version(cert_ptr, (versionM - 1)) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting certificate version"); goto end; } // subject name_ptr = openSsl_ptr->onelineName2Name(subjectM.c_str()); if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "parsing owner name"); goto end; } if (X509_set_subject_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting owner name in certificate"); goto end; } // issuer if (signerCredentialsFile_ptr != NULL) { // CA signed name_ptr = X509_get_subject_name(caCertificate_ptr); if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "getting name from CA certificate"); goto end; } if (X509_set_issuer_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting issuer name in certificate"); goto end; } } else { // self signed name_ptr = X509_NAME_dup(name_ptr); // duplicate the name so it can be used again if (name_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "duplicating owner name"); goto end; } if (X509_set_issuer_name(cert_ptr, name_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting issuer name in certificate"); goto end; } } // public key if (X509_set_pubkey(cert_ptr, key_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting public key in certificate"); goto end; } // valid dates effectiveTime = mktime(&effectiveDateM); expirationTime = mktime(&expirationDateM); if ((X509_time_adj(X509_get_notBefore(cert_ptr), 0, &effectiveTime) == NULL) || (X509_time_adj(X509_get_notAfter(cert_ptr), 0, &expirationTime) == NULL)) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting valid dates in certificate"); goto end; } // serial number, use the current time_t ASN1_INTEGER_set(X509_get_serialNumber(cert_ptr), (unsigned)time(NULL)); // sign the certificate if (signerCredentialsFile_ptr != NULL) { // CA signed tmpKey_ptr = caPrivateKey_ptr; } else { // self signed tmpKey_ptr = key_ptr; } if (EVP_PKEY_type(tmpKey_ptr->type) == EVP_PKEY_RSA) { digest_ptr = EVP_sha1(); } else if (EVP_PKEY_type(tmpKey_ptr->type) == EVP_PKEY_DSA) { digest_ptr = EVP_dss1(); } else { if (logger_ptr) { logger_ptr->text(LOG_ERROR, 1, "Unsupported key type in CA private key"); } goto end; } if (!X509_sign(cert_ptr, tmpKey_ptr, digest_ptr)) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "signing certificate"); goto end; } // write out the private key // open the private key file pkBio_ptr = BIO_new(BIO_s_file_internal()); if (pkBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to write private key file"); goto end; } if (BIO_write_filename(pkBio_ptr, (void *)keyFile_ptr) <= 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening to write private key file"); goto end; } if ((keyPassword_ptr != NULL) && (strlen(keyPassword_ptr) > 0)) { // we have a password, use 3DES to encrypt the key cipher_ptr = EVP_des_ede3_cbc(); } else { // there is no password, don't encrypt the key cipher_ptr = NULL; } // write out the private key if (PEM_write_bio_PKCS8PrivateKey(pkBio_ptr, key_ptr, cipher_ptr, NULL, 0, NULL, (void *)keyPassword_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing private key"); goto end; } // write the certificate file // open the certificate file certBio_ptr = BIO_new(BIO_s_file_internal()); if (certBio_ptr == NULL) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "setting up to write certificate file"); goto end; } if (BIO_write_filename(certBio_ptr, (void *)certificateFile_ptr) <= 0) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "opening to write certificate file"); goto end; } // write the new certificate if (PEM_write_bio_X509(certBio_ptr, cert_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate"); goto end; } // write the new certificate into the credential file if (PEM_write_bio_X509(pkBio_ptr, cert_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate"); goto end; } if (signerCredentialsFile_ptr != NULL) { // write the CA certificate if (PEM_write_bio_X509(certBio_ptr, caCertificate_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing CA certificate"); goto end; } // loop reading certificates from the CA credentials file and writing them to the certificate file X509_free(caCertificate_ptr); while ((caCertificate_ptr = PEM_read_bio_X509(caBio_ptr, NULL, NULL, (void*)credentialsPassword_ptr)) != NULL) { // write the certificate if (PEM_write_bio_X509(certBio_ptr, caCertificate_ptr) != 1) { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "writing certificate chain"); goto end; } X509_free(caCertificate_ptr); } // check the error err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_PEM) && (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { // end of data - this is normal ERR_clear_error(); } else { openSsl_ptr->printError(logger_ptr, LOG_ERROR, "reading certificates from CA credentials file"); goto end; } } ret = MSG_OK; end: if (certBio_ptr != NULL) BIO_free(certBio_ptr); if (pkBio_ptr != NULL) BIO_free(pkBio_ptr); if (cert_ptr != NULL) X509_free(cert_ptr); if (key_ptr != NULL) EVP_PKEY_free(key_ptr); if (caCertificate_ptr != NULL) X509_free(caCertificate_ptr); if (caPrivateKey_ptr != NULL) EVP_PKEY_free(caPrivateKey_ptr); if (caBio_ptr != NULL) BIO_free(caBio_ptr); return ret; }
int PKI_X509_CERT_set_data(PKI_X509_CERT *x, int type, void *data) { long *aLong = NULL; PKI_TIME *aTime = NULL; PKI_INTEGER *aInt = NULL; PKI_X509_NAME *aName = NULL; PKI_X509_KEYPAIR_VALUE *aKey = NULL; int ret = 0; LIBPKI_X509_CERT *xVal = NULL; LIBPKI_X509_ALGOR *alg = NULL; // PKI_X509_CERT_VALUE *xVal = NULL; if ( !x || !x->value || !data || x->type != PKI_DATATYPE_X509_CERT) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return (PKI_ERR); } // xVal = PKI_X509_get_value( x ); xVal = x->value; switch( type ) { case PKI_X509_DATA_VERSION: aLong = (long *) data; ret = X509_set_version( xVal, *aLong ); break; case PKI_X509_DATA_SERIAL: aInt = (PKI_INTEGER *) data; ret = X509_set_serialNumber( xVal, aInt); break; case PKI_X509_DATA_SUBJECT: aName = (PKI_X509_NAME *) data; ret = X509_set_subject_name( xVal, aName ); break; case PKI_X509_DATA_ISSUER: aName = (PKI_X509_NAME *) data; ret = X509_set_issuer_name( xVal, aName ); break; case PKI_X509_DATA_NOTBEFORE: aTime = (PKI_TIME *) data; ret = X509_set_notBefore( xVal, aTime ); break; case PKI_X509_DATA_NOTAFTER: aTime = (PKI_TIME *) data; ret = X509_set_notAfter( xVal, aTime ); break; case PKI_X509_DATA_KEYPAIR_VALUE: aKey = data; ret = X509_set_pubkey( xVal, aKey); break; case PKI_X509_DATA_ALGORITHM: case PKI_X509_DATA_SIGNATURE_ALG1: alg = data; #if OPENSSL_VERSION_NUMBER < 0x1010000fL if (xVal->cert_info != NULL) xVal->cert_info->signature = alg; #else // Transfer Ownership xVal->cert_info.signature.algorithm = alg->algorithm; xVal->cert_info.signature.parameter = alg->parameter; // Remove the transfered data alg->algorithm = NULL; alg->parameter = NULL; // Free memory X509_ALGOR_free((X509_ALGOR *)data); data = NULL; #endif // Ok ret = 1; break; case PKI_X509_DATA_SIGNATURE_ALG2: // if (xVal->sig_alg != NULL ) X509_ALGOR_free(xVal->sig_alg); alg = data; #if OPENSSL_VERSION_NUMBER < 0x1010000fL xVal->sig_alg = alg; #else // Transfer Ownership xVal->sig_alg.algorithm = alg->algorithm; xVal->sig_alg.parameter = alg->parameter; // Remove the transfered data alg->algorithm = NULL; alg->parameter = NULL; // Free memory X509_ALGOR_free((X509_ALGOR *)alg); data = NULL; // Ok ret = 1; #endif break; default: /* Not Recognized/Supported DATATYPE */ ret = 0; break; } if (!ret) return PKI_ERR; return PKI_OK; }
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days) { X509 *x; EVP_PKEY *pk; RSA *rsa; X509_NAME *name=NULL; if ((pkeyp == NULL) || (*pkeyp == NULL)) { if ((pk=EVP_PKEY_new()) == NULL) { abort(); return(0); } } else pk= *pkeyp; if ((x509p == NULL) || (*x509p == NULL)) { if ((x=X509_new()) == NULL) goto err; } else x= *x509p; if (bits != 0){ rsa=RSA_generate_key(bits,RSA_F4,callback,NULL); if (!EVP_PKEY_assign_RSA(pk,rsa)) { abort(); goto err; } rsa=NULL; } X509_set_version(x,2); ASN1_INTEGER_set(X509_get_serialNumber(x),serial); X509_gmtime_adj(X509_get_notBefore(x),0); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_set_pubkey(x,pk); name=X509_get_subject_name(x); /* This function creates and adds the entry, working out the * correct string type and performing checks on its length. * Normally we'd check the return value for errors... */ X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC,(const unsigned char *) "UK", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const unsigned char *) _cert_cn, -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(x,name); /* Add various extensions: standard extensions */ add_ext(x, NID_basic_constraints, "critical,CA:TRUE"); add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign"); add_ext(x, NID_subject_key_identifier, "hash"); /* Some Netscape specific extensions */ add_ext(x, NID_netscape_cert_type, "sslCA"); add_ext(x, NID_netscape_comment, "example comment extension"); #ifdef CUSTOM_EXT /* Maybe even add our own extension based on existing */ { int nid; nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension"); X509V3_EXT_add_alias(nid, NID_netscape_comment); add_ext(x, nid, "example comment alias"); } #endif if (!X509_sign(x,pk,EVP_sha1())) goto err; *x509p=x; *pkeyp=pk; return(1); err: return(0); }
Try<X509*> generate_x509( EVP_PKEY* subject_key, EVP_PKEY* sign_key, const Option<X509*>& parent_certificate, int serial, int days, Option<std::string> hostname) { Option<X509_NAME*> issuer_name = None(); if (parent_certificate.isNone()) { // If there is no parent certificate, then the subject and // signing key must be the same. if (subject_key != sign_key) { return Error("Subject vs signing key mismatch"); } } else { // If there is a parent certificate, then set the issuer name to // be that of the parent. issuer_name = X509_get_subject_name(parent_certificate.get()); if (issuer_name.get() == NULL) { return Error("Failed to get subject name of parent certificate: " "X509_get_subject_name"); } } // Allocate the in-memory structure for the certificate. X509* x509 = X509_new(); if (x509 == NULL) { return Error("Failed to allocate certification: X509_new"); } // Set the version to V3. if (X509_set_version(x509, 2) != 1) { X509_free(x509); return Error("Failed to set version: X509_set_version"); } // Set the serial number. if (ASN1_INTEGER_set(X509_get_serialNumber(x509), serial) != 1) { X509_free(x509); return Error("Failed to set serial number: ASN1_INTEGER_set"); } // Make this certificate valid for 'days' number of days from now. if (X509_gmtime_adj(X509_get_notBefore(x509), 0) == NULL || X509_gmtime_adj(X509_get_notAfter(x509), 60L * 60L * 24L * days) == NULL) { X509_free(x509); return Error("Failed to set valid days of certificate: X509_gmtime_adj"); } // Set the public key for our certificate based on the subject key. if (X509_set_pubkey(x509, subject_key) != 1) { X509_free(x509); return Error("Failed to set public key: X509_set_pubkey"); } // Figure out our hostname if one was not provided. if (hostname.isNone()) { const Try<std::string> _hostname = net::hostname(); if (_hostname.isError()) { X509_free(x509); return Error("Failed to determine hostname"); } hostname = _hostname.get(); } // Grab the subject name of the new certificate. X509_NAME* name = X509_get_subject_name(x509); if (name == NULL) { X509_free(x509); return Error("Failed to get subject name: X509_get_subject_name"); } // Set the country code, organization, and common name. if (X509_NAME_add_entry_by_txt( name, "C", MBSTRING_ASC, reinterpret_cast<const unsigned char*>("US"), -1, -1, 0) != 1) { X509_free(x509); return Error("Failed to set country code: X509_NAME_add_entry_by_txt"); } if (X509_NAME_add_entry_by_txt( name, "O", MBSTRING_ASC, reinterpret_cast<const unsigned char*>("Test"), -1, -1, 0) != 1) { X509_free(x509); return Error("Failed to set organization name: X509_NAME_add_entry_by_txt"); } if (X509_NAME_add_entry_by_txt( name, "CN", MBSTRING_ASC, reinterpret_cast<const unsigned char*>(hostname.get().c_str()), -1, -1, 0) != 1) { X509_free(x509); return Error("Failed to set common name: X509_NAME_add_entry_by_txt"); } // Set the issuer name to be the same as the subject if it is not // already set (this is a self-signed certificate). if (issuer_name.isNone()) { issuer_name = name; } CHECK_SOME(issuer_name); if (X509_set_issuer_name(x509, issuer_name.get()) != 1) { X509_free(x509); return Error("Failed to set issuer name: X509_set_issuer_name"); } // Sign the certificate with the sign key. if (X509_sign(x509, sign_key, EVP_sha1()) == 0) { X509_free(x509); return Error("Failed to sign certificate: X509_sign"); } return x509; }
void DtlsTransport::GenerateCertificateAndPrivateKey() { MS_TRACE(); int ret = 0; BIGNUM* bne = nullptr; RSA* rsa_key = nullptr; int num_bits = 1024; X509_NAME* cert_name = nullptr; // Create a big number object. bne = BN_new(); if (!bne) { LOG_OPENSSL_ERROR("BN_new() failed"); goto error; } ret = BN_set_word(bne, RSA_F4); // RSA_F4 == 65537. if (ret == 0) { LOG_OPENSSL_ERROR("BN_set_word() failed"); goto error; } // Generate a RSA key. rsa_key = RSA_new(); if (!rsa_key) { LOG_OPENSSL_ERROR("RSA_new() failed"); goto error; } // This takes some time. ret = RSA_generate_key_ex(rsa_key, num_bits, bne, nullptr); if (ret == 0) { LOG_OPENSSL_ERROR("RSA_generate_key_ex() failed"); goto error; } // Create a private key object (needed to hold the RSA key). DtlsTransport::privateKey = EVP_PKEY_new(); if (!DtlsTransport::privateKey) { LOG_OPENSSL_ERROR("EVP_PKEY_new() failed"); goto error; } ret = EVP_PKEY_assign_RSA(DtlsTransport::privateKey, rsa_key); if (ret == 0) { LOG_OPENSSL_ERROR("EVP_PKEY_assign_RSA() failed"); goto error; } // The RSA key now belongs to the private key, so don't clean it up separately. rsa_key = nullptr; // Create the X509 certificate. DtlsTransport::certificate = X509_new(); if (!DtlsTransport::certificate) { LOG_OPENSSL_ERROR("X509_new() failed"); goto error; } // Set version 3 (note that 0 means version 1). X509_set_version(DtlsTransport::certificate, 2); // Set serial number (avoid default 0). ASN1_INTEGER_set(X509_get_serialNumber(DtlsTransport::certificate), (long)Utils::Crypto::GetRandomUInt(1000000, 9999999)); // Set valid period. X509_gmtime_adj(X509_get_notBefore(DtlsTransport::certificate), -1*60*60*24*365*10); // - 10 years. X509_gmtime_adj(X509_get_notAfter(DtlsTransport::certificate), 60*60*24*365*10); // 10 years. // Set the public key for the certificate using the key. ret = X509_set_pubkey(DtlsTransport::certificate, DtlsTransport::privateKey); if (ret == 0) { LOG_OPENSSL_ERROR("X509_set_pubkey() failed"); goto error; } // Set certificate fields. cert_name = X509_get_subject_name(DtlsTransport::certificate); if (!cert_name) { LOG_OPENSSL_ERROR("X509_get_subject_name() failed"); goto error; } X509_NAME_add_entry_by_txt(cert_name, "O", MBSTRING_ASC, (uint8_t*)MS_APP_NAME, -1, -1, 0); X509_NAME_add_entry_by_txt(cert_name, "CN", MBSTRING_ASC, (uint8_t*)MS_APP_NAME, -1, -1, 0); // It is self-signed so set the issuer name to be the same as the subject. ret = X509_set_issuer_name(DtlsTransport::certificate, cert_name); if (ret == 0) { LOG_OPENSSL_ERROR("X509_set_issuer_name() failed"); goto error; } // Sign the certificate with its own private key. ret = X509_sign(DtlsTransport::certificate, DtlsTransport::privateKey, EVP_sha1()); if (ret == 0) { LOG_OPENSSL_ERROR("X509_sign() failed"); goto error; } // Free stuff and return. BN_free(bne); return; error: if (bne) BN_free(bne); if (rsa_key && !DtlsTransport::privateKey) RSA_free(rsa_key); if (DtlsTransport::privateKey) EVP_PKEY_free(DtlsTransport::privateKey); // NOTE: This also frees the RSA key. if (DtlsTransport::certificate) X509_free(DtlsTransport::certificate); MS_THROW_ERROR("DTLS certificate and private key generation failed"); }
/** Generate and sign an X509 certificate with the public key <b>rsa</b>, * signed by the private key <b>rsa_sign</b>. The commonName of the * certificate will be <b>cname</b>; the commonName of the issuer will be * <b>cname_sign</b>. The cert will be valid for <b>cert_lifetime</b> seconds * starting from now. Return a certificate on success, NULL on * failure. */ static X509 * tor_tls_create_certificate(crypto_pk_env_t *rsa, crypto_pk_env_t *rsa_sign, const char *cname, const char *cname_sign, unsigned int cert_lifetime) { time_t start_time, end_time; EVP_PKEY *sign_pkey = NULL, *pkey=NULL; X509 *x509 = NULL; X509_NAME *name = NULL, *name_issuer=NULL; tor_tls_init(); start_time = time(NULL); tor_assert(rsa); tor_assert(cname); tor_assert(rsa_sign); tor_assert(cname_sign); if (!(sign_pkey = _crypto_pk_env_get_evp_pkey(rsa_sign,1))) goto error; if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,0))) goto error; if (!(x509 = X509_new())) goto error; if (!(X509_set_version(x509, 2))) goto error; if (!(ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)start_time))) goto error; if (!(name = tor_x509_name_new(cname))) goto error; if (!(X509_set_subject_name(x509, name))) goto error; if (!(name_issuer = tor_x509_name_new(cname_sign))) goto error; if (!(X509_set_issuer_name(x509, name_issuer))) goto error; if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time)) goto error; end_time = start_time + cert_lifetime; if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time)) goto error; if (!X509_set_pubkey(x509, pkey)) goto error; if (!X509_sign(x509, sign_pkey, EVP_sha1())) goto error; goto done; error: if (x509) { X509_free(x509); x509 = NULL; } done: tls_log_errors(NULL, LOG_WARN, "generating certificate"); if (sign_pkey) EVP_PKEY_free(sign_pkey); if (pkey) EVP_PKEY_free(pkey); if (name) X509_NAME_free(name); if (name_issuer) X509_NAME_free(name_issuer); return x509; }