int EstEID_loadCertInfoEntries(EstEID_Certs *certs, int index) { EstEID_Map cert = certs->certs[index]; CK_SLOT_ID slotID = certs->slotIDs[index]; CK_SESSION_HANDLE session; FAIL_IF(EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))); CK_OBJECT_CLASS objectClass = CKO_CERTIFICATE; CK_ATTRIBUTE searchAttribute = {CKA_CLASS, &objectClass, sizeof(objectClass)}; if (EstEID_CK_failure("C_FindObjectsInit", fl->C_FindObjectsInit(session, &searchAttribute, 1))) return FAILURE; CK_OBJECT_HANDLE objectHandle; CK_ULONG objectCount; if (EstEID_CK_failure("C_FindObjects", fl->C_FindObjects(session, &objectHandle, 1, &objectCount))) return FAILURE; if (objectCount == 0) return SUCCESS; CK_ATTRIBUTE attribute = {CKA_VALUE, NULL_PTR, 0}; if (EstEID_CK_failure("C_GetAttributeValue", fl->C_GetAttributeValue(session, objectHandle, &attribute, 1))) return FAILURE; CK_ULONG certificateLength = attribute.ulValueLen; CK_BYTE_PTR certificate = (CK_BYTE_PTR)malloc(certificateLength); attribute.pValue = certificate; if (EstEID_CK_failure("C_GetAttributeValue", fl->C_GetAttributeValue(session, objectHandle, &attribute, 1))) return FAILURE; EstEID_mapPutNoAlloc(cert, strdup("certificateAsHex"), EstEID_bin2hex((char *)certificate, certificateLength)); const unsigned char *p = certificate; X509 *x509 = d2i_X509(NULL, &p, certificateLength); char *certMD5; certMD5 = EstEID_getCertHash((char*)certificate); FAIL_IF(EstEID_md5_failure(certMD5)); EstEID_mapPutNoAlloc(cert, strdup("certHash"), certMD5); free(certificate); // todo: error handling of all openssl functions EstEID_mapPutNoAlloc(cert, strdup("validTo"), EstEID_ASN1_TIME_toString(X509_get_notAfter(x509))); EstEID_mapPutNoAlloc(cert, strdup("validFrom"), EstEID_ASN1_TIME_toString(X509_get_notBefore(x509))); unsigned long keyUsage; ASN1_BIT_STRING *usage = (ASN1_BIT_STRING *)X509_get_ext_d2i(x509, NID_key_usage, NULL, NULL); if (usage->length > 0) keyUsage = usage->data[0]; ASN1_BIT_STRING_free(usage); if (keyUsage & X509v3_KU_DIGITAL_SIGNATURE) EstEID_mapPut(cert, "usageDigitalSignature", "TRUE"); if (keyUsage & X509v3_KU_NON_REPUDIATION) { EstEID_mapPut(cert, "usageNonRepudiation", "TRUE"); EstEID_mapPut(cert, "keyUsage", "Non-Repudiation"); // for compatibility with older plugin } EstEID_loadCertEntries(cert, "", X509_get_subject_name(x509)); char *certSerialNumber = (char*)malloc(33); snprintf(certSerialNumber, 32, "%lX", ASN1_INTEGER_get(X509_get_serialNumber(x509))); EstEID_mapPutNoAlloc(cert, strdup("certSerialNumber"), certSerialNumber); EstEID_loadCertEntries(cert, "issuer.", X509_get_issuer_name(x509)); BIO *bio = BIO_new(BIO_s_mem()); if (!PEM_write_bio_X509(bio, x509)) printf("Cannot create PEM\n"); char *b; int len = BIO_get_mem_data(bio, &b); char *pem = (char *)malloc(len + 1); strncpy(pem, b, len); pem[len] = 0; BIO_free(bio); EstEID_mapPutNoAlloc(cert, strdup("certificateAsPEM"), pem); FAIL_IF(EstEID_CK_failure("C_CloseSession", fl->C_CloseSession(session))); return SUCCESS; }
/** * Return not before date. */ static int meth_notbefore(lua_State *L) { X509* cert = lsec_checkx509(L, 1); return push_asn1_time(L, X509_get_notBefore(cert)); }
/** 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; }
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 enddate = 0; time_t checkoffset = 0; unsigned long nmflag = 0, certflag = 0; char nmflag_set = 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_ANY, &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; 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: nmflag_set = 1; 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; #else case OPT_SUBJECT_HASH_OLD: case OPT_ISSUER_HASH_OLD: break; #endif case OPT_DATES: startdate = ++num; enddate = ++num; break; case OPT_CHECKEND: checkend = 1; { intmax_t temp = 0; if (!opt_imax(opt_arg(), &temp)) goto opthelp; checkoffset = (time_t)temp; if ((intmax_t)checkoffset != temp) { BIO_printf(bio_err, "%s: checkend time out of range %s\n", prog, opt_arg()); goto opthelp; } } 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; } if (!nmflag_set) nmflag = XN_FLAG_ONELINE; out = bio_open_default(outfile, 'w', outformat); 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) { X509V3_CTX ctx2; if ((extconf = app_load_config(extfile)) == NULL) 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', informat); 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 ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); goto end; } i = X509_REQ_verify(req, 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 == NULL || !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, X509_REQ_get_subject_name(req))) goto end; if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req))) 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_get0_pubkey(req); X509_set_pubkey(x, pkey); } } else x = load_cert(infile, informat, "Certificate"); if (x == NULL) goto end; if (CA_flag) { xca = load_cert(CAfile, CAformat, "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_get0_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 (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { BIGNUM *n; RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL); BN_print(out, n); } else #endif #ifndef OPENSSL_NO_DSA if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) { BIGNUM *dsapub = NULL; DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL); BN_print(out, dsapub); } else #endif { BIO_printf(out, "Wrong Algorithm type"); } BIO_printf(out, "\n"); } else if (pubkey == i) { EVP_PKEY *pkey; pkey = X509_get0_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); } 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); 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) { ASN1_BIT_STRING *signature; unsigned char *s; X509_get0_signature(&signature, NULL, x); s = ASN1_STRING_data(signature); s[ASN1_STRING_length(signature) - 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 { 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); 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); }
extern "C" short VALIDATE_CERTIFICATE_TS(char * users_expiration_time) { short ret; // if (my_pin == PIN_UNDEFINED) // FindMyProcessInfo(); // if (cert_expdate[0] == 0) // return SECMXO_PRIVKEY_FILE_NOT_FOUND; // Check to see if we have the latest server certificates ret=CHECK_CERTIFICATE_TS(); if (ret != SECMXO_NO_ERROR) // LCOV_EXCL_START return ret; // LCOV_EXCL_STOP // When MXOSRVR starts up, it downloads a dummy certificate. if ((users_expiration_time == NULL) || (users_expiration_time[0] == 0) || (0 == strncmp(users_expiration_time, NULL_CERTIFICATE, strlen(NULL_CERTIFICATE)))) { // LCOV_EXCL_START return SECMXO_CERTIFICATE_UPDATED; // LCOV_EXCL_STOP } // If client has an old certificate, request download. if ((0 != strncmp(cert_expdate, users_expiration_time, EXPDATESIZE))) { // LCOV_EXCL_START return SECMXO_CERTIFICATE_UPDATED; // LCOV_EXCL_STOP } // Get "now" in ASN1 format; put in current_time. X509* x509_cert = X509_new(); if ( ! x509_cert) { // LCOV_EXCL_START return SECMXO_INTERNAL_ERROR; // LCOV_EXCL_STOP } X509_gmtime_adj(X509_get_notBefore(x509_cert), 0); ASN1_TIME* asn1_notBefore = X509_get_notBefore(x509_cert); char* asn1_current_time = (char*) asn1_notBefore->data; char current_time[EXPDATESIZE_ALLOC]; strncpy(current_time, asn1_current_time, EXPDATESIZE+3); // 2 for the ZZ & 1 for the NULL X509_free(x509_cert); // Check to see if the certificate expired. if (-1 == strncmp(users_expiration_time, current_time, EXPDATESIZE)) { // Client had the latest timestamp, but it expired. // LCOV_EXCL_START return SECMXO_CERTIFICATE_EXPIRED; // LCOV_EXCL_STOP } return SECMXO_NO_ERROR; }
void SecureServer::generateCertificate(const std::string& publicKey, const std::string& privateKey, const std::string& password, const long& secsValid, const std::vector<std::pair<std::string,std::string> >& x509Entries, const std::string& x509Filename) throw (boost::system::system_error) { std::cerr << "generating certificate" << std::endl; std::unique_ptr<X509,void (*)(X509*)> x509(X509_new(), &X509_free); if(ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), std::time(nullptr)) != 1){ throw_system_error_ssl("Could not set X509 parameters"); } X509_gmtime_adj(X509_get_notBefore(x509.get()), 0); X509_gmtime_adj(X509_get_notAfter(x509.get()), secsValid); std::unique_ptr<EVP_PKEY,void(*)(EVP_PKEY*)> privKey(EVP_PKEY_new(), &EVP_PKEY_free); std::unique_ptr<EVP_PKEY,void(*)(EVP_PKEY*)> pubKey(EVP_PKEY_new(), &EVP_PKEY_free); std::unique_ptr<BIO,void (*)(BIO*)> privateBIO(BIO_new_file(privateKey.c_str(), "r"), &BIO_free_all); if(!privateBIO){ throw_system_error_ssl("Could not open "+privateKey+" for reading"); } pem_password_cb* password_cb(nullptr); void *password_u(nullptr); if(!password.empty()){ password_cb = &pemPasswordCBFromString; password_u = (void*)&password; } std::unique_ptr<RSA,void(*)(RSA*)> rsa(PEM_read_bio_RSAPrivateKey(privateBIO.get(), nullptr, password_cb, password_u),&RSA_free); if(!rsa){ throw_system_error_ssl("Could not read PEM RSA private key from "+privateKey); } std::cerr << "read " << privateKey << std::endl; if(EVP_PKEY_set1_RSA(privKey.get(), rsa.get()) != 1){ throw_system_error_ssl("Could not assign EVP_PKEY from RSA private key"); } std::cerr << "assigned EVP_PKEY" << std::endl; std::unique_ptr<BIO,void (*)(BIO*)> publicBIO(BIO_new_file(publicKey.c_str(), "r"), &BIO_free_all); if(!publicBIO){ throw_system_error_ssl("Could not open "+publicKey+" for reading"); } RSA *ptr = rsa.get(); if(PEM_read_bio_RSAPublicKey(publicBIO.get(),&ptr,nullptr,nullptr) == nullptr){ throw_system_error_ssl("Could not read PEM RSA public key from "+publicKey); } std::cerr << "read " << publicKey << std::endl; if(EVP_PKEY_set1_RSA(pubKey.get(), rsa.get()) != 1){ throw_system_error_ssl("Could not assign EVP_PKEY from RSA public key"); } if(X509_set_pubkey(x509.get(), pubKey.get()) != 1){ throw_system_error_ssl("Could nost assign X509 public key from EVP_PKEY"); } X509_NAME *name = X509_get_subject_name(x509.get()); std::cerr << "got subject name" << std::endl; for(const std::pair<std::string,std::string>& entry : x509Entries){ if(X509_NAME_add_entry_by_txt(name, entry.first.c_str(), MBSTRING_ASC, (const unsigned char*)entry.second.c_str(), entry.second.length(), -1, 0) != 1){ throw_system_error_ssl("Could not add X509 entry /"+entry.first+"/ = \""+entry.second+'"'); } std::cerr << "added entry /" << entry.first << "/ = \"" << entry.second << '"' << std::endl; } if(X509_set_issuer_name(x509.get(),name) != 1){ throw_system_error_ssl("Could not set X509 issuer name"); } std::cerr << "set issuer name" << std::endl; std::unique_ptr<EVP_MD_CTX,void(*)(EVP_MD_CTX*)> mctx(EVP_MD_CTX_create(),&EVP_MD_CTX_destroy); // EVP_PKEY_CTX *pkctx(nullptr); if(EVP_DigestSignInit(mctx.get(),nullptr,EVP_sha256(),nullptr,privKey.get()) != 1){ throw_system_error_ssl("Could not init EVP Digest Sign"); } std::cerr << "initialized EVP MD CTX" << std::endl; if(X509_sign_ctx(x509.get(),mctx.get()) <= 0){ throw_system_error_ssl("Could not sign certificate"); } std::cerr << "signed" << std::endl; std::unique_ptr<BIO,void(*)(BIO*)> x509BIO(BIO_new_file(x509Filename.c_str(),"w"),&BIO_free_all); if(PEM_write_bio_X509(x509BIO.get(),x509.get()) != 1){ throw_system_error_ssl("Could not write X509 certificate"); } std::cerr << "written to " << x509Filename << std::endl; }
SL::Remote_Access_Library::Crypto::CertSaveLocation SL::Remote_Access_Library::Crypto::CreateCertificate(const CertInfo& info) { assert(INTERNAL::Started);//you must ensure proper startup of the encryption library! CryptoKeys cry; CertSaveLocation svloc; SL_RAT_LOG(Utilities::Logging_Levels::INFO_log_level, "Starting to generate a certifiate and private key!"); if (!cry.x509Certificate || !cry.PrivateKey) { SL_RAT_LOG(Utilities::Logging_Levels::ERROR_log_level, "Failed to allocate space for the certificate and private key!"); return svloc; } auto rsa = RSA_generate_key(info.bits, RSA_F4, NULL, NULL); if (!EVP_PKEY_assign_RSA(cry.PrivateKey, rsa)) { SL_RAT_LOG(Utilities::Logging_Levels::ERROR_log_level, "Failed EVP_PKEY_assign_RSA"); return svloc; } X509_set_version(cry.x509Certificate, 2); ASN1_INTEGER_set(X509_get_serialNumber(cry.x509Certificate), info.Serial); X509_gmtime_adj(X509_get_notBefore(cry.x509Certificate), 0); X509_gmtime_adj(X509_get_notAfter(cry.x509Certificate), (long)60 * 60 * 24 * info.DaysValid); X509_set_pubkey(cry.x509Certificate, cry.PrivateKey); auto name = X509_get_subject_name(cry.x509Certificate); /* 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*)info.country.c_str(), -1, -1, 0); X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (const unsigned char*)info.companyname.c_str(), -1, -1, 0); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char*)info.commonname.c_str(), -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(cry.x509Certificate, name); /* Add various extensions: standard extensions */ add_ext(cry.x509Certificate, NID_basic_constraints, (char*)"critical,CA:TRUE"); add_ext(cry.x509Certificate, NID_key_usage, (char*)"critical,keyCertSign,cRLSign"); add_ext(cry.x509Certificate, NID_subject_key_identifier, (char*)"hash"); /* Some Netscape specific extensions */ add_ext(cry.x509Certificate, NID_netscape_cert_type, (char*)"sslCA"); add_ext(cry.x509Certificate, NID_netscape_comment, (char*)"example comment extension"); if (!X509_sign(cry.x509Certificate, cry.PrivateKey, EVP_sha256())) { SL_RAT_LOG(Utilities::Logging_Levels::ERROR_log_level, "Failed to sign the certifiate!"); return svloc; } std::string saveloc = info.savelocation; if (saveloc.back() != '/' && saveloc.back() != '\\') saveloc += '/'; assert(!saveloc.empty()); svloc.Private_Key = saveloc + info.filename + "_private.pem"; cry.priv_keyfile = fopen(svloc.Private_Key.c_str(), "wb"); if(cry.priv_keyfile!=NULL){ SL_RAT_LOG(Utilities::Logging_Levels::ERROR_log_level, "Failed to open the Private Key File '" << svloc.Private_Key << "' for writing!"); svloc.Private_Key = ""; return svloc; } PEM_write_PrivateKey( cry.priv_keyfile, /* write the key to the file we've opened */ cry.PrivateKey, /* our key from earlier */ EVP_des_ede3_cbc(), /* default cipher for encrypting the key on disk */ (unsigned char*)info.password.c_str(), /* passphrase required for decrypting the key on disk */ static_cast<int>(info.password.size()), /* length of the passphrase string */ NULL, /* callback for requesting a password */ NULL /* data to pass to the callback */ ); svloc.Certificate = saveloc + info.filename + "_cert.crt"; cry.certfile = fopen(svloc.Certificate.c_str(), "wb"); if(cry.certfile!=NULL){ SL_RAT_LOG(Utilities::Logging_Levels::ERROR_log_level, "Failed to open the Certificate File '" << svloc.Certificate << "' for writing!"); svloc.Certificate = ""; return svloc; } return svloc; }
ConnectionInitiator::ConnectionInitiator(QObject *parent) : QObject(parent) { this->qSql = DatabaseHandler::getInstance(); // generate self-signed certificate // this bit is inspired by http://stackoverflow.com/questions/256405/programmatically-create-x509-certificate-using-openssl EVP_PKEY* pkey; pkey = EVP_PKEY_new(); RSA* rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL); if (!EVP_PKEY_assign_RSA(pkey, rsa)) { qWarning() << "Unable to generate 2048-bit RSA key"; UnixSignalHandler::termSignalHandler(0); } X509* x509 = X509_new(); ASN1_INTEGER_set(X509_get_serialNumber(x509), 1); X509_gmtime_adj(X509_get_notBefore(x509), -2000); X509_gmtime_adj(X509_get_notAfter(x509), 31536000L); X509_set_pubkey(x509, pkey); X509_NAME * name = X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"BE", -1, -1, 0); X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"FriendsVPN", -1, -1, 0); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"facebookApp", -1, -1, 0); X509_set_issuer_name(x509, name); if (!X509_sign(x509, pkey, EVP_sha1())) { qWarning() << "Error signing certificate"; UnixSignalHandler::termSignalHandler(0); } // get the PEM string for cert and key // cert BIO* bio = BIO_new(BIO_s_mem()); PEM_write_bio_X509(bio, x509); BUF_MEM *bptr; BIO_get_mem_ptr(bio, &bptr); int length = bptr->length; char certBuf[length + 1]; BIO_read(bio, certBuf, length); certBuf[length] = '\0'; BIO_free(bio); // key bio = BIO_new(BIO_s_mem()); PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL); BIO_get_mem_ptr(bio, &bptr); length = bptr->length; char keyBuf[length + 1]; BIO_read(bio, keyBuf, length); keyBuf[length] = '\0'; BIO_free(bio); qDebug() << "Printing local key and certificate"; qDebug() << keyBuf; qDebug() << certBuf; key = QSslKey(keyBuf, QSsl::Rsa, QSsl::Pem); cert = QSslCertificate(certBuf, QSsl::Pem); qSql->pushCert(cert); }
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; 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, "UK", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, "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 */ 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_md5())) goto err; *x509p=x; *pkeyp=pk; return(1); err: return(0); }
int mkit(X509 **x509p,EVP_PKEY **pkeyp, int bits, int serial, int days) { X509 *x; EVP_PKEY *pk; RSA *rsa; X509_NAME *name=NULL; X509_NAME_ENTRY *ne=NULL; X509_EXTENSION *ex=NULL; char hostname[HOST_NAME_MAX]; 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; 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,3); 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, "UK", -1, -1, 0); get_local_host_name(hostname, sizeof(hostname)); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, hostname, -1, -1, 0); X509_set_issuer_name(x,name); if (!X509_sign(x,pk,EVP_md5())) goto err; *x509p=x; *pkeyp=pk; return(1); err: return(0); }
static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, request_rec *r, X509 *xs, char *var) { char *result; BOOL resdup; X509_NAME *xsname; int nid; result = NULL; resdup = TRUE; if (strcEQ(var, "M_VERSION")) { result = apr_psprintf(p, "%lu", X509_get_version(xs)+1); resdup = FALSE; } else if (strcEQ(var, "M_SERIAL")) { result = ssl_var_lookup_ssl_cert_serial(p, xs); } else if (strcEQ(var, "V_START")) { result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notBefore(xs)); } else if (strcEQ(var, "V_END")) { result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notAfter(xs)); } else if (strcEQ(var, "V_REMAIN")) { result = ssl_var_lookup_ssl_cert_remain(p, X509_get_notAfter(xs)); resdup = FALSE; } else if (*var && strcEQ(var+1, "_DN")) { if (*var == 'S') xsname = X509_get_subject_name(xs); else if (*var == 'I') xsname = X509_get_issuer_name(xs); else return NULL; result = ssl_var_lookup_ssl_cert_dn_oneline(p, r, xsname); resdup = FALSE; } else if (strlen(var) > 5 && strcEQn(var+1, "_DN_", 4)) { if (*var == 'S') xsname = X509_get_subject_name(xs); else if (*var == 'I') xsname = X509_get_issuer_name(xs); else return NULL; result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5); resdup = FALSE; } else if (strlen(var) > 4 && strcEQn(var, "SAN_", 4)) { result = ssl_var_lookup_ssl_cert_san(p, xs, var+4); resdup = FALSE; } else if (strcEQ(var, "A_SIG")) { #if MODSSL_USE_OPENSSL_PRE_1_1_API nid = OBJ_obj2nid((ASN1_OBJECT *)(xs->cert_info->signature->algorithm)); #else const ASN1_OBJECT *paobj; X509_ALGOR_get0(&paobj, NULL, NULL, X509_get0_tbs_sigalg(xs)); nid = OBJ_obj2nid(paobj); #endif result = apr_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid)); resdup = FALSE; } else if (strcEQ(var, "A_KEY")) { #if OPENSSL_VERSION_NUMBER < 0x10100000L nid = OBJ_obj2nid((ASN1_OBJECT *)(xs->cert_info->key->algor->algorithm)); #else ASN1_OBJECT *paobj; X509_PUBKEY_get0_param(&paobj, NULL, 0, NULL, X509_get_X509_PUBKEY(xs)); nid = OBJ_obj2nid(paobj); #endif result = apr_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid)); resdup = FALSE; } else if (strcEQ(var, "CERT")) { result = ssl_var_lookup_ssl_cert_PEM(p, xs); } if (resdup) result = apr_pstrdup(p, result); return result; }
int lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type, union lws_tls_cert_info_results *buf, size_t len) { X509_NAME *xn; #if !defined(LWS_PLAT_OPTEE) char *p; #endif if (!x509) return -1; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore) #define X509_get_notBefore(x) X509_getm_notBefore(x) #define X509_get_notAfter(x) X509_getm_notAfter(x) #endif switch (type) { case LWS_TLS_CERT_INFO_VALIDITY_FROM: buf->time = lws_tls_openssl_asn1time_to_unix( X509_get_notBefore(x509)); if (buf->time == (time_t)-1) return -1; break; case LWS_TLS_CERT_INFO_VALIDITY_TO: buf->time = lws_tls_openssl_asn1time_to_unix( X509_get_notAfter(x509)); if (buf->time == (time_t)-1) return -1; break; case LWS_TLS_CERT_INFO_COMMON_NAME: #if defined(LWS_PLAT_OPTEE) return -1; #else xn = X509_get_subject_name(x509); if (!xn) return -1; X509_NAME_oneline(xn, buf->ns.name, (int)len - 2); p = strstr(buf->ns.name, "/CN="); if (p) memmove(buf->ns.name, p + 4, strlen(p + 4) + 1); buf->ns.len = (int)strlen(buf->ns.name); return 0; #endif case LWS_TLS_CERT_INFO_ISSUER_NAME: xn = X509_get_issuer_name(x509); if (!xn) return -1; X509_NAME_oneline(xn, buf->ns.name, (int)len - 1); buf->ns.len = (int)strlen(buf->ns.name); return 0; case LWS_TLS_CERT_INFO_USAGE: #if defined(LWS_HAVE_X509_get_key_usage) buf->usage = X509_get_key_usage(x509); break; #else return -1; #endif case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY: { #ifndef USE_WOLFSSL size_t klen = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL); uint8_t *tmp, *ptmp; if (!klen || klen > len) return -1; tmp = (uint8_t *)OPENSSL_malloc(klen); if (!tmp) return -1; ptmp = tmp; if (i2d_X509_PUBKEY( X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen || !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) { lwsl_info("%s: cert public key extraction failed\n", __func__); if (ptmp) OPENSSL_free(tmp); return -1; } buf->ns.len = (int)klen; memcpy(buf->ns.name, tmp, klen); OPENSSL_free(tmp); #endif return 0; } default: return -1; } return 0; }
int tls_cert_info_get(tls_t *tls, tls_cert_info_t *tci, char **errstr) { #ifdef HAVE_LIBGNUTLS const gnutls_datum_t *cert_list; unsigned int cert_list_size; gnutls_x509_crt_t cert; size_t size; const char *oid[6] = { GNUTLS_OID_X520_COMMON_NAME, GNUTLS_OID_X520_ORGANIZATION_NAME, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, GNUTLS_OID_X520_LOCALITY_NAME, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, GNUTLS_OID_X520_COUNTRY_NAME }; int i; int e; char *p; const char *errmsg; errmsg = _("cannot get TLS certificate info"); if (!(cert_list = gnutls_certificate_get_peers(tls->session, &cert_list_size)) || cert_list_size == 0) { *errstr = xasprintf(_("%s: no certificate was found"), errmsg); return TLS_ECERT; } if (gnutls_x509_crt_init(&cert) != 0) { *errstr = xasprintf(_("%s: cannot initialize certificate structure"), errmsg); return TLS_ECERT; } if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) != 0) { *errstr = xasprintf(_("%s: error parsing certificate"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } /* certificate information */ size = 20; if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA, tci->sha1_fingerprint, &size) != 0) { *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } size = 16; if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, tci->md5_fingerprint, &size) != 0) { *errstr = xasprintf(_("%s: error getting MD5 fingerprint"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } if ((tci->activation_time = gnutls_x509_crt_get_activation_time(cert)) < 0) { *errstr = xasprintf(_("%s: cannot get activation time"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } if ((tci->expiration_time = gnutls_x509_crt_get_expiration_time(cert)) < 0) { *errstr = xasprintf(_("%s: cannot get expiration time"), errmsg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } /* owner information */ for (i = 0; i < 6; i++) { size = 0; e = gnutls_x509_crt_get_dn_by_oid(cert, oid[i], 0, 0, NULL, &size); if (e == GNUTLS_E_SHORT_MEMORY_BUFFER) { p = xmalloc(size); e = gnutls_x509_crt_get_dn_by_oid(cert, oid[i], 0, 0, p, &size); if (e == 0) { tci->owner_info[i] = p; } else { free(p); } } } /* issuer information */ for (i = 0; i < 6; i++) { size = 0; e = gnutls_x509_crt_get_issuer_dn_by_oid( cert, oid[i], 0, 0, NULL, &size); if (e == GNUTLS_E_SHORT_MEMORY_BUFFER) { p = xmalloc(size); e = gnutls_x509_crt_get_issuer_dn_by_oid( cert, oid[i], 0, 0, p, &size); if (e == 0) { tci->issuer_info[i] = p; } else { free(p); } } } gnutls_x509_crt_deinit(cert); return TLS_EOK; #endif /* HAVE_LIBGNUTLS */ #ifdef HAVE_LIBSSL X509 *x509cert; X509_NAME *x509_subject; X509_NAME *x509_issuer; ASN1_TIME *asn1time; int nid[6] = { NID_commonName, NID_organizationName, NID_organizationalUnitName, NID_localityName, NID_stateOrProvinceName, NID_countryName }; int size; unsigned int usize; char *p; int i; const char *errmsg; errmsg = _("cannot get TLS certificate info"); if (!(x509cert = SSL_get_peer_certificate(tls->ssl))) { *errstr = xasprintf(_("%s: no certificate was found"), errmsg); return TLS_ECERT; } if (!(x509_subject = X509_get_subject_name(x509cert))) { *errstr = xasprintf(_("%s: cannot get certificate subject"), errmsg); X509_free(x509cert); return TLS_ECERT; } if (!(x509_issuer = X509_get_issuer_name(x509cert))) { *errstr = xasprintf(_("%s: cannot get certificate issuer"), errmsg); X509_free(x509cert); return TLS_ECERT; } /* certificate information */ usize = 20; if (!X509_digest(x509cert, EVP_sha1(), tci->sha1_fingerprint, &usize)) { *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), errmsg); return TLS_ECERT; } usize = 16; if (!X509_digest(x509cert, EVP_md5(), tci->md5_fingerprint, &usize)) { *errstr = xasprintf(_("%s: error getting MD5 fingerprint"), errmsg); return TLS_ECERT; } asn1time = X509_get_notBefore(x509cert); if (asn1time_to_time_t((char *)asn1time->data, (asn1time->type != V_ASN1_GENERALIZEDTIME), &(tci->activation_time)) != 0) { *errstr = xasprintf(_("%s: cannot get activation time"), errmsg); X509_free(x509cert); tls_cert_info_free(tci); return TLS_ECERT; } asn1time = X509_get_notAfter(x509cert); if (asn1time_to_time_t((char *)asn1time->data, (asn1time->type != V_ASN1_GENERALIZEDTIME), &(tci->expiration_time)) != 0) { *errstr = xasprintf(_("%s: cannot get expiration time"), errmsg); X509_free(x509cert); tls_cert_info_free(tci); return TLS_ECERT; } /* owner information */ for (i = 0; i < 6; i++) { size = X509_NAME_get_text_by_NID(x509_subject, nid[i], NULL, 0); size++; p = xmalloc((size_t)size); if (X509_NAME_get_text_by_NID(x509_subject, nid[i], p, size) != -1) { tci->owner_info[i] = p; } else { free(p); } } /* issuer information */ for (i = 0; i < 6; i++) { size = X509_NAME_get_text_by_NID(x509_issuer, nid[i], NULL, 0); size++; p = xmalloc((size_t)size); if (X509_NAME_get_text_by_NID(x509_issuer, nid[i], p, size) != -1) { tci->issuer_info[i] = p; } else { free(p); } } X509_free(x509cert); return TLS_EOK; #endif /* HAVE_LIBSSL */ }
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, char* common_name, 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; 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); unsigned char* response = (unsigned char*) calloc(1,512); printf("Enter Country: "); scanf("%s",response); X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, response, -1, -1, 0); printf("Enter State: "); memset(response, 0, 512); scanf("%s",response); X509_NAME_add_entry_by_txt(name,"ST", MBSTRING_ASC, response, -1, -1, 0); printf("Enter City: "); memset(response, 0, 512); scanf("%s",response); X509_NAME_add_entry_by_txt(name,"L", MBSTRING_ASC, response, -1, -1, 0); printf("Enter Organization: "); memset(response, 0, 512); scanf("%s",response); X509_NAME_add_entry_by_txt(name,"O", MBSTRING_ASC, response, -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (unsigned char*)common_name, -1, -1, 0); X509_set_issuer_name(x,name); 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"); add_ext(x, NID_netscape_cert_type, "sslCA"); if (!X509_sign(x,pk,EVP_sha1())) goto err; *x509p=x; *pkeyp=pk; return 1; err: return 0; }
int cgiMain() { static char title[] = "List of existing Certificates"; char sorting[16] = "desc"; char certfilestr[225] = ""; FILE *certfile = NULL; BIO *membio = NULL; BIO *outbio = NULL; char membio_buf[128] = ""; X509 *cert = NULL; X509_NAME *certsubject = NULL; ASN1_TIME *start_date = NULL; ASN1_TIME *expiration_date = NULL; struct tm start_tm; struct tm expiration_tm; time_t now = time(NULL); time_t start = time(NULL); time_t expiration = time(NULL); double available_secs = 0; double remaining_secs = 0; struct dirent **certstore_files = NULL; int pagenumber = 1; int certcounter = 0; int tempcounter = 0; int pagecounter = 0; int dispcounter = 0; int dispmaxlines = 0; int certvalidity = 0; div_t disp_calc; div_t oddline_calc; double percent = 0; cert = X509_new(); certsubject = X509_NAME_new(); /* -------------------------------------------------------------------------- * * Get the list of .pem files from the cert directory * * ---------------------------------------------------------------------------*/ certcounter = scandir(CACERTSTORE, &certstore_files, file_select, hexsort); if(certcounter<=0) int_error("Error: No certificate files found."); /* -------------------------------------------------------------------------- * * calculate how many pages we get with MAXCERTDISPLAY * * ---------------------------------------------------------------------------*/ if(certcounter<=MAXCERTDISPLAY) pagecounter = 1; else { disp_calc = div(certcounter, MAXCERTDISPLAY); /* if the count of certs divided by MAXCERTDISPLAY has no remainder */ if(disp_calc.rem == 0) pagecounter = disp_calc.quot; /* with a remainder, we must prepare an extra page for the rest */ else pagecounter = disp_calc.quot +1; } /* -------------------------------------------------------------------------- * * Check if we have been subsequently called with a pagenumber & sort request * * ---------------------------------------------------------------------------*/ if(cgiFormInteger("page", &pagenumber, 1) == cgiFormSuccess) if(pagenumber > pagecounter || pagenumber <=0) int_error("Error: Page does not exist."); if(cgiFormString("sort", sorting, sizeof(sorting)) != cgiFormSuccess) strncpy(sorting, "desc", sizeof(sorting)); /* -------------------------------------------------------------------------- * * now we know how many certs we have in total and we can build the page(s). * * For every MAXCERTDISPLAY certs we start a new page and cycle through by * * calling ourself with the requested certs in range. * * ---------------------------------------------------------------------------*/ if(strcmp(sorting, "asc") == 0) { if(certcounter <= MAXCERTDISPLAY) { dispmaxlines = certcounter; tempcounter = 0; } else if(pagenumber == pagecounter && ( pagecounter * MAXCERTDISPLAY) - certcounter != 0) { tempcounter = (pagecounter * MAXCERTDISPLAY) - MAXCERTDISPLAY; dispmaxlines = certcounter - ((pagecounter-1) * MAXCERTDISPLAY); } else { tempcounter = (pagenumber * MAXCERTDISPLAY) - MAXCERTDISPLAY; dispmaxlines = MAXCERTDISPLAY; } } if(strcmp(sorting, "desc") == 0) { if(certcounter <= MAXCERTDISPLAY) { dispmaxlines = certcounter; tempcounter = certcounter; } else if(pagenumber == pagecounter && ( pagecounter * MAXCERTDISPLAY) - certcounter != 0) { tempcounter = certcounter - ((pagecounter-1) * MAXCERTDISPLAY); dispmaxlines = certcounter - ((pagecounter-1) * MAXCERTDISPLAY); } else { tempcounter = certcounter - (pagenumber*MAXCERTDISPLAY) + MAXCERTDISPLAY; dispmaxlines = MAXCERTDISPLAY; } } /* -------------------------------------------------------------------------- * * start the html output * * ---------------------------------------------------------------------------*/ outbio = BIO_new(BIO_s_file()); BIO_set_fp(outbio, cgiOut, BIO_NOCLOSE); pagehead(title); //debugging only: //printf("Number of certs: %d\n", certcounter); //printf("Num tempcounter: %d\n", tempcounter); //printf("Number of pages: %d\n", pagecounter); //printf("Div Quotient: %d\n", disp_calc.quot); //printf("Div Remainder: %d\n", disp_calc.rem); //fprintf(cgiOut, "</BODY></HTML>\n"); //exit(0); /* -------------------------------------------------------------------------- * * start the form output * * ---------------------------------------------------------------------------*/ fprintf(cgiOut, "<table>\n"); fprintf(cgiOut, "<tr>\n"); fprintf(cgiOut, "<th width=\"20\">"); fprintf(cgiOut, "#"); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "<th width=\"495\">"); fprintf(cgiOut, "Certificate Subject Information"); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "<th colspan=\"2\" width=\"60\">"); fprintf(cgiOut, "Expiry"); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "<th width=\"65\">"); fprintf(cgiOut, "Action"); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "</tr>\n"); for(dispcounter=0; dispcounter < dispmaxlines; dispcounter++) { /* zero certificate values and flags */ certvalidity = 0; percent = 0; available_secs = 0; remaining_secs = 0; cert = X509_new(); certsubject = X509_NAME_new(); if(strcmp(sorting, "desc") == 0) tempcounter--; snprintf(certfilestr, sizeof(certfilestr), "%s/%s", CACERTSTORE, certstore_files[tempcounter]->d_name); fprintf(cgiOut, "<tr>\n"); fprintf(cgiOut, "<th rowspan=\"2\">"); fprintf(cgiOut, "%d", tempcounter+1); fprintf(cgiOut, "</th>\n"); oddline_calc = div(tempcounter+1, 2); if(oddline_calc.rem) fprintf(cgiOut, "<td rowspan=\"2\" class=\"odd\">"); else fprintf(cgiOut, "<td rowspan=\"2\" class=\"even\">"); if ( (certfile = fopen(certfilestr, "r")) != NULL) { PEM_read_X509(certfile, &cert, NULL, NULL); certsubject = X509_get_subject_name(cert); /* display the subject data, use the UTF-8 flag to show * * Japanese Kanji, also needs the separator flag to work */ X509_NAME_print_ex_fp(cgiOut, certsubject, 0, ASN1_STRFLGS_UTF8_CONVERT|XN_FLAG_SEP_CPLUS_SPC); /* store certificate start date for later eval */ start_date = X509_get_notBefore(cert); /* store certificate expiration date for later eval */ expiration_date = X509_get_notAfter(cert); /* check the start and end dates in the cert */ if (X509_cmp_current_time (X509_get_notBefore (cert)) >= 0) /* flag the certificate as not valid yet */ certvalidity = 0; else if (X509_cmp_current_time (X509_get_notAfter (cert)) <= 0) /* flag the certificate as expired */ certvalidity = 0; else /* flag the certificate is still valid */ certvalidity = 1; fclose(certfile); } else fprintf(cgiOut, "Error: Can't open certificate file %s for reading.", certfilestr); fprintf(cgiOut, "</td>\n"); if(certvalidity == 0) { /* expiration bar display column */ fprintf(cgiOut, "<th rowspan=\"2\">\n"); fprintf(cgiOut, "<table class=\"led\">\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, "</table>\n"); fprintf(cgiOut, "</th>\n"); /* remaining days before expiration column */ fprintf(cgiOut, "<th class=\"exnok\" rowspan=\"2\">\n"); fprintf(cgiOut, "Inval<br />Expd"); fprintf(cgiOut, "</th>\n"); } if(certvalidity == 1) { /* ------ START get the certificate lifetime in seconds ------ */ /* copy the start date into a string */ membio = BIO_new(BIO_s_mem()); ASN1_TIME_print(membio, start_date); BIO_gets(membio, membio_buf, sizeof(membio_buf)); BIO_free(membio); /* parse the start date string into a time struct */ memset (&start_tm, '\0', sizeof(start_tm)); strptime(membio_buf, "%h %d %T %Y %z", &start_tm); start = mktime(&start_tm); /* ------ START get the certificate remaining time in seconds ------ */ /* copy the expiration date into a string */ membio = BIO_new(BIO_s_mem()); ASN1_TIME_print(membio, expiration_date); BIO_gets(membio, membio_buf, sizeof(membio_buf)); BIO_free(membio); /* parse the expiration date string into a time struct */ memset (&expiration_tm, '\0', sizeof(expiration_tm)); strptime(membio_buf, "%h %d %T %Y %z", &expiration_tm); /* get the current time */ now = time(NULL); expiration = mktime(&expiration_tm); /* get the time difference between expiration time and current time */ remaining_secs = difftime(expiration, now); /* ------ END get the certificate remaining time in seconds ------ */ /* get the time difference between start and expiration time */ available_secs = difftime(expiration, start); /* ------ END get the certificate lifetime in seconds ------ */ /* ------ START calculate percentage of lifetime left ------ */ /* remaining_secs *100 */ /* ------------------- = X, rounded down with floor() */ /* available_secs */ percent = floor((remaining_secs*100)/available_secs); /* ------ END calculate percentage of lifetime left ------ */ /* expiration bar display column */ fprintf(cgiOut, "<th rowspan=\"2\">\n"); fprintf(cgiOut, "<table class=\"led\">\n"); if (percent >= 90) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#00FF00\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); if (percent >= 80) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#00FF33\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); if (percent >= 70) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#99FF33\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); if (percent >= 60) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#FFFF00\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); if (percent >= 50) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#FFCC00\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); if (percent >= 40) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#FF9900\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); if (percent >= 30) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#FF6600\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); if (percent >= 20) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#FF3300\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); if (percent >= 10) fprintf(cgiOut, " <tr><td class=\"led\" bgcolor=\"#FF0000\"></td></tr>\n"); else fprintf(cgiOut, " <tr><td class=\"led-off\"></td></tr>\n"); fprintf(cgiOut, "</table>\n"); fprintf(cgiOut, "</th>\n"); /* remaining days before expiration column */ //fprintf(cgiOut, membio_buf); if (percent < 10) fprintf(cgiOut, "<th class=\"exnok\" rowspan=\"2\">\n"); else fprintf(cgiOut, "<th class=\"exok\" rowspan=\"2\">\n"); if(floor(remaining_secs/63072000) > 0) fprintf(cgiOut, "%.f<br />years", remaining_secs/31536000); else if(floor(remaining_secs/86400) > 0 ) fprintf(cgiOut, "%.f<br />days", remaining_secs/86400); else if(floor(remaining_secs/3600) > 0 ) fprintf(cgiOut, "%.f<br />hours", remaining_secs/3600); else if(floor(remaining_secs/60) > 0 ) fprintf(cgiOut, "%.f<br />mins", remaining_secs/60); else fprintf(cgiOut, "%.f<br />secs", remaining_secs); fprintf(cgiOut, "</th>\n"); } /* action column */ fprintf(cgiOut, "<th>"); fprintf(cgiOut, "<form action=\"getcert.cgi\" method=\"post\">\n"); fprintf(cgiOut, "<input type=\"hidden\" name=\"cfilename\" "); fprintf(cgiOut, "value=\"%s\" />\n", certstore_files[tempcounter]->d_name); fprintf(cgiOut, "<input type=\"hidden\" name=\"format\" value=\"text\" />\n"); fprintf(cgiOut, "<input class=\"getcert\" type=\"submit\" value=\"Detail\" />\n"); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "</tr>\n"); fprintf(cgiOut, "<tr>\n"); fprintf(cgiOut, "<th>\n"); fprintf(cgiOut, "<form action=\"certrenew.cgi\" method=\"post\">\n"); fprintf(cgiOut, "<input type=\"hidden\" name=\"cert-renew\" "); fprintf(cgiOut, "value=\""); PEM_write_bio_X509(outbio, cert); fprintf(cgiOut, "\" />\n"); fprintf(cgiOut, "<input class=\"getcert\" type=\"submit\" value=\"Renew\" />\n"); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "</tr>\n"); if(strcmp(sorting, "asc") == 0) tempcounter++; } fprintf(cgiOut, "<tr>\n"); fprintf(cgiOut, "<th colspan=\"5\">"); fprintf(cgiOut, "Total # of certs: %d | ", certcounter); fprintf(cgiOut, "Page %d of %d", pagenumber, pagecounter); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "</tr>\n"); fprintf(cgiOut, "</table>\n"); fprintf(cgiOut, "<p></p>\n"); fprintf(cgiOut, "<table>\n"); fprintf(cgiOut, "<tr>\n"); fprintf(cgiOut, "<th>\n"); fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n"); fprintf(cgiOut, "<input type=\"hidden\" name=\"sort\" "); fprintf(cgiOut, "value=\"desc\" />\n"); fprintf(cgiOut, "<input type=\"submit\" name=\"sort\""); fprintf(cgiOut, " value=\"Latest Certs first\" />\n"); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "<th>\n"); fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n"); fprintf(cgiOut, "<input type=\"hidden\" name=\"sort\" "); fprintf(cgiOut, "value=\"asc\" />\n"); fprintf(cgiOut, "<input type=\"submit\" name=\"sort\""); fprintf(cgiOut, " value=\"Oldest Certs first\" />\n"); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); // filler 1 fprintf(cgiOut, "<th width=\"15\">"); fprintf(cgiOut, " "); fprintf(cgiOut, "</th>\n"); // goto page 1 fprintf(cgiOut, "<th width=\"5\">\n"); fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n"); fprintf(cgiOut, "<input type=\"submit\" value=\"<<\" />\n"); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); // goto page before fprintf(cgiOut, "<th width=\"5\">\n"); fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n"); fprintf(cgiOut, "<input type=\"hidden\" name=\"certcounter\" "); fprintf(cgiOut, "value=\"%d\" />\n", certcounter); fprintf(cgiOut, "<input type=\"hidden\" name=\"pagecounter\" "); fprintf(cgiOut, "value=\"%d\" />\n", pagecounter); fprintf(cgiOut, "<input type=\"hidden\" name=\"page\" "); fprintf(cgiOut, "value=\""); tempcounter = 0; if(pagenumber > 1) tempcounter = pagenumber - 1; else tempcounter = 1; fprintf(cgiOut, "%d", tempcounter); fprintf(cgiOut, "\" />\n"); fprintf(cgiOut, "<input type=\"submit\" value=\"< 1\" />\n"); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); // goto page after fprintf(cgiOut, "<th width=\"5\">\n"); fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">\n"); fprintf(cgiOut, "<input type=\"hidden\" name=\"certcounter\" "); fprintf(cgiOut, "value=\"%d\" />\n", certcounter); fprintf(cgiOut, "<input type=\"hidden\" name=\"pagecounter\" "); fprintf(cgiOut, "value=\"%d\" />\n", pagecounter); fprintf(cgiOut, "<input type=\"hidden\" name=\"page\" "); fprintf(cgiOut, "value=\""); tempcounter = 0; if(pagecounter > pagenumber) tempcounter = pagenumber + 1; else tempcounter = pagecounter; fprintf(cgiOut, "%d", tempcounter); fprintf(cgiOut, "\" />\n"); fprintf(cgiOut, "<input type=\"submit\" value=\"1 >\" />\n"); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); // goto last page fprintf(cgiOut, "<th width=\"5\">\n"); fprintf(cgiOut, "<form action=\"certstore.cgi\" method=\"post\">"); fprintf(cgiOut, "<input type=\"hidden\" name=\"certcounter\" "); fprintf(cgiOut, "value=\"%d\" />\n", certcounter); fprintf(cgiOut, "<input type=\"hidden\" name=\"pagecounter\" "); fprintf(cgiOut, "value=\"%d\" />\n", pagecounter); fprintf(cgiOut, "<input type=\"hidden\" name=\"page\" "); fprintf(cgiOut, "value=\"%d\" />\n", pagecounter); fprintf(cgiOut, "<input type=\"submit\" value=\">>\" />\n"); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); // goto page number fprintf(cgiOut, "<th width=\"120\">\n"); fprintf(cgiOut, "<form class=\"setpage\" action=\"certstore.cgi\" method=\"post\">\n"); fprintf(cgiOut, "<input type=\"hidden\" name=\"certcounter\" "); fprintf(cgiOut, "value=\""); fprintf(cgiOut, "%d", certcounter); fprintf(cgiOut, "\" />\n"); fprintf(cgiOut, "<input type=\"hidden\" name=\"pagecounter\" "); fprintf(cgiOut, "value=\""); fprintf(cgiOut, "%d", pagecounter); fprintf(cgiOut, "\" />\n"); fprintf(cgiOut, "<input class=\"goto\" type=\"submit\" value=\"Goto\" />\n"); fprintf(cgiOut, "<input class=\"page\" type=\"text\" name=\"page\" "); fprintf(cgiOut, "value=\"%d\" />\n", pagecounter); fprintf(cgiOut, "</form>\n"); fprintf(cgiOut, "</th>\n"); fprintf(cgiOut, "</tr>\n"); fprintf(cgiOut, "</table>\n"); /* ---------------------------------------------------------------------------* * end the html output * * ---------------------------------------------------------------------------*/ pagefoot(); BIO_free(outbio); 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 = x509_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); X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); if (!reqfile && X509_verify_cert(&xsc) <= 0) 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; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create( OpcUa_CryptoProvider* a_pProvider, OpcUa_Int32 a_serialNumber, OpcUa_UInt32 a_validToInSec, OpcUa_Crypto_NameEntry* a_pNameEntries, /* will be used for issuer and subject thus it's selfigned cert */ OpcUa_UInt a_nameEntriesCount, /* will be used for issuer and subject thus it's selfigned cert */ OpcUa_Key a_pSubjectPublicKey, /* EVP_PKEY* - type defines also public key algorithm */ OpcUa_Crypto_Extension* a_pExtensions, OpcUa_UInt a_extensionsCount, OpcUa_UInt a_signatureHashAlgorithm, /* EVP_sha1(),... */ OpcUa_Key a_pIssuerPrivateKey, /* EVP_PKEY* - type defines also signature algorithm */ OpcUa_ByteString* a_pCertificate) { OpcUa_UInt i; X509_NAME* pSubj = OpcUa_Null; X509V3_CTX ctx; const EVP_MD* pDigest = OpcUa_Null; X509* pCert = OpcUa_Null; EVP_PKEY* pSubjectPublicKey = OpcUa_Null; EVP_PKEY* pIssuerPrivateKey = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_SelfSigned_Custom_Create"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pNameEntries); OpcUa_ReturnErrorIfArgumentNull(a_pExtensions); OpcUa_ReturnErrorIfArgumentNull(a_pIssuerPrivateKey.Key.Data); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); if(a_pSubjectPublicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } if(a_pIssuerPrivateKey.Type != OpcUa_Crypto_KeyType_Rsa_Private) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } pSubjectPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pSubjectPublicKey.Key.Data)),a_pSubjectPublicKey.Key.Length); if(pSubjectPublicKey == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } pIssuerPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pIssuerPrivateKey.Key.Data)),a_pIssuerPrivateKey.Key.Length); if(pIssuerPrivateKey == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* create new certificate object */ pCert = X509_new(); if(pCert == OpcUa_Null) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set version of certificate (V3 since internal representation starts versioning from 0) */ if(X509_set_version(pCert, 2L) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* generate a unique number for a serial number if none provided. */ if(a_serialNumber == 0) { ASN1_INTEGER* pSerialNumber = X509_get_serialNumber(pCert); pSerialNumber->type = V_ASN1_INTEGER; pSerialNumber->data = OPENSSL_realloc(pSerialNumber->data, 16); pSerialNumber->length = 16; if(pSerialNumber->data == NULL || OpcUa_P_Guid_Create((OpcUa_Guid*)pSerialNumber->data) == NULL) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } } /* use the integer passed in - note the API should not be using a 32-bit integer - must fix sometime */ else if(ASN1_INTEGER_set(X509_get_serialNumber(pCert), a_serialNumber) == 0) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* add key to the request */ if(X509_set_pubkey(pCert, pSubjectPublicKey) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(pSubjectPublicKey != OpcUa_Null) { EVP_PKEY_free(pSubjectPublicKey); pSubjectPublicKey = OpcUa_Null; } /* assign the subject name */ pSubj = X509_NAME_new(); if(!pSubj) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* create and add entries to subject name */ for(i=0; i<a_nameEntriesCount; i++) { uStatus = OpcUa_P_OpenSSL_X509_Name_AddEntry(&pSubj, a_pNameEntries + i); OpcUa_GotoErrorIfBad(uStatus); } /* set subject name in request */ if(X509_set_subject_name(pCert, pSubj) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set name of issuer (CA) */ if(X509_set_issuer_name(pCert, pSubj) != 1) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(!(X509_gmtime_adj(X509_get_notBefore(pCert), 0))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* set ending time of the certificate */ if(!(X509_gmtime_adj(X509_get_notAfter(pCert), a_validToInSec))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } /* add x509v3 extensions */ X509V3_set_ctx(&ctx, pCert, pCert, OpcUa_Null, OpcUa_Null, 0); for(i=0; i<a_extensionsCount; i++) { uStatus = OpcUa_P_OpenSSL_X509_AddCustomExtension(&pCert, a_pExtensions+i, &ctx); OpcUa_GotoErrorIfBad(uStatus); } /* sign certificate with the CA private key */ switch(a_signatureHashAlgorithm) { case OPCUA_P_SHA_160: pDigest = EVP_sha1(); break; case OPCUA_P_SHA_224: pDigest = EVP_sha224(); break; case OPCUA_P_SHA_256: pDigest = EVP_sha256(); break; case OPCUA_P_SHA_384: pDigest = EVP_sha384(); break; case OPCUA_P_SHA_512: pDigest = EVP_sha512(); break; default: uStatus = OpcUa_BadNotSupported; OpcUa_GotoErrorIfBad(uStatus); } if(!(X509_sign(pCert, pIssuerPrivateKey, pDigest))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(X509_verify(pCert, pIssuerPrivateKey) <= 0) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(pIssuerPrivateKey != OpcUa_Null) { EVP_PKEY_free(pIssuerPrivateKey); pIssuerPrivateKey = OpcUa_Null; } if(pSubj != OpcUa_Null) { X509_NAME_free(pSubj); pSubj = OpcUa_Null; } /* prepare container */ memset(a_pCertificate, 0, sizeof(OpcUa_ByteString)); /* get required length for conversion target buffer */ a_pCertificate->Length = i2d_X509(pCert, NULL); if(a_pCertificate->Length <= 0) { /* conversion to DER not possible */ uStatus = OpcUa_Bad; } /* allocate conversion target buffer */ a_pCertificate->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pCertificate->Data); /* convert into DER */ a_pCertificate->Length = i2d_X509(pCert, &(a_pCertificate->Data)); if(a_pCertificate->Length <= 0) { /* conversion to DER not possible */ uStatus = OpcUa_Bad; } else { /* correct pointer incrementation by i2d_X509() */ a_pCertificate->Data -= a_pCertificate->Length; } X509_free(pCert); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; X509_free(pCert); if(pSubjectPublicKey != OpcUa_Null) { EVP_PKEY_free(pSubjectPublicKey); } if(pIssuerPrivateKey != OpcUa_Null) { EVP_PKEY_free(pIssuerPrivateKey); } if(pSubj != OpcUa_Null) { X509_NAME_free(pSubj); } OpcUa_FinishErrorHandling; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; int ret=1; X509_REQ *req=NULL; X509 *x=NULL,*xca=NULL; ASN1_OBJECT *objtmp; 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; 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=EVP_sha1(); 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_func(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,"-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; else if (strcmp(*argv,"-issuer_hash") == 0) issuer_hash= ++num; 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_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); 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 *emlst; if (email == i) emlst = X509_get1_email(x); else emlst = X509_get1_ocsp(x); for (j = 0; j < sk_num(emlst); j++) BIO_printf(STDout, "%s\n", sk_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)); } else if (issuer_hash == i) { BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x)); } 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]; if (!X509_digest(x,digest,md,&n)) { BIO_printf(bio_err,"out of memory\n"); goto end; } BIO_printf(STDout,"%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); 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; } #ifndef OPENSSL_NO_DSA if (Upkey->type == EVP_PKEY_DSA) digest=EVP_dss1(); #endif #ifndef OPENSSL_NO_ECDSA if (Upkey->type == EVP_PKEY_EC) digest=EVP_ecdsa(); #endif 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; } #ifndef OPENSSL_NO_DSA if (CApkey->type == EVP_PKEY_DSA) digest=EVP_dss1(); #endif #ifndef OPENSSL_NO_ECDSA if (CApkey->type == EVP_PKEY_EC) digest = EVP_ecdsa(); #endif assert(need_rand); if (!x509_certify(ctx,CAfile,digest,x,xca, CApkey, 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, FORMAT_PEM, 0, passin, e, "request key"); if (pk == NULL) goto end; } BIO_printf(bio_err,"Generating certificate request\n"); #ifndef OPENSSL_NO_DSA if (pk->type == EVP_PKEY_DSA) digest=EVP_dss1(); #endif #ifndef OPENSSL_NO_ECDSA if (pk->type == EVP_PKEY_EC) digest=EVP_ecdsa(); #endif 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) { ASN1_HEADER ah; ASN1_OCTET_STRING os; os.data=(unsigned char *)NETSCAPE_CERT_HDR; os.length=strlen(NETSCAPE_CERT_HDR); ah.header= &os; ah.data=(char *)x; ah.meth=X509_asn1_meth(); i=ASN1_i2d_bio_of(ASN1_HEADER,i2d_ASN1_HEADER,out,&ah); } 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); 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 PyObject * get_not_before (certificate_x509 *self, PyObject *args) { ASN1_UTCTIME *time = X509_get_notBefore (self->x509); return time_to_string (time); }
int gen_cert (X509 ** cert, EVP_PKEY ** key) { RSA *rsa; X509_NAME *subj; X509_EXTENSION *ext; X509V3_CTX ctx; const char *commonName = "localhost"; char dNSName[128]; int rc; *cert = NULL; *key = NULL; /* Generate a private key. */ *key = EVP_PKEY_new (); if (*key == NULL) { #ifdef DEBUG fprintf (stderr, "Error generating key.\n"); #endif exit (1); } do { rsa = RSA_generate_key (DEFAULT_KEY_BITS, RSA_F4, NULL, NULL); if (rsa == NULL) { #ifdef DEBUG fprintf (stderr, "Error generating RSA key.\n"); #endif exit (1); } rc = RSA_check_key (rsa); } while (rc == 0); if (rc == -1) { #ifdef DEBUG fprintf (stderr, "Error generating RSA key.\n"); #endif exit (1); } if (EVP_PKEY_assign_RSA (*key, rsa) == 0) { RSA_free (rsa); #ifdef DEBUG fprintf (stderr, "Error with EVP and PKEY.\n"); #endif exit (1); } /* Generate a certificate. */ *cert = X509_new (); if (*cert == NULL) { #ifdef DEBUG fprintf (stderr, "Couldn't generate 509 cert.\n"); #endif exit (1); } if (X509_set_version (*cert, 2) == 0) { /* Version 3. */ #ifdef DEBUG fprintf (stderr, "Couldn't set x509 version.\n"); #endif exit (1); } /* Set the commonName. */ subj = X509_get_subject_name (*cert); if (X509_NAME_add_entry_by_txt (subj, "commonName", MBSTRING_ASC, (unsigned char *) commonName, -1, -1, 0) == 0) { #ifdef DEBUG fprintf (stderr, "Couldn't set common name.\n"); #endif exit (1); } /* Set the dNSName. */ rc = snprintf (dNSName, sizeof (dNSName), "DNS:%s", commonName); if (rc < 0 || rc >= sizeof (dNSName)) { #ifdef DEBUG fprintf (stderr, "Unable to set dns name.\n"); #endif exit (1); } X509V3_set_ctx (&ctx, *cert, *cert, NULL, NULL, 0); ext = X509V3_EXT_conf (NULL, &ctx, "subjectAltName", dNSName); if (ext == NULL) { #ifdef DEBUG fprintf (stderr, "Unable to get subjectaltname.\n"); #endif exit (1); } if (X509_add_ext (*cert, ext, -1) == 0) { #ifdef DEBUG fprintf (stderr, "x509_add_ext error.\n"); #endif exit (1); } /* Set a comment. */ ext = X509V3_EXT_conf (NULL, &ctx, "nsComment", CERTIFICATE_COMMENT); if (ext == NULL) { #ifdef DEBUG fprintf (stderr, "x509v3_ext_conf error.\n"); #endif exit (1); } if (X509_add_ext (*cert, ext, -1) == 0) { #ifdef DEBUG fprintf (stderr, "x509_add_ext error.\n"); #endif exit (1); } X509_set_issuer_name (*cert, X509_get_subject_name (*cert)); X509_gmtime_adj (X509_get_notBefore (*cert), 0); X509_gmtime_adj (X509_get_notAfter (*cert), DEFAULT_CERT_DURATION); X509_set_pubkey (*cert, *key); /* Sign it. */ if (X509_sign (*cert, *key, EVP_sha1 ()) == 0) { #ifdef DEBUG fprintf (stderr, "x509_sign error.\n"); #endif exit (1); } return 1; }
/* * Create a fake X509v3 certificate, signed by the provided CA, * based on the original certificate retrieved from the real server. * The returned certificate is created using X509_new() and thus must * be freed by the caller using X509_free(). * The optional argument extraname is added to subjectAltNames if provided. */ X509 * ssl_x509_forge(X509 *cacrt, EVP_PKEY *cakey, X509 *origcrt, const char *extraname, EVP_PKEY *key) { X509_NAME *subject, *issuer; GENERAL_NAMES *names; GENERAL_NAME *gn; X509 *crt; subject = X509_get_subject_name(origcrt); issuer = X509_get_subject_name(cacrt); if (!subject || !issuer) return NULL; crt = X509_new(); if (!crt) return NULL; if (!X509_set_version(crt, 0x02) || !X509_set_subject_name(crt, subject) || !X509_set_issuer_name(crt, issuer) || ssl_x509_serial_copyrand(crt, origcrt) == -1 || !X509_gmtime_adj(X509_get_notBefore(crt), (long)-60*60*24) || !X509_gmtime_adj(X509_get_notAfter(crt), (long)60*60*24*364) || !X509_set_pubkey(crt, key)) goto errout; /* add standard v3 extensions; cf. RFC 2459 */ X509V3_CTX ctx; X509V3_set_ctx(&ctx, cacrt, crt, NULL, NULL, 0); if (ssl_x509_v3ext_add(&ctx, crt, "basicConstraints", "CA:FALSE") == -1 || ssl_x509_v3ext_add(&ctx, crt, "keyUsage", "digitalSignature," "keyEncipherment") == -1 || ssl_x509_v3ext_add(&ctx, crt, "extendedKeyUsage", "serverAuth") == -1 || ssl_x509_v3ext_add(&ctx, crt, "subjectKeyIdentifier", "hash") == -1 || ssl_x509_v3ext_add(&ctx, crt, "authorityKeyIdentifier", "keyid,issuer:always") == -1) goto errout; if (!extraname) { /* no extraname provided: copy original subjectAltName ext */ if (ssl_x509_v3ext_copy_by_nid(crt, origcrt, NID_subject_alt_name) == -1) goto errout; } else { names = X509_get_ext_d2i(origcrt, NID_subject_alt_name, 0, 0); if (!names) { /* no subjectAltName present: add new one */ char *cfval; if (asprintf(&cfval, "DNS:%s", extraname) < 0) goto errout; if (ssl_x509_v3ext_add(&ctx, crt, "subjectAltName", cfval) == -1) { free(cfval); goto errout; } free(cfval); } else { /* add extraname to original subjectAltName * and add it to the new certificate */ gn = GENERAL_NAME_new(); if (!gn) goto errout2; gn->type = GEN_DNS; gn->d.dNSName = M_ASN1_IA5STRING_new(); if (!gn->d.dNSName) goto errout3; ASN1_STRING_set(gn->d.dNSName, (unsigned char *)extraname, strlen(extraname)); sk_GENERAL_NAME_push(names, gn); X509_EXTENSION *ext = X509V3_EXT_i2d( NID_subject_alt_name, 0, names); if (!X509_add_ext(crt, ext, -1)) { if (ext) { X509_EXTENSION_free(ext); } goto errout3; } X509_EXTENSION_free(ext); sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); } } #ifdef DEBUG_CERTIFICATE ssl_x509_v3ext_add(&ctx, crt, "nsComment", "Generated by " PNAME); #endif /* DEBUG_CERTIFICATE */ const EVP_MD *md; switch (EVP_PKEY_type(cakey->type)) { #ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: md = EVP_sha1(); break; #endif /* !OPENSSL_NO_RSA */ #ifndef OPENSSL_NO_DSA case EVP_PKEY_DSA: md = EVP_dss1(); break; #endif /* !OPENSSL_NO_DSA */ #ifndef OPENSSL_NO_ECDSA case EVP_PKEY_EC: md = EVP_ecdsa(); break; #endif /* !OPENSSL_NO_ECDSA */ default: goto errout; } if (!X509_sign(crt, cakey, md)) goto errout; return crt; errout3: GENERAL_NAME_free(gn); errout2: sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); errout: X509_free(crt); return NULL; }
CK_RV PKCS11_Objects_OpenSSL::GetAttributeValue(Cryptoki_Session_Context* pSessionCtx, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { OBJECT_DATA* pObj = PKCS11_Objects_OpenSSL::GetObjectFromHandle(pSessionCtx, hObject); if(pObj == NULL) return CKR_OBJECT_HANDLE_INVALID; if(pObj->Type == CertificateType) { CERT_DATA* pCertData = (CERT_DATA*)pObj->Data; X509* pCert = pCertData->cert; UINT32 valLen = 0; for(int i=0; i<(int)ulCount; i++) { switch(pTemplate[i].type) { case CKA_CLASS: *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(CKO_CERTIFICATE); break; case CKA_PRIVATE: *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->privKeyData.key == NULL ? 0 : 1); valLen = sizeof(INT32); break; case CKA_VALUE_BITS: { *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->pubKeyData.size); valLen = sizeof(INT32); } break; case CKA_KEY_TYPE: { *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->pubKeyData.type); valLen = sizeof(UINT32); } break; case CKA_ISSUER: { char* name=X509_NAME_oneline(X509_get_issuer_name(pCert),NULL,0); valLen = TINYCLR_SSL_STRLEN(name) + 1; if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen; hal_strcpy_s((char*)pTemplate[i].pValue, valLen, name); OPENSSL_free(name); } break; case CKA_SUBJECT: { char* subject=X509_NAME_oneline(X509_get_subject_name(pCert),NULL,0); valLen = TINYCLR_SSL_STRLEN(subject) + 1; if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen; hal_strcpy_s((char*)pTemplate[i].pValue, valLen, subject); OPENSSL_free(subject); } break; case CKA_SERIAL_NUMBER: { ASN1_INTEGER* asn = X509_get_serialNumber(pCert); valLen = asn->length; if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen; TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, asn->data, valLen); } break; case CKA_MECHANISM_TYPE: if(pCert->sig_alg != NULL) { int signature_nid; CK_MECHANISM_TYPE type = CKM_VENDOR_DEFINED; signature_nid = OBJ_obj2nid(pCert->sig_alg->algorithm); switch(signature_nid) { case NID_sha1WithRSA: case NID_sha1WithRSAEncryption: //szNid = "1.2.840.113549.1.1.5"; type = CKM_SHA1_RSA_PKCS; break; case NID_md5WithRSA: case NID_md5WithRSAEncryption: //szNid = "1.2.840.113549.1.1.4"; type = CKM_MD5_RSA_PKCS; break; case NID_sha256WithRSAEncryption: //szNid = "1.2.840.113549.1.1.11"; type = CKM_SHA256_RSA_PKCS; break; case NID_sha384WithRSAEncryption: //szNid = "1.2.840.113549.1.1.12"; type = CKM_SHA384_RSA_PKCS; break; case NID_sha512WithRSAEncryption: //szNid = "1.2.840.113549.1.1.13"; type = CKM_SHA512_RSA_PKCS; break; } valLen = sizeof(CK_MECHANISM_TYPE); *(CK_MECHANISM_TYPE*)pTemplate[i].pValue = SwapEndianIfBEc32(type); } break; case CKA_START_DATE: { DATE_TIME_INFO dti; ssl_get_ASN1_UTCTIME(X509_get_notBefore(pCert), &dti); valLen = (INT32)pTemplate[i].ulValueLen; if(valLen > sizeof(dti)) valLen = sizeof(dti); TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, &dti, valLen); } break; case CKA_END_DATE: { DATE_TIME_INFO dti; ssl_get_ASN1_UTCTIME(X509_get_notAfter(pCert), &dti); valLen = pTemplate[i].ulValueLen; if(valLen > sizeof(dti)) valLen = sizeof(dti); TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, &dti, valLen); } break; case CKA_VALUE: { UINT8* pData = (UINT8*)pTemplate[i].pValue; UINT8* pTmp = pData; valLen = i2d_X509(pCert, NULL); if(valLen > pTemplate[i].ulValueLen) return CKR_DEVICE_MEMORY; valLen = i2d_X509(pCert, &pTmp); if(valLen < 0) return CKR_FUNCTION_FAILED; } break; case CKA_VALUE_LEN: *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(valLen); break; default: return CKR_ATTRIBUTE_TYPE_INVALID; } } } else if(pObj->Type == KeyType) { KEY_DATA* pKey = (KEY_DATA*)pObj->Data; int valLen = 0; bool isPrivate = false; for(int i=0; i<(int)ulCount; i++) { switch(pTemplate[i].type) { case CKA_CLASS: *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32((0 != (pKey->attrib & Private) ? CKO_PRIVATE_KEY : 0 != (pKey->attrib & Public) ? CKO_PUBLIC_KEY : CKO_SECRET_KEY)); break; case CKA_MODULUS: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->n, (UINT8*)pTemplate[i].pValue); } break; case CKA_EXPONENT_1: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->dmp1, (UINT8*)pTemplate[i].pValue); } break; case CKA_EXPONENT_2: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->dmq1, (UINT8*)pTemplate[i].pValue); } break; case CKA_COEFFICIENT: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->iqmp, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIME_1: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->p, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIME_2: if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->q, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIVATE_EXPONENT: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->priv_key, (UINT8*)pTemplate[i].pValue); } else if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->d, (UINT8*)pTemplate[i].pValue); } break; case CKA_PUBLIC_EXPONENT: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->pub_key, (UINT8*)pTemplate[i].pValue); } else if(pKey->type == CKK_EC) { UINT8 pTmp[66*2+1]; EC_KEY* pEC = ((EVP_PKEY*)pKey->key)->pkey.ec; const EC_POINT* point = EC_KEY_get0_public_key(pEC); valLen = EC_POINT_point2oct(EC_KEY_get0_group(pEC), point, POINT_CONVERSION_UNCOMPRESSED, (UINT8*)pTmp, ARRAYSIZE(pTmp), NULL); if(valLen == 0) return CKR_FUNCTION_FAILED; memmove(pTemplate[i].pValue, &pTmp[1], valLen-1); // remove POINT_CONVERSION_UNCOMPRESSED header byte } else if(pKey->type == CKK_RSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.rsa->e, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIME: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->p, (UINT8*)pTemplate[i].pValue); } break; case CKA_SUBPRIME: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->q, (UINT8*)pTemplate[i].pValue); } break; case CKA_BASE: if(pKey->type == CKK_DSA) { EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key; valLen = BN_bn2bin(pRealKey->pkey.dsa->g, (UINT8*)pTemplate[i].pValue); } break; case CKA_PRIVATE: isPrivate = 0 != *(INT32*)pTemplate[i].pValue; break; case CKA_KEY_TYPE: *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pKey->type); break; case CKA_VALUE_BITS: *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pKey->size); break; case CKA_VALUE: switch(pKey->type) { case CKK_AES: case CKK_GENERIC_SECRET: { // TODO: Add permissions to export key int len = (pKey->size + 7) / 8; if(len > (INT32)pTemplate[i].ulValueLen) len = (int)pTemplate[i].ulValueLen; TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, pKey->key, len); valLen = len; } break; default: return CKR_ATTRIBUTE_TYPE_INVALID; } break; case CKA_VALUE_LEN: switch(pKey->type) { case CKK_EC: *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(valLen); break; default: return CKR_ATTRIBUTE_TYPE_INVALID; } break; default: return CKR_ATTRIBUTE_TYPE_INVALID; } } } return CKR_OK; }
static int __pkcs11h_crypto_openssl_certificate_get_expiration ( IN void * const global_data, IN const unsigned char * const blob, IN const size_t blob_size, OUT time_t * const expiration ) { X509 *x509 = NULL; __pkcs11_openssl_d2i_t d2i; ASN1_TIME *notBefore; ASN1_TIME *notAfter; (void)global_data; /*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/ _PKCS11H_ASSERT (blob!=NULL); _PKCS11H_ASSERT (expiration!=NULL); *expiration = (time_t)0; if ((x509 = X509_new ()) == NULL) { goto cleanup; } d2i = (__pkcs11_openssl_d2i_t)blob; if (!d2i_X509 (&x509, &d2i, blob_size)) { goto cleanup; } notBefore = X509_get_notBefore (x509); notAfter = X509_get_notAfter (x509); if ( notBefore != NULL && notAfter != NULL && X509_cmp_current_time (notBefore) <= 0 && X509_cmp_current_time (notAfter) >= 0 && notAfter->length >= 12 ) { struct tm tm1; memset (&tm1, 0, sizeof (tm1)); tm1.tm_year = (notAfter->data[ 0] - '0') * 10 + (notAfter->data[ 1] - '0') + 100; tm1.tm_mon = (notAfter->data[ 2] - '0') * 10 + (notAfter->data[ 3] - '0') - 1; tm1.tm_mday = (notAfter->data[ 4] - '0') * 10 + (notAfter->data[ 5] - '0'); tm1.tm_hour = (notAfter->data[ 6] - '0') * 10 + (notAfter->data[ 7] - '0'); tm1.tm_min = (notAfter->data[ 8] - '0') * 10 + (notAfter->data[ 9] - '0'); tm1.tm_sec = (notAfter->data[10] - '0') * 10 + (notAfter->data[11] - '0'); *expiration = mktime (&tm1); *expiration += (int)(mktime (localtime (expiration)) - mktime (gmtime (expiration))); } cleanup: if (x509 != NULL) { X509_free (x509); x509 = NULL; } return *expiration != (time_t)0; }
PKI_X509_CERT * PKI_X509_CERT_new ( PKI_X509_CERT *ca_cert, PKI_X509_KEYPAIR *kPair, PKI_X509_REQ *req, char *subj_s, char *serial_s, uint64_t validity, PKI_X509_PROFILE *conf, PKI_ALGOR *algor, 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 ) { char *tmp_s = NULL; if(( tmp_s = PKI_CONFIG_get_value( conf, "/profile/subject/dn")) != NULL ) { subj = PKI_X509_NAME_new ( tmp_s ); PKI_Free ( tmp_s ); } else { subj = PKI_X509_NAME_new( "" ); } } else if ( req ) { /* Copy the name from the request */ subj = PKI_X509_REQ_get_data( req, PKI_X509_DATA_SUBJECT ); } 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 ) { 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 ) { serial = s2i_ASN1_INTEGER( NULL, serial_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_log_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_log_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_log_debug("Got Signing Algorithm: %s, %s", PKI_DIGEST_ALG_get_parsed(dgst), PKI_ALGOR_get_parsed(myAlg)); digest = dgst; } else { PKI_log_debug("Can not parse digest algorithm from %s", tmp_s); } } else { PKI_log_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 ( kParams->ec.form > -1 ) { EC_KEY_set_conv_form(certPubKeyVal->pkey.ec, kParams->ec.form); } if ( kParams->ec.asn1flags > -1 ) { EC_KEY_set_asn1_flag( certPubKeyVal->pkey.ec, kParams->ec.asn1flags ); } 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_log_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, ca_cert); } else { PKI_TOKEN_set_cacert ( tk, ret ); } if (req) PKI_TOKEN_set_req ( tk, req ); if (kPair) PKI_TOKEN_set_keypair ( tk, kPair ); rv = PKI_X509_EXTENSIONS_cert_add_profile(conf, oids, ret, tk); if (rv != PKI_OK) { PKI_log_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 ); } /* if(PKI_sign ( PKI_DATATYPE_X509_CERT, (void *) val->cert_info, &X509_CINF_it, val->cert_info->signature, val->sig_alg, val->signature, k, digest )==PKI_ERR) { PKI_log_err("PKI_X509_CERT_new()::Can not sign certificate!"); goto err; } */ // X509_sign ( val, k->value, digest ); 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 ) 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)); } // PKI_X509_CINF_FULL *cFull = NULL; // cFull = (PKI_X509_CINF_FULL *) cVal->cert_info; // cFull->enc.modified = 1; #endif /* if(PKI_sign ( PKI_DATATYPE_X509_CERT, (void *) val->cert_info, &X509_CINF_it, val->cert_info->signature, val->sig_alg, val->signature, k, digest ) == PKI_ERR ) { PKI_log_err("PKI_X509_CERT_new()::Can not sign certificate!"); goto err; } */ /* if(!X509_sign( ret->value, k->value, digest)) { PKI_log_err("PKI_X509_CERT_new()::Can not sign certificate!"); goto err; } */ 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) { 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; };
int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag) { long l; int ret=0,i; char *m=NULL,mlch = ' '; int nmindent = 0; X509_CINF *ci; ASN1_INTEGER *bs; EVP_PKEY *pkey=NULL; const char *neg; if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { mlch = '\n'; nmindent = 12; } if(nmflags == X509_FLAG_COMPAT) nmindent = 16; ci=x->cert_info; if(!(cflag & X509_FLAG_NO_HEADER)) { if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err; if (BIO_write(bp," Data:\n",10) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_VERSION)) { l=X509_get_version(x); if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_SERIAL)) { if (BIO_write(bp," Serial Number:",22) <= 0) goto err; bs=X509_get_serialNumber(x); if (bs->length <= (int)sizeof(long)) { l=ASN1_INTEGER_get(bs); if (bs->type == V_ASN1_NEG_INTEGER) { l= -l; neg="-"; } else neg=""; if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0) goto err; } else { neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":""; if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err; for (i=0; i<bs->length; i++) { if (BIO_printf(bp,"%02x%c",bs->data[i], ((i+1 == bs->length)?'\n':':')) <= 0) goto err; } } } if(!(cflag & X509_FLAG_NO_SIGNAME)) { if(X509_signature_print(bp, x->sig_alg, NULL) <= 0) goto err; #if 0 if (BIO_printf(bp,"%8sSignature Algorithm: ","") <= 0) goto err; if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0) goto err; if (BIO_puts(bp, "\n") <= 0) goto err; #endif } if(!(cflag & X509_FLAG_NO_ISSUER)) { if (BIO_printf(bp," Issuer:%c",mlch) <= 0) goto err; if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err; if (BIO_write(bp,"\n",1) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_VALIDITY)) { if (BIO_write(bp," Validity\n",17) <= 0) goto err; if (BIO_write(bp," Not Before: ",24) <= 0) goto err; if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err; if (BIO_write(bp,"\n Not After : ",25) <= 0) goto err; if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err; if (BIO_write(bp,"\n",1) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_SUBJECT)) { if (BIO_printf(bp," Subject:%c",mlch) <= 0) goto err; if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err; if (BIO_write(bp,"\n",1) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_PUBKEY)) { if (BIO_write(bp," Subject Public Key Info:\n",33) <= 0) goto err; if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0) goto err; if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0) goto err; if (BIO_puts(bp, "\n") <= 0) goto err; pkey=X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bp,"%12sUnable to load Public Key\n",""); BIO_print_errors(bp); } else { EVP_PKEY_print_public(bp, pkey, 16, NULL); EVP_PKEY_free(pkey); } } if(!(cflag & X509_FLAG_NO_IDS)) { if (ci->issuerUID) { if (BIO_printf(bp,"%8sIssuer Unique ID: ","") <= 0) goto err; if (!X509_signature_dump(bp, ci->issuerUID, 12)) goto err; } if (ci->subjectUID) { if (BIO_printf(bp,"%8sSubject Unique ID: ","") <= 0) goto err; if (!X509_signature_dump(bp, ci->subjectUID, 12)) goto err; } } if (!(cflag & X509_FLAG_NO_EXTENSIONS)) X509V3_extensions_print(bp, "X509v3 extensions", ci->extensions, cflag, 8); if(!(cflag & X509_FLAG_NO_SIGDUMP)) { if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_AUX)) { if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err; } ret=1; err: if (m != NULL) OPENSSL_free(m); return(ret); }
void * PKI_X509_CERT_get_data ( PKI_X509_CERT *x, PKI_X509_DATA type ) { void *ret = NULL; PKI_X509_CERT_VALUE *tmp_x = NULL; PKI_MEM *mem = NULL; int *tmp_int = NULL; if( !x || !x->value ) return (NULL); tmp_x = x->value; switch (type) { case PKI_X509_DATA_VERSION: ret = (tmp_x)->cert_info->version; break; case PKI_X509_DATA_SERIAL: ret = X509_get_serialNumber ( (X509 *) x->value ); break; case PKI_X509_DATA_SUBJECT: ret = X509_get_subject_name( (X509 *) x->value ); break; case PKI_X509_DATA_ISSUER: ret = X509_get_issuer_name( (X509 *) x->value ); break; case PKI_X509_DATA_NOTBEFORE: ret = X509_get_notBefore( (X509 *) x->value ); break; case PKI_X509_DATA_NOTAFTER: ret = X509_get_notAfter( (X509 *) x->value ); break; case PKI_X509_DATA_KEYPAIR_VALUE: case PKI_X509_DATA_PUBKEY: ret = X509_get_pubkey( (X509 *) x->value); break; case PKI_X509_DATA_PUBKEY_BITSTRING: ret = X509_get0_pubkey_bitstr( (X509 *) x->value); break; case PKI_X509_DATA_SIGNATURE: ret = (void *) (tmp_x)->signature; break; case PKI_X509_DATA_ALGORITHM: case PKI_X509_DATA_SIGNATURE_ALG1: if (tmp_x->cert_info && tmp_x->cert_info->signature) ret = tmp_x->cert_info->signature; break; case PKI_X509_DATA_SIGNATURE_ALG2: if (tmp_x->sig_alg) ret = tmp_x->sig_alg; break; case PKI_X509_DATA_KEYSIZE: tmp_int = PKI_Malloc ( sizeof( int )); *tmp_int = EVP_PKEY_size( X509_get_pubkey ( (X509 *) x->value )); ret = tmp_int; break; case PKI_X509_DATA_TBS_MEM_ASN1: if((mem = PKI_MEM_new_null()) == NULL ) break; mem->size = (size_t) ASN1_item_i2d ( (void *) tmp_x->cert_info, &(mem->data), &X509_CINF_it ); ret = mem; break; case PKI_X509_DATA_CERT_TYPE: tmp_int = PKI_Malloc ( sizeof ( int )); *tmp_int = PKI_X509_CERT_get_type( x ); break; case PKI_X509_DATA_EXTENSIONS: default: /* Not Recognized/Supported DATATYPE */ return (NULL); } return (ret); }
/* FIXME: Master-Key, Extensions, CA bits (openssl x509 -text -in servcert.pem) */ int _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl) { X509 *peer_cert; EVP_PKEY *peer_pkey; /* EVP_PKEY *ca_pkey; */ /* EVP_PKEY *tmp_pkey; */ char notBefore[64]; char notAfter[64]; int alg; int sign_alg; if (!(peer_cert = SSL_get_peer_certificate (ssl))) return (1); /* FATAL? */ X509_NAME_oneline (X509_get_subject_name (peer_cert), cert_info->subject, sizeof (cert_info->subject)); X509_NAME_oneline (X509_get_issuer_name (peer_cert), cert_info->issuer, sizeof (cert_info->issuer)); broke_oneline (cert_info->subject, cert_info->subject_word); broke_oneline (cert_info->issuer, cert_info->issuer_word); alg = OBJ_obj2nid (peer_cert->cert_info->key->algor->algorithm); sign_alg = OBJ_obj2nid (peer_cert->sig_alg->algorithm); ASN1_TIME_snprintf (notBefore, sizeof (notBefore), X509_get_notBefore (peer_cert)); ASN1_TIME_snprintf (notAfter, sizeof (notAfter), X509_get_notAfter (peer_cert)); peer_pkey = X509_get_pubkey (peer_cert); strncpy (cert_info->algorithm, (alg == NID_undef) ? "Unknown" : OBJ_nid2ln (alg), sizeof (cert_info->algorithm)); cert_info->algorithm_bits = EVP_PKEY_bits (peer_pkey); strncpy (cert_info->sign_algorithm, (sign_alg == NID_undef) ? "Unknown" : OBJ_nid2ln (sign_alg), sizeof (cert_info->sign_algorithm)); /* EVP_PKEY_bits(ca_pkey)); */ cert_info->sign_algorithm_bits = 0; strncpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore)); strncpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter)); EVP_PKEY_free (peer_pkey); /* SSL_SESSION_print_fp(stdout, SSL_get_session(ssl)); */ /* if (ssl->session->sess_cert->peer_rsa_tmp) { tmp_pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(tmp_pkey, ssl->session->sess_cert->peer_rsa_tmp); cert_info->rsa_tmp_bits = EVP_PKEY_bits (tmp_pkey); EVP_PKEY_free(tmp_pkey); } else fprintf(stderr, "REMOTE SIDE DOESN'T PROVIDES ->peer_rsa_tmp\n"); */ cert_info->rsa_tmp_bits = 0; X509_free (peer_cert); return (0); }
static void init_generated (GstDtlsCertificate * self) { GstDtlsCertificatePrivate *priv = self->priv; RSA *rsa; X509_NAME *name = NULL; g_return_if_fail (!priv->x509); g_return_if_fail (!priv->private_key); priv->private_key = EVP_PKEY_new (); if (!priv->private_key) { GST_WARNING_OBJECT (self, "failed to create private key"); return; } priv->x509 = X509_new (); if (!priv->x509) { GST_WARNING_OBJECT (self, "failed to create certificate"); EVP_PKEY_free (priv->private_key); priv->private_key = NULL; return; } rsa = RSA_generate_key (2048, RSA_F4, NULL, NULL); if (!rsa) { GST_WARNING_OBJECT (self, "failed to generate RSA"); EVP_PKEY_free (priv->private_key); priv->private_key = NULL; X509_free (priv->x509); priv->x509 = NULL; return; } if (!EVP_PKEY_assign_RSA (priv->private_key, rsa)) { GST_WARNING_OBJECT (self, "failed to assign RSA"); RSA_free (rsa); rsa = NULL; EVP_PKEY_free (priv->private_key); priv->private_key = NULL; X509_free (priv->x509); priv->x509 = NULL; return; } rsa = NULL; X509_set_version (priv->x509, 2); ASN1_INTEGER_set (X509_get_serialNumber (priv->x509), 0); X509_gmtime_adj (X509_get_notBefore (priv->x509), 0); X509_gmtime_adj (X509_get_notAfter (priv->x509), 31536000L); /* A year */ X509_set_pubkey (priv->x509, priv->private_key); name = X509_get_subject_name (priv->x509); 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 *) "OpenWebRTC", -1, -1, 0); X509_set_issuer_name (priv->x509, name); name = NULL; if (!X509_sign (priv->x509, priv->private_key, EVP_sha256 ())) { GST_WARNING_OBJECT (self, "failed to sign certificate"); EVP_PKEY_free (priv->private_key); priv->private_key = NULL; X509_free (priv->x509); priv->x509 = NULL; return; } self->priv->pem = _gst_dtls_x509_to_pem (priv->x509); }
int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) { X509 *err_cert; int err,depth; err_cert=X509_STORE_CTX_get_current_cert(ctx); err= X509_STORE_CTX_get_error(ctx); depth= X509_STORE_CTX_get_error_depth(ctx); if (!verify_quiet || !ok) { BIO_printf(bio_err,"depth=%d ",depth); if (err_cert) { X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert), 0, XN_FLAG_ONELINE); BIO_puts(bio_err, "\n"); } else BIO_puts(bio_err, "<no cert>\n"); } if (!ok) { BIO_printf(bio_err,"verify error:num=%d:%s\n",err, X509_verify_cert_error_string(err)); if (verify_depth >= depth) { if (!verify_return_error) ok=1; verify_error=X509_V_OK; } else { ok=0; verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG; } } switch (err) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: BIO_puts(bio_err,"issuer= "); X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert), 0, XN_FLAG_ONELINE); BIO_puts(bio_err, "\n"); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: BIO_printf(bio_err,"notBefore="); ASN1_TIME_print(bio_err,X509_get_notBefore(err_cert)); BIO_printf(bio_err,"\n"); break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: BIO_printf(bio_err,"notAfter="); ASN1_TIME_print(bio_err,X509_get_notAfter(err_cert)); BIO_printf(bio_err,"\n"); break; case X509_V_ERR_NO_EXPLICIT_POLICY: if (!verify_quiet) policies_print(bio_err, ctx); break; } if (err == X509_V_OK && ok == 2 && !verify_quiet) policies_print(bio_err, ctx); if (ok && !verify_quiet) BIO_printf(bio_err,"verify return:%d\n",ok); return(ok); }
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; // Attempt to load key as an RSA key or a DSA key 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 we still can't load the key, try loading any keys from the certificate 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 have a key, walk the list of certs, find the one for our key, // remove any certs for our key from the list, what's left is part of // the CA certificate chain. 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 // Really old certs/keys are no good, throw them away so we can // generate a new one below. if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } // If we have a cert, and it's a self-signed one, but we're binding to // all the same addresses as the Meta server is, use it's cert instead. // This allows a self-signed certificate generated by Murmur to be // replaced by a CA-signed certificate in the .ini file. 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 we still don't have a certificate by now, try to load the one from Meta 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 loading from Meta doesn't work, build+sign a new one 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 // Drain OpenSSL's per-thread error queue // to ensure that errors from the operations // we've done in here do not leak out into // Qt's SSL module. // // If an error leaks, it can break all connections // to the server because each invocation of Qt's SSL // read callback checks OpenSSL's per-thread error // queue (albeit indirectly, via SSL_get_error()). // Qt expects any errors returned from SSL_get_error() // to be related to the QSslSocket it is currently // processing -- which is the obvious thing to expect: // SSL_get_error() takes a pointer to an SSL object // and the return code of the failed operation. // However, it is also documented as: // // "In addition to ssl and ret, SSL_get_error() // inspects the current thread's OpenSSL error // queue." // // So, if any OpenSSL operation on the main thread // forgets to clear the error queue, those errors // *will* leak into other things that *do* error // checking. In our case, into Qt's SSL read callback, // resulting in all clients being disconnected. ERR_clear_error(); }