int signRequest(char* pemRequest, int days, char* pemCAKey, char* pemCaCert, int certType, char *url, char* result) { BIO* bioReq = BIO_new_mem_buf(pemRequest, -1); BIO* bioCAKey = BIO_new_mem_buf(pemCAKey, -1); BIO* bioCert = BIO_new_mem_buf(pemCaCert, -1); X509* caCert = PEM_read_bio_X509(bioCert, NULL, NULL, NULL); int err = 0; X509_REQ *req=NULL; if (!(req=PEM_read_bio_X509_REQ(bioReq, NULL, NULL, NULL))) { BIO_free(bioReq); BIO_free(bioCert); BIO_free(bioCAKey); return ERR_peek_error(); } EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioCAKey, NULL, NULL, NULL); if (!caKey) { BIO_free(bioReq); BIO_free(bioCert); BIO_free(bioCAKey); return ERR_peek_error(); } X509* cert = X509_new(); EVP_PKEY* reqPub; if(!(err = X509_set_version(cert, 2))) { BIO_free(bioReq); BIO_free(bioCAKey); return ERR_peek_error(); } //redo all the certificate details, because OpenSSL wants us to work hard X509_set_issuer_name(cert, X509_get_subject_name(caCert)); ASN1_UTCTIME *s=ASN1_UTCTIME_new(); // Jira-issue: WP-37 // This is temp solution for putting pzp validity 5 minutes before current time // If there is a small clock difference between machines, it results in cert_not_yet_valid // It does set GMT time but is relevant to machine time. // A better solution would be to have ntp server contacted to get a proper time. if(certType == 2) { X509_gmtime_adj(s, long(0-300)); } else { X509_gmtime_adj(s, long(0)); } // End of WP-37 X509_set_notBefore(cert, s); X509_gmtime_adj(s, (long)60*60*24*days); X509_set_notAfter(cert, s); ASN1_UTCTIME_free(s); X509_set_subject_name(cert, X509_REQ_get_subject_name(req)); reqPub = X509_REQ_get_pubkey(req); X509_set_pubkey(cert,reqPub); EVP_PKEY_free(reqPub); //create a serial number at random ASN1_INTEGER* serial = getRandomSN(); X509_set_serialNumber(cert, serial); X509_EXTENSION *ex; X509V3_CTX ctx; X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); char *str = (char*)malloc(strlen("caIssuers;") + strlen(url) + 1); if (str == NULL) { return -10; } strcpy(str, "caIssuers;"); strcat(str, url); if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_info_access, (char*)str))) { free(str); return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } free(str); if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, (char*)url))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_issuer_alt_name, (char*)"issuer:copy"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if( certType == 1) { if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:FALSE"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_ext_key_usage, (char*)"critical, clientAuth, serverAuth"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } } else if( certType == 2) { if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:FALSE"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_ext_key_usage, (char*)"critical, clientAuth, serverAuth"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } } if (!(err = X509_sign(cert,caKey,EVP_sha1()))) { BIO_free(bioReq); BIO_free(bioCert); BIO_free(bioCAKey); return err; } BIO *mem = BIO_new(BIO_s_mem()); PEM_write_bio_X509(mem,cert); BUF_MEM *bptr; BIO_get_mem_ptr(mem, &bptr); BIO_read(mem, result, bptr->length); BIO_free(mem); BIO_free(bioReq); BIO_free(bioCert); BIO_free(bioCAKey); return 0; }
int selfSignRequest(char* pemRequest, int days, char* pemCAKey, int certType, char *url, char* result) { BIO* bioReq = BIO_new_mem_buf(pemRequest, -1); BIO* bioCAKey = BIO_new_mem_buf(pemCAKey, -1); int err = 0; X509_REQ *req=NULL; if (!(req=PEM_read_bio_X509_REQ(bioReq, NULL, NULL, NULL))) { BIO_free(bioReq); BIO_free(bioCAKey); return -5; } EVP_PKEY* caKey = PEM_read_bio_PrivateKey(bioCAKey, NULL, NULL, NULL); if (!caKey) { BIO_free(bioReq); BIO_free(bioCAKey); return -6; } X509* cert = X509_new(); EVP_PKEY* reqPub; //redo all the certificate details, because OpenSSL wants us to work hard if(!(err = X509_set_version(cert, 2))) { BIO_free(bioReq); BIO_free(bioCAKey); return err; } if(!(err = X509_set_issuer_name(cert, X509_REQ_get_subject_name(req)))) { BIO_free(bioReq); BIO_free(bioCAKey); return err; } ASN1_UTCTIME *s=ASN1_UTCTIME_new(); // Jira-issue: WP-37 // This is temp solution for putting pzp validity 5 minutes before current time // If there is a small clock difference between machines, it results in cert_not_yet_valid // It does set GMT time but is relevant to machine time. // A better solution would be to have ntp server contacted to get proper time. if(certType == 2) { X509_gmtime_adj(s, long(0-300)); } else { X509_gmtime_adj(s, long(0)); } // End of WP-37 X509_set_notBefore(cert, s); X509_gmtime_adj(s, (long)60*60*24*days); X509_set_notAfter(cert, s); ASN1_UTCTIME_free(s); if(!(err = X509_set_subject_name(cert, X509_REQ_get_subject_name(req)))) { BIO_free(bioReq); BIO_free(bioCAKey); return err; } if (!(reqPub = X509_REQ_get_pubkey(req))) { BIO_free(bioReq); BIO_free(bioCAKey); return -7; } err = X509_set_pubkey(cert,reqPub); EVP_PKEY_free(reqPub); if (!err) { return err; // an error occurred, this is terrible style. } //create a serial number at random ASN1_INTEGER* serial = getRandomSN(); X509_set_serialNumber(cert, serial); // V3 extensions X509_EXTENSION *ex; X509V3_CTX ctx; X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_alt_name, (char*)url))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_subject_key_identifier, (char*)"hash"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if( certType == 0) { if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_basic_constraints, (char*)"critical, CA:TRUE"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_key_usage, (char*)"critical, keyCertSign, digitalSignature, cRLSign"))) { /* critical, keyCertSign,cRLSign, nonRepudiation,*/ return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_ext_key_usage, (char*)"critical, serverAuth"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_inhibit_any_policy, (char*)"0"))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } if(!(ex = X509V3_EXT_conf_nid(NULL, &ctx, NID_crl_distribution_points, (char*)url))) { return ERR_peek_error(); } else { X509_add_ext(cert, ex, -1); } } if (!(err = X509_sign(cert,caKey,EVP_sha1()))) { BIO_free(bioReq); BIO_free(bioCAKey); return err; } BIO *mem = BIO_new(BIO_s_mem()); PEM_write_bio_X509(mem,cert); BUF_MEM *bptr; BIO_get_mem_ptr(mem, &bptr); BIO_read(mem, result, bptr->length); BIO_free(mem); BIO_free(bioReq); BIO_free(bioCAKey); return 0; }
static int add_ext(X509 * crt, int nid, char *value) { X509_EXTENSION *ex; X509V3_CTX ctx; X509V3_set_ctx_nodb(&ctx); X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0); ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); if (!ex) return 0; X509_add_ext(crt, ex, -1); X509_EXTENSION_free(ex); return 1; }
/** * Adds a key usage extension to the list of extensions in a request. */ static X509_EXTENSION *makeKeyUsageExt(KeyUsage keyUsage) { char *ku_str; switch (keyUsage) { case KeyUsage_Signing: ku_str = "nonRepudiation"; break; case KeyUsage_Authentication: ku_str = "digitalSignature"; break; default: ku_str = NULL; } return X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, ku_str); }
/* * Set one extension in a given certificate */ static int set_extension(X509 * issuer, X509 * cert, int nid, char * value) { X509_EXTENSION * ext ; X509V3_CTX ctx ; X509V3_set_ctx(&ctx, issuer, cert, NULL, NULL, 0); ext = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); if (!ext) return -1; X509_add_ext(cert, ext, -1); X509_EXTENSION_free(ext); return 0 ; }
// Add extension using V3 code: we can set the config file as NULL because we wont reference any other sections. int __fastcall util_add_ext(X509 *cert, int nid, char *value) { X509_EXTENSION *ex; X509V3_CTX ctx; // This sets the 'context' of the extensions. No configuration database X509V3_set_ctx_nodb(&ctx); // Issuer and subject certs: both the target since it is self signed, no request and no CRL X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); if (!ex) return 0; X509_add_ext(cert,ex,-1); X509_EXTENSION_free(ex); return 1; }
/** * Returns true on success, false on failure * * Example: * @code * <#example#> * @endcode */ static bool _addCertificateExtensionWithContext(X509 *cert, int nid, char *value) { X509_EXTENSION *extension; X509V3_CTX context; X509V3_set_ctx_nodb(&context); X509V3_set_ctx(&context, cert, cert, NULL, NULL, 0); extension = X509V3_EXT_conf_nid(NULL, &context, nid, value); if (extension == NULL) { return false; } X509_add_ext(cert, extension, -1); X509_EXTENSION_free(extension); return true; }
void add_ext(X509 *cert, int nid, const char *value) { X509_EXTENSION *ex = NULL; X509V3_CTX ctx; /* This sets the 'context' of the extensions. */ /* No configuration database */ X509V3_set_ctx_nodb(&ctx); /* Issuer and subject certs: both the target since it is self signed, * no request and no CRL */ X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0); MORDOR_VERIFY(X509V3_EXT_conf_nid(NULL, &ctx, nid, (char*) value)); X509_add_ext(cert,ex,-1); X509_EXTENSION_free(ex); }
// verify if prefix is part of the resources listed in cert // CA and untrusted are needed, because the resources in cert could be inherited // prefix_as_ext is the text-representation of an ip-address block like you would specify in an extension file // when creating a certificate, e.g. IPv6:2001:0638::/32 int verify_prefix_with_cert( int CA_der_count, int CA_der_length, const char* CAs_der, int untrusted_der_count, int untrusted_der_length, const char* untrusted_der, int cert_der_length, const char* cert_der, char* prefix_as_ext ) { X509_EXTENSION *prefix_ext; IPAddrBlocks *prefix_blocks = NULL; STACK_OF(X509) *chain = NULL; int allow_inheritance = 0; // router prefix cannot inherit int ret = 0; if ((prefix_ext = X509V3_EXT_conf_nid(NULL, NULL, NID_sbgp_ipAddrBlock, prefix_as_ext)) == NULL){ ret = -1; goto end; } prefix_blocks = (IPAddrBlocks *) X509V3_EXT_d2i(prefix_ext); X509_EXTENSION_free(prefix_ext); chain = get_verified_chain( CA_der_count, CA_der_length, CAs_der, untrusted_der_count, untrusted_der_length, untrusted_der, cert_der_length, cert_der ); if (chain == NULL) { ret = 0; } else { ret = v3_addr_validate_resource_set(chain, prefix_blocks, allow_inheritance); } end: if (prefix_blocks != NULL) sk_IPAddressFamily_pop_free(prefix_blocks, IPAddressFamily_free); if (chain != NULL) sk_X509_pop_free(chain, X509_free); return ret; }
int add_ext( X509 *issuer, X509 *subj, int nid, const char* value ) { X509V3_CTX ctx; X509V3_set_ctx( &ctx, issuer, subj, NULL, NULL, 0 ); X509_EXTENSION *ex = X509V3_EXT_conf_nid( NULL, &ctx, nid, (char *) value ); if( !ex ) { return 0; } // removing old extensions of the same type int loc = -1; while( ( loc = X509_get_ext_by_NID(subj, nid, loc) ) != -1 ){ printf("Removing old extension number %d\n", loc); X509_EXTENSION *old = X509_delete_ext(subj, loc); X509_EXTENSION_free(old); } // adding the new extension X509_add_ext( subj, ex, -1 ); X509_EXTENSION_free( ex ); return 1; }
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); #endif if (!X509_REQ_sign(x,pk,EVP_md5())) goto err; *req=x; *pkeyp=pk; return(1); err: return(0); } /* Add extension using V3 code: we can set the config file as NULL * because we wont reference any other sections. */ int add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value) { X509_EXTENSION *ex; ex = X509V3_EXT_conf_nid(NULL, NULL, nid, value); if (!ex) return 0; sk_X509_EXTENSION_push(sk, ex); return 1; }
int32_t HttpsGenCertReq( HttpsCertReqInfo_t *pCertReqInfo, unsigned char *pPrivbuf, unsigned char *pCertbuf, HttpsCertReqParams_t *pParams ) { EVP_PKEY *pkey = NULL; HX509Req_t *preq = NULL; #ifdef OPENSSL_9_7 const EVP_MD *pDigest; #else EVP_MD *pDigest = NULL; #endif /*OPENSSL_9_7*/ int32_t iRetVal; unsigned char aSubAltName[HTTPS_PARAMS_SUB_NAME_LEN]; bool bFlag = FALSE; STACK_OF(X509_EXTENSION) *skExtensions = NULL; X509_EXTENSION *pSubExt = NULL; unsigned char ucCT; int32_t uileng; /** * Input Validations... */ if (pCertReqInfo == NULL) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Invalid parameters\n"); return OF_FAILURE; } /** * Allocate space for the public-private key pair.. */ if ((pkey = EVP_PKEY_new()) == NULL) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: MemAlloc failure\n"); return OF_FAILURE; } /** * Generate a public-private key pair.. */ switch (pCertReqInfo->usCertType) { case RSA_MD5: case RSA_SHA1: if ((pCertReqInfo->cr_params.rsa_params.usNumBits < MIN_KEY_LENGTH)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq : Invalid RSA parameters\n"); EVP_PKEY_free(pkey); return OF_FAILURE; } if (!EVP_PKEY_assign_RSA(pkey, RSA_generate_key(pCertReqInfo->cr_params.rsa_params.usNumBits, 0x10001, NULL, NULL))) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq: EVP_PKEY assign failed\n"); EVP_PKEY_free(pkey); return OF_FAILURE; } ucCT='r'; if (pCertReqInfo->usCertType == RSA_MD5) { pDigest = (EVP_MD *) EVP_md5(); } else { pDigest = (EVP_MD *) EVP_sha1(); } break; default: Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Invalid certificate type\n"); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * Prepare the Certificate Request.. */ if ((preq = HttpsCertReqNew()) == NULL) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: X509_req_new failed\n"); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * Version Number.. */ if (!ASN1_INTEGER_set(preq->req_info->version, 0L)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: ASN1_INTEGER_set failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * Subject Name...Filled with two RDNs... */ /** * RDN # 1 : Country Name... */ if (!Httpsadd_DN_object((HX509Name_t *) preq->req_info->subject, NULL, NULL, (char *) pParams->ucCn, NID_countryName, 2, 2)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Httpsadd_DN_object failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } #ifdef OPENSSL_9_7 if (NID_postalCode == 0) { NID_postalCode = OBJ_create("2.5.4.17", "2.5.4.17", "postal code attribute"); } #endif /** * RDN #New::2: Postal code... */ if (!Httpsadd_DN_object((HX509Name_t *) preq->req_info->subject, NULL, NULL, (char *) pParams->aPostalCode, NID_postalCode, 0, 10)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Httpsadd_DN_object failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * RDN #3: State.. */ if (!Httpsadd_DN_object((HX509Name_t *) preq->req_info->subject, NULL, NULL, (char *) pParams->aState, NID_stateOrProvinceName, 0, 50)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Httpsadd_DN_object failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * RDN #New::4: Locality Name... */ if (!Httpsadd_DN_object((HX509Name_t *) preq->req_info->subject, NULL, NULL, (char *) pParams->aCity, NID_localityName, 0, 50)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Httpsadd_DN_object failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * RDN #5 : Organization .. */ if (!Httpsadd_DN_object((HX509Name_t *) preq->req_info->subject, NULL, NULL, (char *) pParams->aOrg, NID_organizationName, 0, 50)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Httpsadd_DN_object failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * RDN #6 : Department .. */ if (!Httpsadd_DN_object((HX509Name_t *) preq->req_info->subject, NULL, NULL, (char *) pParams->aDept, NID_organizationalUnitName, 0, 50)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Httpsadd_DN_object failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * RDN #7 : Common Name (Subject)... */ if (!Httpsadd_DN_object((HX509Name_t *) preq->req_info->subject, NULL, NULL, (char *) pParams->ucSub, NID_commonName, 0, 50)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: Httpsadd_DN_object failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } of_memset( aSubAltName, 0, HTTPS_PARAMS_SUB_NAME_LEN); if (strlen((char *) pParams->aIpAddr)) { of_strcat((char *) aSubAltName, "IP:"); of_strcat((char *) aSubAltName, (char *) pParams->aIpAddr); bFlag = TRUE; } if (strlen((char *) pParams->aEmailId)) { if (bFlag) { of_strcat((char *) aSubAltName, ",email:"); } else { of_strcat((char *) aSubAltName, "email:"); } of_strcat((char *) aSubAltName, (char *) pParams->aEmailId); bFlag = TRUE; } if (strlen((char *) pParams->aDomain)) { if (bFlag) { of_strcat((char *) aSubAltName, ",DNS:"); } else { of_strcat((char *) aSubAltName, "DNS:"); } of_strcat((char *) aSubAltName, (char *) pParams->aDomain); bFlag = TRUE; } /** * Adding subject alt name extension to the request. */ if ( of_strlen((char *) aSubAltName)) { skExtensions = sk_X509_EXTENSION_new_null(); if (skExtensions == NULL) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: sk_X509_EXTENSION_new_null failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } pSubExt = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name, (char *) aSubAltName); if (pSubExt) { sk_X509_EXTENSION_push(skExtensions, pSubExt); } iRetVal = X509_REQ_add_extensions(preq, skExtensions); if (iRetVal == 0) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: X509_REQ_add_extensions failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } sk_X509_EXTENSION_pop_free(skExtensions, X509_EXTENSION_free); } /* strlen sub alt */ /** * Set the public key.. */ if (!X509_REQ_set_pubkey(preq, pkey)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: X509_REQ_sign failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * Sign the CertReq Info.. */ if (!X509_REQ_sign(preq, pkey, pDigest)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: X509_REQ_sign failed\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * Write the Private Key into the file... */ if (HttpsWritetoFile(pPrivbuf, HTTPS_PRIV_KEY, pkey, ucCT, pParams->aIdName)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: HttpsWritetoFile failed #1\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } /** * Write the Certificate Request into the file... */ if (HttpsWritetoFile(pCertbuf, HTTPS_CERT_REQ, preq, ucCT, pParams->aIdName)) { Trace(HTTPS_ID, TRACE_SEVERE, "HttpsGenCertReq:: HttpsWritetoFile failed #2\n"); HttpsDeleteCerts(pParams->aIdName, 's'); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } uileng=strlen((char *) pCertbuf); if (uileng > 2047) { Trace(HTTPS_ID, TRACE_SEVERE, "pCertbuf length exceeds 2k\n"); HttpsDeleteCerts(pParams->aIdName, 's'); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_FAILURE; } Trace(HTTPS_ID, TRACE_INFO, "Generation of Certificate Request done\n"); HttpsCertReqFree(preq); EVP_PKEY_free(pkey); return OF_SUCCESS; } /* HttpsGenCertReq() */
// Creates a X509 certificate, if rootcert is NULL this creates a root (self-signed) certificate. // Is the name parameter is NULL, the hex value of the hash of the public key will be the subject name. int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, int bits, int days, char* name, enum CERTIFICATE_TYPES certtype, struct util_cert* initialcert) { X509 *x = NULL; X509_EXTENSION *ex = NULL; EVP_PKEY *pk = NULL; RSA *rsa = NULL; X509_NAME *cname=NULL; X509 **x509p = NULL; EVP_PKEY **pkeyp = NULL; char hash[UTIL_HASHSIZE]; char serial[8]; char nameStr[(UTIL_HASHSIZE * 2) + 2]; BIGNUM *oBigNbr; CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); if (initialcert != NULL) { pk = X509_get_pubkey(initialcert->x509); rsa = EVP_PKEY_get1_RSA(initialcert->pkey); if ((x=X509_new()) == NULL) goto err; } else { if ((pkeyp == NULL) || (*pkeyp == NULL)) { if ((pk = EVP_PKEY_new()) == NULL) return 0; } else pk = *pkeyp; if ((x509p == NULL) || (*x509p == NULL)) { if ((x=X509_new()) == NULL) goto err; } else x = *x509p; oBigNbr = BN_new(); rsa = RSA_new(); BN_set_word(oBigNbr, RSA_F4); if (RSA_generate_key_ex(rsa, bits, oBigNbr, NULL) == -1) { RSA_free(rsa); BN_free(oBigNbr); abort(); goto err; } BN_free(oBigNbr); } if (!EVP_PKEY_assign_RSA(pk, rsa)) { RSA_free(rsa); abort(); goto err; } rsa = NULL; util_randomtext(8, serial); X509_set_version(x, 2); ASN1_STRING_set(X509_get_serialNumber(x), serial, 8); X509_gmtime_adj(X509_get_notBefore(x),(long)60*60*24*-2); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_set_pubkey(x, pk); // Set the subject name cname = X509_get_subject_name(x); if (name == NULL) { // Computer the hash of the public key util_sha256((char*)x->cert_info->key->public_key->data, x->cert_info->key->public_key->length, hash); util_tohex(hash, UTIL_HASHSIZE, nameStr); X509_NAME_add_entry_by_txt(cname,"CN", MBSTRING_ASC, (unsigned char*)nameStr, -1, -1, 0); } else { // 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(cname,"CN", MBSTRING_ASC, (unsigned char*)name, -1, -1, 0); } if (rootcert == NULL) { // Its self signed so set the issuer name to be the same as the subject. X509_set_issuer_name(x,cname); // Add various extensions: standard extensions util_add_ext(x, NID_basic_constraints, "critical,CA:TRUE"); util_add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign"); util_add_ext(x, NID_subject_key_identifier, "hash"); //util_add_ext(x, NID_netscape_cert_type, "sslCA"); //util_add_ext(x, NID_netscape_comment, "example comment extension"); if (!X509_sign(x, pk, EVP_sha256())) goto err; } else { // This is a sub-certificate cname=X509_get_subject_name(rootcert->x509); X509_set_issuer_name(x, cname); // Add usual cert stuff ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, "digitalSignature, keyEncipherment, keyAgreement"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); // Add usages: TLS server, TLS client, Intel(R) AMT Console //ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication, TLS Web Client Authentication, 2.16.840.1.113741.1.2.1, 2.16.840.1.113741.1.2.2"); if (certtype == CERTIFICATE_TLS_SERVER) { // TLS server ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); } else if (certtype == CERTIFICATE_TLS_CLIENT) { // TLS client ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Client Authentication"); X509_add_ext(x, ex, -1); X509_EXTENSION_free(ex); } if (!X509_sign(x, rootcert->pkey, EVP_sha256())) goto err; } cert->x509 = x; cert->pkey = pk; return(1); err: return(0); }
// 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); }
void X509V3_add_ext(X509V3_CTX *ctx, X509 *cert, int nid, char *value) { X509_EXTENSION *ex = X509V3_EXT_conf_nid(NULL, ctx, nid, value); X509_add_ext(cert, ex, -1); X509_EXTENSION_free(ex); }
int main() { EVP_PKEY *pKey; RSA *rsa; X509 *x509; X509_NAME *name; X509_EXTENSION *ex; FILE *fp; int KEY_SIZE = 2048; int days = 365; pKey = EVP_PKEY_new(); // Create a private key rsa = RSA_generate_key( KEY_SIZE, // Key length (bits) RSA_F4, // Exponent NULL, // Callback NULL // Callback argument ); EVP_PKEY_assign_RSA(pKey, rsa); x509 = X509_new(); X509_set_version(x509, 3); ASN1_INTEGER_set(X509_get_serialNumber(x509), 1); X509_gmtime_adj(X509_get_notBefore(x509), 0); X509_gmtime_adj(X509_get_notAfter(x509), (long)60 * 60 * 24 * days); X509_set_pubkey(x509, pKey); name = X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, "Wnmp", -1, -1, 0); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, "Wnmp", -1, -1, 0); X509_set_issuer_name(x509, name); ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_cert_type, "server"); X509_add_ext(x509, ex, -1); X509_EXTENSION_free(ex); ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_comment, "Wnmp by Kurt Cancemi"); X509_add_ext(x509, ex, -1); X509_EXTENSION_free(ex); ex = X509V3_EXT_conf_nid(NULL, NULL, NID_netscape_ssl_server_name, "localhost"); X509_add_ext(x509, ex, -1); X509_EXTENSION_free(ex); X509_sign(x509, pKey, EVP_sha1()); if (!(fp = fopen(KEY_PUB, "w"))) { printf("Error writing to public key file"); return -1; } if (PEM_write_X509(fp, x509) != 1) printf("Error while writing public key"); fclose(fp); if (!(fp = fopen(KEY_PRV, "w"))) { printf("Error writing to private key file"); return -1; } if (PEM_write_PrivateKey(fp, pKey, NULL, NULL, 0, NULL, NULL) != 1) printf("Error while writing private key"); fclose(fp); X509_free(x509); EVP_PKEY_free(pKey); return 0; }