Beispiel #1
0
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;
}
Beispiel #2
0
/**
 * 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));
}
Beispiel #3
0
/** 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;
}
Beispiel #4
0
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);
        }
Beispiel #10
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);
}
Beispiel #11
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;
}
Beispiel #12
0
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;
}
Beispiel #13
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 */
}
Beispiel #14
0
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;
}
Beispiel #15
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, "&nbsp;");
  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=\"&lt;&lt;\" />\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=\"&lt; 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 &gt;\" />\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=\"&gt;&gt;\" />\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);
}
Beispiel #16
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;
}
Beispiel #18
0
int MAIN(int argc, char **argv)
	{
	ENGINE *e = NULL;
	int ret=1;
	X509_REQ *req=NULL;
	X509 *x=NULL,*xca=NULL;
	ASN1_OBJECT *objtmp;
	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);
	}
Beispiel #19
0
static PyObject *
get_not_before (certificate_x509 *self, PyObject *args)
{
	ASN1_UTCTIME *time = X509_get_notBefore (self->x509);
	return time_to_string (time);
}
Beispiel #20
0
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;
}
Beispiel #21
0
/*
 * 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;
}
Beispiel #24
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;
};
Beispiel #25
0
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);
	}
Beispiel #26
0
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);
}
Beispiel #27
0
/*
    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);
}
Beispiel #29
0
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);
	}
Beispiel #30
0
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();
}