Example #1
0
int generate_ski_string() {
	FILE *fp;
	int i, j = 0, loc = 0;
	char* buf2 = ski = calloc(40 + 1, 1);
	X509 * signed_cert = 0;
	X509_EXTENSION *ext;
        
	fp = fopen(f_signedcert, "r");
	if (fp) {
		signed_cert = d2i_X509_fp(fp, &signed_cert);
		fclose(fp);
	} else { 	//Create new one
		return -1;
	}

	loc = X509_get_ext_by_NID(signed_cert, NID_subject_key_identifier, -1);
	ext = X509_get_ext(signed_cert, loc);

	OPENSSL_free(signed_cert);

	if (ext == NULL) {
		return -1;
	}

	for (i = 2; i < 22; i++) {
		j += sprintf(buf2 + j, "%02X", ext->value->data[i]);
	}
	return j + 2;
}
Example #2
0
static int
SSL_CTX_use_certificate_file_with_check(
	SSL_CTX *ctx, 
	char *file, 
	int type)
{
	FILE *fp;
	X509 *x509;
	X509_STORE_CTX *sctx;
	int ret;
	ret = SSL_CTX_use_certificate_file(ctx, file, type);
	if(!ret) return ret;
	if(!(fp = fopen(file, "r"))) {
		return -1;
	}
	x509 = PEM_read_X509(fp, NULL, NULL, NULL);
	if(!x509){
		rewind(fp);
		x509 = d2i_X509_fp(fp, NULL);
	}
	fclose(fp);
	if(!x509) return -1;
	X509_STORE_add_cert(ctx->cert_store, x509);
	sctx = X509_STORE_CTX_new();
	X509_STORE_CTX_init(sctx, ctx->cert_store, x509, NULL);
	X509_STORE_CTX_set_verify_cb(sctx, LocalVerifyCallBack);
	X509_verify_cert(sctx);
	X509_STORE_CTX_free(sctx);
	CheckValidPeriod(x509);
	return ret;
}
Example #3
0
u32 parse_single_cert(cert_info_s *cert_buf, s8 *file_path)
{
	u32 ret = 1;
	FILE *fp;
	X509 *x;
	BIO *biofile;
  
	fp = fopen(file_path, "rb");
    if (NULL == fp)
    {
        return PARSE_FAIL;
    }

    x = X509_new();
	if (NULL == x)
	{
		fclose(fp);
		return PARSE_FAIL;
	}
    if (NULL == d2i_X509_fp(fp, &x))
    {
        biofile = BIO_new_file(file_path, "rb");
		if (NULL == biofile)
		{
			X509_free(x);
			fclose(fp);
			return PARSE_FAIL;	
		}

        if (!PEM_read_bio_X509(biofile, &x, 0, NULL))
        {
			BIO_free(biofile);
			X509_free(x);
			fclose(fp);
			return PARSE_FAIL;
        }
        BIO_free(biofile);
    }
	
	ret = get_single_cert_info(x, cert_buf);

	X509_free(x);
	fclose(fp);
	
	return ret;
}
Example #4
0
SSLCertificate *ssl_certificate_find_lookup(const char *host, int port,
	int lookup)
{
	char *file = NULL;
	char *buf = NULL;
	char *fqdn_host = NULL;
	SSLCertificate *cert = NULL;
	X509 *tmp_x509 = NULL;
	FILE *fp = NULL;

	if (lookup)
		fqdn_host = get_fqdn(host, port);
	else
		fqdn_host = g_strdup(host);

	buf = g_strdup_printf("%d", port);
	file = g_strconcat(config_dir, G_DIR_SEPARATOR_S,
		"certs", G_DIR_SEPARATOR_S, fqdn_host, ".", buf, ".cert", NULL);

	g_free(buf);
	fp = fopen(file, "rb");
	if (fp == NULL) {
		g_free(file);
		g_free(fqdn_host);
		return NULL;
	}

	if ((tmp_x509 = d2i_X509_fp(fp, 0)) != NULL) {
		cert = ssl_certificate_new_lookup(tmp_x509, fqdn_host, port,
			lookup);
		X509_free(tmp_x509);
	}
	fclose(fp);
	g_free(file);
	g_free(fqdn_host);

	return cert;
}
Example #5
0
void OcNetwork::sslErrorHandler(QNetworkReply* rep,const QList<QSslError> &errors)
{
    QVariantMap account = config.getAccount();
    bool ignoreSSLerrors = false;
    if (account["state"].toInt() == 0)
    {
        ignoreSSLerrors = account["ignoresslerror"].toBool();
    }

    if (ignoreSSLerrors)
    {
        rep->ignoreSslErrors();

        QLOG_WARN() << "Network: ignore SSL errors";

    } else {

        foreach (const QSslError &error, errors)
        {
            QLOG_ERROR() << "Network SSL error: " << error.errorString();
        }

        // get certificate checksum
        QString checksum = QString::fromLatin1(rep->sslConfiguration().peerCertificateChain().last().digest(QCryptographicHash::Md5).toHex().toLower());

        // set string for temporary file path
        QString filePath(QDir::homePath());
        filePath.append(BASE_PATH).append(QDir::separator()).append(checksum).append(".der");

        // store server certificate temporary
        QFile x509Temp(filePath);
        x509Temp.open(QIODevice::WriteOnly);
        x509Temp.write(rep->sslConfiguration().peerCertificateChain().last().toDer());
        x509Temp.close();


#if defined(MEEGO_EDITION_HARMATTAN)

        // set credential
        int credSuc = aegis_certman_set_credentials("buschtrommel-ocnews::CertOCNewsSSL");
        if (credSuc != 0) qDebug() << "set credential error: " << credSuc;

        // open file for X509 struct
        FILE * crtFile;
        crtFile = fopen(filePath.toAscii().data(), "r");
        if (crtFile == NULL) qDebug() << "Can not open cert file.";

        X509 * crt;
        crt = d2i_X509_fp(crtFile, NULL);

        if (crt == NULL) qDebug() << "Error importing X509 Certificate";

        // get server key id
        aegis_key_id crtKeyId;
        aegis_certman_get_key_id(crt, crtKeyId);

        // open ssl domain
        domain_handle ownDomain;
        int openCheck = aegis_certman_open_domain("ssl-ocnews", AEGIS_CERTMAN_DOMAIN_PRIVATE, &ownDomain);
        if (openCheck != 0) QLOG_ERROR() << "Network: Error Opening SSL Domain: " << openCheck;

        int guiCheck = aegis_certman_gui_check_certificate(crt, 120);
        QLOG_INFO() << "Network Certificate check: " << guiCheck;
        if (guiCheck == 0)
        {
            // check if cert is already in domain
            X509 * storedCert;
            int loadStoredCert = aegis_certman_load_cert(ownDomain, crtKeyId, &storedCert);

            if (loadStoredCert == 0 && storedCert != NULL)
            {
                QLOG_INFO() << "Network Load Cert: " << loadStoredCert;

                // convert internal X509 structure to DER
                int len;
                unsigned char *buf;

                buf = NULL;

                len = i2d_X509(storedCert, &buf);

                if (len > 0) {
                    // create Qt Certificate from buffer
                    QByteArray buffer(reinterpret_cast<const char*>(buf), len);
                    QSslCertificate sslCert(buffer, QSsl::Der);

                    // create list and append cert
                    QList<QSslCertificate> sslCerts;
                    sslCerts.append(sslCert);

                    // put ssl into ssl error for ignored errors
                    QSslError sslError(QSslError::SelfSignedCertificate, sslCerts.at(0));
                    QList<QSslError> expectedSslErrors;
                    expectedSslErrors.append(sslError);

                    // add certificate to socket and current configuration
                    QSslSocket::addDefaultCaCertificates(sslCerts);
                    QList<QSslCipher> ciphers = rep->sslConfiguration().ciphers();
                    QSslConfiguration sslConfig;
                    sslConfig.setCiphers(ciphers);
                    sslConfig.setCaCertificates(sslCerts);
                    rep->setSslConfiguration(sslConfig);

                    // ignore only this ssl error
                    rep->ignoreSslErrors(expectedSslErrors);
                } else {
                    QLOG_ERROR() << "Network: Can not decode cert to DER.";
                }
            } else {
                int addCheck = aegis_certman_add_cert(ownDomain, crt);
                QLOG_INFO() << "Network Add Cert: " << addCheck;


                // convert internal X509 structure to DER
                int len;
                unsigned char *buf;

                buf = NULL;

                len = i2d_X509(crt, &buf);

                if (len > 0) {
                    // create Qt Certificate from buffer
                    QByteArray buffer(reinterpret_cast<const char*>(buf), len);
                    QSslCertificate sslCert(buffer, QSsl::Der);

                    // create list and append cert
                    QList<QSslCertificate> sslCerts;
                    sslCerts.append(sslCert);

                    // put ssl into ssl error for ignored errors
                    QSslError sslError(QSslError::SelfSignedCertificate, sslCerts.at(0));
                    QList<QSslError> expectedSslErrors;
                    expectedSslErrors.append(sslError);

                    // add certificate to socket and current configuration
                    QSslSocket::addDefaultCaCertificates(sslCerts);
                    QList<QSslCipher> ciphers = rep->sslConfiguration().ciphers();
                    QSslConfiguration sslConfig;
                    sslConfig.setCiphers(ciphers);
                    sslConfig.setCaCertificates(sslCerts);
                    rep->setSslConfiguration(sslConfig);

                    // ignore only these ssl error
                    rep->ignoreSslErrors(expectedSslErrors);
                } else {
                    QLOG_ERROR() << "Network: Can not decode cert to DER.";
                }
            }
        } else {
            // remove cert if not approved
            int removeCheck = aegis_certman_rm_cert(ownDomain, crtKeyId);
            QLOG_INFO() << "Network Remove Cert: " << removeCheck;
        }

        aegis_certman_close_domain(ownDomain);
        x509Temp.remove(); // remove temporary cert file

#else

//        rep->ignoreSslErrors();
        rep->abort();
        QLOG_WARN() << "Abort network operation...";

#endif
    }
}
Example #6
0
/*
    ToDo:   Create Access to OpenSSL certificate store
            => Only API to In-Memory-Store is available for version 0.9.8x
            => Wait until Directory- and/or File-Store is available
*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_LoadCertificate(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_Void*                 a_pLoadHandle,
    OpcUa_Void*                 a_pCertificateStore,
    OpcUa_ByteString*           a_pCertificate)
{
    OpcUa_Byte*     buf                 = OpcUa_Null;
    OpcUa_Byte*     p                   = OpcUa_Null;
    FILE*           pCertificateFile    = OpcUa_Null;
    X509*           pTmpCert            = OpcUa_Null;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_LoadCertificate");

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle);
    OpcUa_ReturnErrorIfArgumentNull(a_pLoadHandle);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);

    /* read DER certificates */
    pCertificateFile = fopen((const char*)a_pLoadHandle, "r");

    /* check for valid file handle */
    OpcUa_GotoErrorIfTrue((pCertificateFile == OpcUa_Null), OpcUa_BadInvalidArgument);

    if(!(pTmpCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null)))
    {
        uStatus = OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    a_pCertificate->Length = i2d_X509(pTmpCert, NULL);
    buf = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length);
    OpcUa_GotoErrorIfAllocFailed(buf);
    p = buf;
    for (;;)
    {
        i2d_X509(pTmpCert, &p);
        X509_free(pTmpCert);
        if(!(pTmpCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null)))
        {
            break;
        }
        p = OpcUa_P_Memory_ReAlloc(buf, a_pCertificate->Length + i2d_X509(pTmpCert, NULL));
        OpcUa_GotoErrorIfAllocFailed(p);
        buf = p;
        p = buf + a_pCertificate->Length;
        a_pCertificate->Length += i2d_X509(pTmpCert, NULL);
    }

    if(fclose(pCertificateFile) != 0)
    {
        pCertificateFile = OpcUa_Null;
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    a_pCertificate->Data = buf;

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(pCertificateFile != OpcUa_Null)
    {
        fclose(pCertificateFile);
    }

    if(pTmpCert != OpcUa_Null)
    {
        X509_free(pTmpCert);
    }

    if(buf != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(buf);
    }

OpcUa_FinishErrorHandling;
}
Example #7
0
/*============================================================================
 * OpcUa_P_OpenSSL_PKI_ValidateCertificate
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_ValidateCertificate(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_ByteString*           a_pCertificate,
    OpcUa_Void*                 a_pCertificateStore,
    OpcUa_Int*                  a_pValidationCode /* Validation return codes from OpenSSL */
    )
{
    OpcUa_P_OpenSSL_CertificateStore_Config*    pCertificateStoreCfg;

    const unsigned char* p;

    X509*               pX509Certificate        = OpcUa_Null;
    STACK_OF(X509)*     pX509Chain              = OpcUa_Null;
    X509_STORE_CTX*     verify_ctx              = OpcUa_Null;    /* holds data used during verification process */
    char                CertFile[MAX_PATH];
    struct dirent **dirlist = NULL;
    int numCertificates = 0, i;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ValidateCertificate");

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore);
    OpcUa_ReturnErrorIfArgumentNull(a_pValidationCode);

    pCertificateStoreCfg = (OpcUa_P_OpenSSL_CertificateStore_Config*)a_pProvider->Handle;

    /* convert DER encoded bytestring certificate to openssl X509 certificate */
    p = a_pCertificate->Data;
    if(!(pX509Certificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Length)))
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

    while(p < a_pCertificate->Data + a_pCertificate->Length)
    {
        X509* pX509AddCertificate;
        if(!(pX509AddCertificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Data + a_pCertificate->Length - p)))
        {
            OpcUa_GotoErrorWithStatus(OpcUa_Bad);
        }
        if(pX509Chain == NULL)
        {
            pX509Chain = sk_X509_new_null();
            OpcUa_GotoErrorIfAllocFailed(pX509Chain);
        }
        if(!sk_X509_push(pX509Chain, pX509AddCertificate))
        {
            X509_free(pX509AddCertificate);
            OpcUa_GotoErrorWithStatus(OpcUa_Bad);
        }
    }

    /* create verification context and initialize it */
    if(!(verify_ctx = X509_STORE_CTX_new()))
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
    if(X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain) != 1)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }
#else
    X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain);
#endif

    if(X509_STORE_CTX_set_app_data(verify_ctx, pCertificateStoreCfg) != 1)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

    if((pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) == OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL_EXCEPT_SELF_SIGNED
        && !verify_ctx->check_issued(verify_ctx, pX509Certificate, pX509Certificate))
    {
        /* set the flags of the store so that CRLs are consulted */
        X509_STORE_CTX_set_flags(verify_ctx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
    }

    /* verify the certificate */
    *a_pValidationCode = X509_V_OK;
    if(X509_verify_cert(verify_ctx) <= 0)
    {
        *a_pValidationCode = verify_ctx->error;
        switch(verify_ctx->error)
        {
        case X509_V_ERR_CERT_HAS_EXPIRED:
        case X509_V_ERR_CERT_NOT_YET_VALID:
        case X509_V_ERR_CRL_NOT_YET_VALID:
        case X509_V_ERR_CRL_HAS_EXPIRED:
        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
        case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
        case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
            {
                uStatus = OpcUa_BadCertificateTimeInvalid;
                break;
            }
        case X509_V_ERR_CERT_REVOKED:
            {
                uStatus = OpcUa_BadCertificateRevoked;
                break;
            }
        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
            {
                uStatus = OpcUa_BadCertificateUntrusted;
                break;
            }
        case X509_V_ERR_CERT_SIGNATURE_FAILURE:
            {
                uStatus = OpcUa_BadSecurityChecksFailed;
                break;
            }
        default:
            {
                uStatus = OpcUa_BadCertificateInvalid;
            }
        }
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REQUIRE_CHAIN_CERTIFICATE_IN_TRUST_LIST)
    {
        FILE*            pCertificateFile;
        X509*            pTrustCert;
        STACK_OF(X509)*  chain;
        int              trusted, n;

        chain = X509_STORE_CTX_get_chain(verify_ctx);
        trusted = 0;
        if(pCertificateStoreCfg->CertificateTrustListLocation == NULL || pCertificateStoreCfg->CertificateTrustListLocation[0] == '\0')
        {
            uStatus = OpcUa_Bad;
            OpcUa_GotoErrorIfBad(uStatus);
        }

        numCertificates = scandir(pCertificateStoreCfg->CertificateTrustListLocation, &dirlist, certificate_filter_der, alphasort);
        for (i=0; i<numCertificates; i++)
        {
            uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateTrustListLocation, dirlist[i]->d_name, MAX_PATH, CertFile);
            OpcUa_GotoErrorIfBad(uStatus);

            /* read DER certificates */
            pCertificateFile = fopen(CertFile, "r");
            if(pCertificateFile == OpcUa_Null)
            {
                continue; /* ignore access errors */
            }

            pTrustCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null);
            fclose(pCertificateFile);
            if(pTrustCert == OpcUa_Null)
            {
                continue; /* ignore parse errors */
            }

            for(n = 0; n < sk_X509_num(chain); n++)
            {
                if (X509_cmp(sk_X509_value(chain, n), pTrustCert) == 0)
                    break;
            }

            X509_free(pTrustCert);
            if(n < sk_X509_num(chain))
            {
                trusted = 1;
                break;
            }
        }
        for (i=0; i<numCertificates; i++)
        {
            free(dirlist[i]);
        }
        free(dirlist);
        dirlist = NULL;

        if(!trusted)
        {
            uStatus = OpcUa_BadCertificateUntrusted;
            OpcUa_GotoErrorIfBad(uStatus);
        }
    }

    X509_STORE_CTX_free(verify_ctx);
    X509_free(pX509Certificate);
    if(pX509Chain != OpcUa_Null)
    {
        sk_X509_pop_free(pX509Chain, X509_free);
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(dirlist != NULL)
    {
        for (i=0; i<numCertificates; i++)
        {
            free(dirlist[i]);
        }
        free(dirlist);
    }

    if(verify_ctx != OpcUa_Null)
    {
        X509_STORE_CTX_free(verify_ctx);
    }

    if(pX509Certificate != OpcUa_Null)
    {
        X509_free(pX509Certificate);
    }

    if(pX509Chain != OpcUa_Null)
    {
        sk_X509_pop_free(pX509Chain, X509_free);
    }

OpcUa_FinishErrorHandling;
}
Example #8
0
void RunEaSession(SSL* ssl, void* data) 
{
  int rfd, wfd;
  FILE* rfp;
  FILE* wfp;
  SetupFileDescriptors(ssl, &rfd, &rfp, &wfd, &wfp);

  RsaDevice device = (RsaDevice)data;

  // Device makes entropy request
  BIGNUM* v1 = BN_new();
  BIGNUM* v2 = BN_new(); 
  BIGNUM* v3 = BN_new(); 
  BIGNUM* v4 = BN_new(); 

  CHECK_CALL(v1);
  CHECK_CALL(v2);
  CHECK_CALL(RsaDevice_GenEntropyRequest(device, v1, v2));

  PrintTime("Sending commits to EA");
  // Send mode flag
  CHECK_CALL(fprintf(wfp, "%d\n", RSA_CLIENT));
  CHECK_CALL(!fflush(wfp));

  CHECK_CALL(WriteOneBignum(STRING_COMMIT_X, sizeof(STRING_COMMIT_X), wfp, v1));
  CHECK_CALL(WriteOneBignum(STRING_COMMIT_Y, sizeof(STRING_COMMIT_Y), wfp, v2));
  CHECK_CALL(!fflush(wfp));

  PrintTime("...done");

  // Read x', y' from EA
  PrintTime("Reading entropy from EA");
  CHECK_CALL(ReadOneBignum(&v1, rfp, STRING_X_PRIME));
  CHECK_CALL(ReadOneBignum(&v2, rfp, STRING_Y_PRIME));
  PrintTime("...done");

  CHECK_CALL(RsaDevice_SetEntropyResponse(device, v1, v2));

  // Send proof to EA 
  ProductEvidence ev;
  CHECK_CALL(ev);
  X509_REQ* req = X509_REQ_new();
  CHECK_CALL(req);
  CHECK_CALL(RsaDevice_GenEaSigningRequest(device, req, v1, v2, v3, &ev));

  PrintTime("Sending cert to EA");
  CHECK_CALL(i2d_X509_REQ_fp(wfp, req));
  //fprintf(wfp, "\n");
  CHECK_CALL(!fflush(wfp));

  CHECK_CALL(WriteOneBignum(STRING_DELTA_X, sizeof(STRING_DELTA_X), wfp, v1));
  CHECK_CALL(WriteOneBignum(STRING_DELTA_Y, sizeof(STRING_DELTA_Y), wfp, v2));
  CHECK_CALL(WriteOneBignum(STRING_MODULUS_RAND, sizeof(STRING_MODULUS_RAND), wfp, v3));
  CHECK_CALL(ProductEvidence_Serialize(ev, wfp));
  CHECK_CALL(!fflush(wfp));
  PrintTime("...done");

  X509_REQ_free(req);

  ProductEvidence_Free(ev);

  X509* cert = NULL;
  PrintTime("Reading cert from EA");
  if(!(cert = d2i_X509_fp(rfp, NULL))) {
    fatal("Could not read X509 response");
  }
  PrintTime("...done");

  fclose(rfp);
  fclose(wfp);

  BN_clear_free(v1);
  BN_clear_free(v2);
  BN_clear_free(v3);
  BN_clear_free(v4);

  // Give EA signature back to device
  CHECK_CALL(RsaDevice_SetEaCertResponse(device, cert));

  X509_free(cert);
  return;
}