// 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; }
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); }
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); }
/* * 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)); }