// returns NULL if CSR doesn't contain the extension, the commitment C value otherwise
BIGNUM *getCommitmentValueFromCSR(char *req_filename) {
	
	/* read in the request */
	X509_REQ *req;
	FILE *fp;
	if (!(fp = fopen(req_filename, "r")))
		critical_error("Error reading request file");
	if (!(req = PEM_read_X509_REQ(fp, NULL, NULL, NULL)))
		critical_error("Error reading request in file");
	fclose(fp);

	BIGNUM *toret = NULL;

	// enable the extension handling (retrieve/print as string)
	int nid = _commitmentExt_start();

	// get extensions stack of request
	STACK_OF(X509_EXTENSION) *extlist = X509_REQ_get_extensions(req);
			
	if (extlist!=NULL) {	// if there are extensions
		int extpos = X509v3_get_ext_by_NID(extlist, nid, -1); 	// try to locate extension
		if (extpos!=-1) { // if found	
			X509_EXTENSION *ext = X509v3_get_ext(extlist, extpos);
			toret = _commitmentExt2BN(ext);
		}
	} 
	X509_REQ_free(req);
	_commitmentExt_end();
	return toret;
}
Beispiel #2
0
void pki_x509req::fload(const QString fname)
{
	FILE *fp = fopen_read(fname);
	X509_REQ *_req;
	int ret = 0;

	if (fp != NULL) {
		_req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
		if (!_req) {
			pki_ign_openssl_error();
			rewind(fp);
			_req = d2i_X509_REQ_fp(fp, NULL);
		}
		fclose(fp);
		if (ret || pki_ign_openssl_error()) {
			if (_req)
				X509_REQ_free(_req);
			throw errorEx(tr("Unable to load the certificate request in file %1. Tried PEM, DER and SPKAC format.").arg(fname));
		}
	} else {
		fopen_error(fname);
		return;
	}

	if (_req) {
		X509_REQ_free(request);
		request = _req;
	}
	autoIntName();
	if (getIntName().isEmpty())
		setIntName(rmslashdot(fname));
	openssl_error(fname);
}
Beispiel #3
0
void
read_request(void) {
	/* Read certificate request file */
	if (!r_flag || !(reqfile = fopen(r_char, "r"))) {
		fprintf(stderr, "%s: cannot open certificate request\n", pname);
		exit (SCEP_PKISTATUS_FILE);
	}
	if (!PEM_read_X509_REQ(reqfile, &request, NULL, NULL)) {
		fprintf(stderr, "%s: error while reading request file\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_FILE);
	}
	fclose(reqfile);
}
Beispiel #4
0
/*
 * initialize ssl engine, load certs and initialize openssl internals
 */
void init_ssl(void)
{
	const SSL_METHOD *ssl_method;
	RSA *rsa=NULL;
	X509_REQ *req = NULL;
	X509 *cer = NULL;
	EVP_PKEY *pk = NULL;
	EVP_PKEY *req_pkey = NULL;
	X509_NAME *name = NULL;
	FILE *fp;
	char buf[SIZ];
	int rv = 0;

	if (!access("/var/run/egd-pool", F_OK)) {
		RAND_egd("/var/run/egd-pool");
	}

	if (!RAND_status()) {
		syslog(LOG_WARNING, "PRNG not adequately seeded, won't do SSL/TLS\n");
		return;
	}
	SSLCritters = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *));
	if (!SSLCritters) {
		syslog(LOG_ERR, "citserver: can't allocate memory!!\n");
		/* Nothing's been initialized, just die */
		ShutDownWebcit();
		exit(WC_EXIT_SSL);
	} else {
		int a;

		for (a = 0; a < CRYPTO_num_locks(); a++) {
			SSLCritters[a] = malloc(sizeof(pthread_mutex_t));
			if (!SSLCritters[a]) {
				syslog(LOG_EMERG,
					"citserver: can't allocate memory!!\n");
				/** Nothing's been initialized, just die */
				ShutDownWebcit();
				exit(WC_EXIT_SSL);
			}
			pthread_mutex_init(SSLCritters[a], NULL);
		}
	}

	/*
	 * Initialize SSL transport layer
	 */
	SSL_library_init();
	SSL_load_error_strings();
	ssl_method = SSLv23_server_method();
	if (!(ssl_ctx = SSL_CTX_new(ssl_method))) {
		syslog(LOG_WARNING, "SSL_CTX_new failed: %s\n", ERR_reason_error_string(ERR_get_error()));
		return;
	}

	syslog(LOG_INFO, "Requesting cipher list: %s\n", ssl_cipher_list);
	if (!(SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher_list))) {
		syslog(LOG_WARNING, "SSL_CTX_set_cipher_list failed: %s\n", ERR_reason_error_string(ERR_get_error()));
		return;
	}

	CRYPTO_set_locking_callback(ssl_lock);
	CRYPTO_set_id_callback(id_callback);

	/*
	 * Get our certificates in order. (FIXME: dirify. this is a setup job.)
	 * First, create the key/cert directory if it's not there already...
	 */
	mkdir(CTDL_CRYPTO_DIR, 0700);

	/*
	 * Before attempting to generate keys/certificates, first try
	 * link to them from the Citadel server if it's on the same host.
	 * We ignore any error return because it either meant that there
	 * was nothing in Citadel to link from (in which case we just
	 * generate new files) or the target files already exist (which
	 * is not fatal either).
	 */
	if (!strcasecmp(ctdlhost, "uds")) {
		sprintf(buf, "%s/keys/citadel.key", ctdlport);
		rv = symlink(buf, CTDL_KEY_PATH);
		if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno));
		sprintf(buf, "%s/keys/citadel.csr", ctdlport);
		rv = symlink(buf, CTDL_CSR_PATH);
		if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno));
		sprintf(buf, "%s/keys/citadel.cer", ctdlport);
		rv = symlink(buf, CTDL_CER_PATH);
		if (!rv) syslog(LOG_DEBUG, "%s\n", strerror(errno));
	}

	/*
	 * If we still don't have a private key, generate one.
	 */
	if (access(CTDL_KEY_PATH, R_OK) != 0) {
		syslog(LOG_INFO, "Generating RSA key pair.\n");
		rsa = RSA_generate_key(1024,	/* modulus size */
					65537,	/* exponent */
					NULL,	/* no callback */
					NULL	/* no callback */
		);
		if (rsa == NULL) {
			syslog(LOG_WARNING, "Key generation failed: %s\n", ERR_reason_error_string(ERR_get_error()));
		}
		if (rsa != NULL) {
			fp = fopen(CTDL_KEY_PATH, "w");
			if (fp != NULL) {
				chmod(CTDL_KEY_PATH, 0600);
				if (PEM_write_RSAPrivateKey(fp,	/* the file */
							rsa,	/* the key */
							NULL,	/* no enc */
							NULL,	/* no passphr */
							0,	/* no passphr */
							NULL,	/* no callbk */
							NULL	/* no callbk */
				) != 1) {
					syslog(LOG_WARNING, "Cannot write key: %s\n",
						ERR_reason_error_string(ERR_get_error()));
					unlink(CTDL_KEY_PATH);
				}
				fclose(fp);
			}
			else {
				syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_KEY_PATH);
				ShutDownWebcit();
				exit(0);
			}
			RSA_free(rsa);
		}
	}

	/*
	 * If there is no certificate file on disk, we will be generating a self-signed certificate
	 * in the next step.  Therefore, if we have neither a CSR nor a certificate, generate
	 * the CSR in this step so that the next step may commence.
	 */
	if ( (access(CTDL_CER_PATH, R_OK) != 0) && (access(CTDL_CSR_PATH, R_OK) != 0) ) {
		syslog(LOG_INFO, "Generating a certificate signing request.\n");

		/*
		 * Read our key from the file.  No, we don't just keep this
		 * in memory from the above key-generation function, because
		 * there is the possibility that the key was already on disk
		 * and we didn't just generate it now.
		 */
		fp = fopen(CTDL_KEY_PATH, "r");
		if (fp) {
			rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
			fclose(fp);
		}

		if (rsa) {

			/** Create a public key from the private key */
			if (pk=EVP_PKEY_new(), pk != NULL) {
				EVP_PKEY_assign_RSA(pk, rsa);
				if (req = X509_REQ_new(), req != NULL) {
					const char *env;
					/* Set the public key */
					X509_REQ_set_pubkey(req, pk);
					X509_REQ_set_version(req, 0L);

					name = X509_REQ_get_subject_name(req);

					/* Tell it who we are */

					/*
					 * We used to add these fields to the subject, but
					 * now we don't.  Someone doing this for real isn't
					 * going to use the webcit-generated CSR anyway.
					 *
					X509_NAME_add_entry_by_txt(name, "C",
						MBSTRING_ASC, "US", -1, -1, 0);
					*
					X509_NAME_add_entry_by_txt(name, "ST",
						MBSTRING_ASC, "New York", -1, -1, 0);
					*
					X509_NAME_add_entry_by_txt(name, "L",
						MBSTRING_ASC, "Mount Kisco", -1, -1, 0);
					*/

					env = getenv("O");
					if (env == NULL)
						env = "Organization name",

					X509_NAME_add_entry_by_txt(
						name, "O",
						MBSTRING_ASC, 
						(unsigned char*)env, 
						-1, -1, 0
					);

					env = getenv("OU");
					if (env == NULL)
						env = "Citadel server";

					X509_NAME_add_entry_by_txt(
						name, "OU",
						MBSTRING_ASC, 
						(unsigned char*)env, 
						-1, -1, 0
					);

					env = getenv("CN");
					if (env == NULL)
						env = "*";

					X509_NAME_add_entry_by_txt(
						name, "CN",
						MBSTRING_ASC, 
						(unsigned char*)env,
						-1, -1, 0
					);
				
					X509_REQ_set_subject_name(req, name);

					/* Sign the CSR */
					if (!X509_REQ_sign(req, pk, EVP_md5())) {
						syslog(LOG_WARNING, "X509_REQ_sign(): error\n");
					}
					else {
						/* Write it to disk. */	
						fp = fopen(CTDL_CSR_PATH, "w");
						if (fp != NULL) {
							chmod(CTDL_CSR_PATH, 0600);
							PEM_write_X509_REQ(fp, req);
							fclose(fp);
						}
						else {
							syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_CSR_PATH);
							ShutDownWebcit();
							exit(0);
						}
					}

					X509_REQ_free(req);
				}
			}

			RSA_free(rsa);
		}

		else {
			syslog(LOG_WARNING, "Unable to read private key.\n");
		}
	}



	/*
	 * Generate a self-signed certificate if we don't have one.
	 */
	if (access(CTDL_CER_PATH, R_OK) != 0) {
		syslog(LOG_INFO, "Generating a self-signed certificate.\n");

		/* Same deal as before: always read the key from disk because
		 * it may or may not have just been generated.
		 */
		fp = fopen(CTDL_KEY_PATH, "r");
		if (fp) {
			rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
			fclose(fp);
		}

		/* This also holds true for the CSR. */
		req = NULL;
		cer = NULL;
		pk = NULL;
		if (rsa) {
			if (pk=EVP_PKEY_new(), pk != NULL) {
				EVP_PKEY_assign_RSA(pk, rsa);
			}

			fp = fopen(CTDL_CSR_PATH, "r");
			if (fp) {
				req = PEM_read_X509_REQ(fp, NULL, NULL, NULL);
				fclose(fp);
			}

			if (req) {
				if (cer = X509_new(), cer != NULL) {

					ASN1_INTEGER_set(X509_get_serialNumber(cer), 0);
					X509_set_issuer_name(cer, req->req_info->subject);
					X509_set_subject_name(cer, req->req_info->subject);
					X509_gmtime_adj(X509_get_notBefore(cer), 0);
					X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS);

					req_pkey = X509_REQ_get_pubkey(req);
					X509_set_pubkey(cer, req_pkey);
					EVP_PKEY_free(req_pkey);
					
					/* Sign the cert */
					if (!X509_sign(cer, pk, EVP_md5())) {
						syslog(LOG_WARNING, "X509_sign(): error\n");
					}
					else {
						/* Write it to disk. */	
						fp = fopen(CTDL_CER_PATH, "w");
						if (fp != NULL) {
							chmod(CTDL_CER_PATH, 0600);
							PEM_write_X509(fp, cer);
							fclose(fp);
						}
						else {
							syslog(LOG_WARNING, "Cannot write key: %s\n", CTDL_CER_PATH);
							ShutDownWebcit();
							exit(0);
						}
					}
					X509_free(cer);
				}
			}

			RSA_free(rsa);
		}
	}

	/*
	 * Now try to bind to the key and certificate.
	 * Note that we use SSL_CTX_use_certificate_chain_file() which allows
	 * the certificate file to contain intermediate certificates.
	 */
	SSL_CTX_use_certificate_chain_file(ssl_ctx, CTDL_CER_PATH);
	SSL_CTX_use_PrivateKey_file(ssl_ctx, CTDL_KEY_PATH, SSL_FILETYPE_PEM);
	if ( !SSL_CTX_check_private_key(ssl_ctx) ) {
		syslog(LOG_WARNING, "Cannot install certificate: %s\n",
				ERR_reason_error_string(ERR_get_error()));
	}
	
}
// reads the request req_filename and creates a modified creq_filename with the commitment extension added
void writeCommitmentCSR(BIGNUM *commitment_c, char *privkey_filename, char *req_filename, char *creq_filename) {
	FILE *fp;

	/* read in the request */
	X509_REQ *req;
	if (!(fp = fopen(req_filename, "r")))
		critical_error("Error reading request file");
	if (!(req = PEM_read_X509_REQ(fp, NULL, NULL, NULL)))
		critical_error("Error reading request in file");
	fclose(fp);

	/*  read in the private key */
	EVP_PKEY *pkey;
	if (!(fp = fopen(privkey_filename, "r")))
		critical_error("Error reading private key file");
	if (!(pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)))
		critical_error("Error reading private key in file");
	fclose(fp);

	/* create the new request */
	X509_REQ *creq;
	if (!(creq = X509_REQ_new()))
		critical_error("Failed to create X509_REQ object");

	X509_REQ_set_pubkey(creq, pkey);

	// gets subj from initial requests and adds it to new one
	X509_NAME *subj = X509_REQ_get_subject_name(req);
	if (X509_REQ_set_subject_name(creq, subj) != 1)
			critical_error("Error adding subject to request");

	// enable the commitment extension handling (retrieve/print as string)
	int nid = _commitmentExt_start();

	// get extensions stack of original request
	STACK_OF(X509_EXTENSION) *extlist = X509_REQ_get_extensions(req);

	// if no extensions, create new stack
	if (extlist==NULL) {
		extlist = sk_X509_EXTENSION_new_null();
	} else { // else check that the extension isn't already there (error!)
		X509_EXTENSION *tmp = (X509_EXTENSION*) X509V3_get_d2i(extlist, nid, NULL, NULL);
		if (tmp!=NULL)
			critical_error("Aborting process: CSR already contains commitment extension!\n");		
	}

	// create commitment extension storing C value as a hex string
	X509_EXTENSION *exCommitment = (X509_EXTENSION*) X509V3_EXT_conf_nid(NULL, NULL, nid, BN_bn2hex(commitment_c));
	if (!exCommitment)
		critical_error("error creating commitment extension");

	// push commitment extension into stack
	sk_X509_EXTENSION_push(extlist, exCommitment);

	// assign extensions to the new request
	if (!X509_REQ_add_extensions(creq, extlist))
		critical_error("Error adding extensions to the request");

	sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
	/////////////////////////////////////////////////////////////////////

	/* pick the correct digest and sign the new request */
	EVP_MD *digest;
	if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
		digest = (EVP_MD*) EVP_dss1();
	else if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA)
		digest = (EVP_MD*) EVP_sha1();
	else
		critical_error("Error checking public key for a valid digest");

	if (!(X509_REQ_sign(creq, pkey, digest)))
		critical_error("Error signing request");

	/* write the modified request */
	if (!(fp = fopen(creq_filename, "w")))
		critical_error("Error writing to request file");
	if (PEM_write_X509_REQ(fp, creq) != 1)
		critical_error("Error while writing request");
	fclose(fp);

	// cleanup
	_commitmentExt_end();
	EVP_PKEY_free(pkey);
	X509_REQ_free(req);
	X509_REQ_free(creq);
}
TU_RET TuProtocol::HandleCertRequest(
                            PTU_MEMBERINFO  pMemberInfo, 
                            uchar           *dataBuffer, 
                            UINT32          dataLen,
                            uchar           **message, 
                            UINT32          *msgLen)
{
    TU_RET err = TU_ERROR_CRYPTO_FAILED;
    tu_member *member;
    UINT32  hours;    
    char role[MAX_NAME_SIZE];
    char memberName[MAX_NAME_SIZE];
    UINT32 serialLen;
    uchar *serialCert;
    UINT32 CACertLength ;
    uchar *CACert;
    uchar *msgPtr;

    EVP_PKEY *pkey;
    X509_REQ *req;
    FILE *fp;

    pMemberInfo->state = State_App;

    //Store the data buffer into a temporary file to extract the request
    if(!(fp = fopen("protofile", "wb")))
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error opening file for writing Cert Request.\n"));
        err = TU_ERROR_FILEOPEN;
        goto EXIT;
    }

    fwrite(dataBuffer, 1, dataLen, fp);
    fclose(fp);

    if(!(fp = fopen("protofile", "r")))
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error opening file for reading Cert Request.\n"));
        err = TU_ERROR_FILEOPEN;
        goto EXIT;
    }

    if(!(req = PEM_read_X509_REQ(fp, NULL, NULL, NULL)))
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error reading Cert Request.\n"));
        fclose(fp);
        err = TU_ERROR_FILEREAD;
        goto EXIT;
    }

    fclose(fp);

//Amol
#if 0
    //verify the signature with the key we have stored
    DEVICE_NAME(pMemberInfo->domainName, pMemberInfo->Name);
    err = GetPublicKey(DEVICE_NAME_BUF, TU_KEY_SIGN, &pkey);
    if(TU_SUCCESS != err)
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error getting enrollee's public key.\n"));
        err = TU_ERROR_FILEOPEN;
        goto ERR_REQ;
    }
#endif

    if(!(pkey = X509_REQ_get_pubkey(req)))
    {
        ERR_print_errors_fp(stdout);
        TUTRACE((TUTRACE_ERR, "PROTO: Error extracting public key\n"));
        err = TU_ERROR_SIGN_VERIFY_FAILURE;
        goto ERR_PKEY;
    }

    if(X509_REQ_verify(req, pkey) != 1)
    {
        ERR_print_errors_fp(stdout);
        TUTRACE((TUTRACE_ERR, "PROTO: Verification failed for Cert Request.\n"));
        err = TU_ERROR_SIGN_VERIFY_FAILURE;
        goto ERR_PKEY;
    }

    if(pMemberInfo->role == guest)
    {
        hours = 24;
    }
    else
    {
        hours = 365*24;
    }

    //Finally, create a certificate
    err = m_pDomainMgr->SignAndStoreCertRequest(req, 
                                                pMemberInfo->pDomain, 
                                                hours,
                                                &serialCert,
                                                (unsigned long *)&serialLen);
    if(TU_SUCCESS != err)
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error signing Cert Request.\n"));
        goto ERR_PKEY;
    }

    //We now have the cert. Now serialize the CA cert
    //Open the CA cert file. The name can be derived from the device name 
    //stored in the oobData name
    FILE_CERT(pMemberInfo->oobData.name);
    if(!(fp = fopen(NAME_BUF, "rb")))
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error opening CA Cert file.\n"));
        err = TU_ERROR_FILEOPEN;
        goto ERR_CERT;
    }

    //Now check the size of the file
    fseek(fp, 0, SEEK_END);
    CACertLength = (UINT32)ftell(fp);
    if(CACertLength == (UINT32) -1)
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error getting CA Cert length.\n"));
        fclose(fp);
        err = TU_ERROR_FILEREAD;
        goto ERR_CERT;
    }

    CACert = (uchar *)calloc(CACertLength , 1);
    if(!CACert)
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error allocating memory for CA Cert.\n"));
        fclose(fp);
        err = TU_ERROR_OUT_OF_MEMORY;
        goto ERR_CERT;
    }

    rewind(fp);
    if(CACertLength != fread(CACert, 1, CACertLength, fp))
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error reading CA Cert.\n"));
        fclose(fp);
        err = TU_ERROR_FILEREAD;
        goto ERR_CA;
    }

    fclose(fp);

    //Now construct the certificate chain - we simply lump all certs together

    //copy the current certificate and its length in the message buffer
    //Also, allocate space for a message length at the start of the buffer
    *message = (uchar *)malloc(sizeof(UINT32) 
                               + sizeof(serialLen) 
                               + serialLen 
                               + sizeof(CACertLength) 
                               + CACertLength);
    if(!*message)
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error allocating memory.\n"));
        err = TU_ERROR_OUT_OF_MEMORY;
        goto ERR_CA;
    }

    //The structure of the message is: MessageLength|CertLen|Cert|CertLen|Cert...
    //The reason for having an extra message length is to help reassemble fragmented packets
    *msgLen = sizeof(UINT32) + sizeof(serialLen) + serialLen + sizeof(CACertLength) + CACertLength;
    
    msgPtr = *message;
    memcpy(msgPtr, msgLen, sizeof(UINT32));
    msgPtr += sizeof(UINT32);
    memcpy(msgPtr, &serialLen, sizeof(serialLen));
    msgPtr += sizeof(serialLen);
    memcpy(msgPtr, serialCert, serialLen);
    msgPtr += serialLen;
    memcpy(msgPtr, &CACertLength, sizeof(CACertLength));
    msgPtr += sizeof(CACertLength);
    memcpy(msgPtr, CACert, CACertLength);
    
    //TBD: Add a serial number...get the context, then extract the serial #
    err = m_pDomainMgr->AddMember(pMemberInfo->Name, 
                                  pMemberInfo->pDomain,
                                  (uchar *)&pMemberInfo->enrolleeAddr, 
                                  NULL, 
                                  &member);
    if(TU_SUCCESS != err)
    {
        TUTRACE((TUTRACE_ERR, "PROTO: Error Adding member.\n"));
        free(*message);
    }
    else
    {
        //Finally, notify the UI of the new member
        pUpdateCB(pMemberInfo->Name, pMemberInfo->pDomain->Name);
        err = TU_SUCCESS;
    }
  
ERR_CA:
    if(CACert)
        free(CACert);
ERR_CERT:
    if(serialCert)
        free(serialCert);
ERR_PKEY:
    EVP_PKEY_free(pkey);
ERR_REQ:
    X509_REQ_free(req);
EXIT:
    return err;
}//HandleCertRequest
		inline certificate_request certificate_request::from_certificate_request(file _file, pem_passphrase_callback_type callback, void* callback_arg)
		{
			return take_ownership(PEM_read_X509_REQ(_file.raw(), NULL, callback, callback_arg));
		}