extern "C" int32_t CryptoNative_ObjObj2Txt(char* buf, int32_t buf_len, const ASN1_OBJECT* a) { return OBJ_obj2txt(buf, buf_len, a, true); }
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a) { return OBJ_obj2txt(buf, buf_len, a, 0); }
/* Function: GetX509NameInfo Used by System.Security.Cryptography.X509Certificates' OpenSslX509CertificateReader as the entire implementation of X509Certificate2.GetNameInfo. Return values: NULL if the certificate is invalid or no name information could be found, otherwise a pointer to a memory-backed BIO structure which contains the answer to the GetNameInfo query */ extern BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32_t forIssuer) { static const char szOidUpn[] = "1.3.6.1.4.1.311.20.2.3"; if (!x509 || !x509->cert_info || nameType < NAME_TYPE_SIMPLE || nameType > NAME_TYPE_URL) { return NULL; } // Algorithm behaviors (pseudocode). When forIssuer is true, replace "Subject" with "Issuer" and // SAN (Subject Alternative Names) with IAN (Issuer Alternative Names). // // SimpleName: Subject[CN] ?? Subject[OU] ?? Subject[O] ?? Subject[E] ?? Subject.Rdns.FirstOrDefault() ?? // SAN.Entries.FirstOrDefault(type == GEN_EMAIL); // EmailName: SAN.Entries.FirstOrDefault(type == GEN_EMAIL) ?? Subject[E]; // UpnName: SAN.Entries.FirsOrDefaultt(type == GEN_OTHER && entry.AsOther().OID == szOidUpn).AsOther().Value; // DnsName: SAN.Entries.FirstOrDefault(type == GEN_DNS) ?? Subject[CN]; // DnsFromAlternativeName: SAN.Entries.FirstOrDefault(type == GEN_DNS); // UrlName: SAN.Entries.FirstOrDefault(type == GEN_URI); if (nameType == NAME_TYPE_SIMPLE) { X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject; if (name) { ASN1_STRING* cn = NULL; ASN1_STRING* ou = NULL; ASN1_STRING* o = NULL; ASN1_STRING* e = NULL; ASN1_STRING* firstRdn = NULL; // Walk the list backwards because it is stored in stack order for (int i = X509_NAME_entry_count(name) - 1; i >= 0; --i) { X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i); if (!entry) { continue; } ASN1_OBJECT* oid = X509_NAME_ENTRY_get_object(entry); ASN1_STRING* str = X509_NAME_ENTRY_get_data(entry); if (!oid || !str) { continue; } int nid = OBJ_obj2nid(oid); if (nid == NID_commonName) { // CN wins, so no need to keep looking. cn = str; break; } else if (nid == NID_organizationalUnitName) { ou = str; } else if (nid == NID_organizationName) { o = str; } else if (nid == NID_pkcs9_emailAddress) { e = str; } else if (!firstRdn) { firstRdn = str; } } ASN1_STRING* answer = cn; // If there was no CN, but there was something, then perform fallbacks. if (!answer && firstRdn) { answer = ou; if (!answer) { answer = o; } if (!answer) { answer = e; } if (!answer) { answer = firstRdn; } } if (answer) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, answer, 0); return b; } } } if (nameType == NAME_TYPE_SIMPLE || nameType == NAME_TYPE_DNS || nameType == NAME_TYPE_DNSALT || nameType == NAME_TYPE_EMAIL || nameType == NAME_TYPE_UPN || nameType == NAME_TYPE_URL) { int expectedType = -1; switch (nameType) { case NAME_TYPE_DNS: case NAME_TYPE_DNSALT: expectedType = GEN_DNS; break; case NAME_TYPE_SIMPLE: case NAME_TYPE_EMAIL: expectedType = GEN_EMAIL; break; case NAME_TYPE_UPN: expectedType = GEN_OTHERNAME; break; case NAME_TYPE_URL: expectedType = GEN_URI; break; } STACK_OF(GENERAL_NAME)* altNames = X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, NULL, NULL); if (altNames) { int i; for (i = 0; i < sk_GENERAL_NAME_num(altNames); ++i) { GENERAL_NAME* altName = sk_GENERAL_NAME_value(altNames, i); if (altName && altName->type == expectedType) { ASN1_STRING* str = NULL; switch (nameType) { case NAME_TYPE_DNS: case NAME_TYPE_DNSALT: str = altName->d.dNSName; break; case NAME_TYPE_SIMPLE: case NAME_TYPE_EMAIL: str = altName->d.rfc822Name; break; case NAME_TYPE_URL: str = altName->d.uniformResourceIdentifier; break; case NAME_TYPE_UPN: { OTHERNAME* value = altName->d.otherName; if (value) { // Enough more padding than szOidUpn that a \0 won't accidentally align char localOid[sizeof(szOidUpn) + 3]; int cchLocalOid = 1 + OBJ_obj2txt(localOid, sizeof(localOid), value->type_id, 1); if (sizeof(szOidUpn) == cchLocalOid && 0 == strncmp(localOid, szOidUpn, sizeof(szOidUpn))) { // OTHERNAME->ASN1_TYPE->union.field str = value->value->value.asn1_string; } } break; } } if (str) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, str, 0); sk_GENERAL_NAME_free(altNames); return b; } } } sk_GENERAL_NAME_free(altNames); } } if (nameType == NAME_TYPE_EMAIL || nameType == NAME_TYPE_DNS) { X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject; int expectedNid = NID_undef; switch (nameType) { case NAME_TYPE_EMAIL: expectedNid = NID_pkcs9_emailAddress; break; case NAME_TYPE_DNS: expectedNid = NID_commonName; break; } if (name) { // Walk the list backwards because it is stored in stack order for (int i = X509_NAME_entry_count(name) - 1; i >= 0; --i) { X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i); if (!entry) { continue; } ASN1_OBJECT* oid = X509_NAME_ENTRY_get_object(entry); ASN1_STRING* str = X509_NAME_ENTRY_get_data(entry); if (!oid || !str) { continue; } int nid = OBJ_obj2nid(oid); if (nid == expectedNid) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, str, 0); return b; } } } } return NULL; }
static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, int indent, unsigned long flags) { int i, prev = -1, orflags, cnt; int fn_opt, fn_nid; ASN1_OBJECT *fn; ASN1_STRING *val; X509_NAME_ENTRY *ent; char objtmp[80]; const char *objbuf; int outlen, len; char *sep_dn, *sep_mv, *sep_eq; int sep_dn_len, sep_mv_len, sep_eq_len; if (indent < 0) indent = 0; outlen = indent; if (!do_indent(io_ch, arg, indent)) return -1; switch (flags & XN_FLAG_SEP_MASK) { case XN_FLAG_SEP_MULTILINE: sep_dn = "\n"; sep_dn_len = 1; sep_mv = " + "; sep_mv_len = 3; break; case XN_FLAG_SEP_COMMA_PLUS: sep_dn = ","; sep_dn_len = 1; sep_mv = "+"; sep_mv_len = 1; indent = 0; break; case XN_FLAG_SEP_CPLUS_SPC: sep_dn = ", "; sep_dn_len = 2; sep_mv = " + "; sep_mv_len = 3; indent = 0; break; case XN_FLAG_SEP_SPLUS_SPC: sep_dn = "; "; sep_dn_len = 2; sep_mv = " + "; sep_mv_len = 3; indent = 0; break; default: return -1; } if (flags & XN_FLAG_SPC_EQ) { sep_eq = " = "; sep_eq_len = 3; } else { sep_eq = "="; sep_eq_len = 1; } fn_opt = flags & XN_FLAG_FN_MASK; cnt = X509_NAME_entry_count(n); for (i = 0; i < cnt; i++) { if (flags & XN_FLAG_DN_REV) ent = X509_NAME_get_entry(n, cnt - i - 1); else ent = X509_NAME_get_entry(n, i); if (prev != -1) { if (prev == X509_NAME_ENTRY_set(ent)) { if (!io_ch(arg, sep_mv, sep_mv_len)) return -1; outlen += sep_mv_len; } else { if (!io_ch(arg, sep_dn, sep_dn_len)) return -1; outlen += sep_dn_len; if (!do_indent(io_ch, arg, indent)) return -1; outlen += indent; } } prev = X509_NAME_ENTRY_set(ent); fn = X509_NAME_ENTRY_get_object(ent); val = X509_NAME_ENTRY_get_data(ent); fn_nid = OBJ_obj2nid(fn); if (fn_opt != XN_FLAG_FN_NONE) { int objlen, fld_len; if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); fld_len = 0; /* XXX: what should this be? */ objbuf = objtmp; } else { if (fn_opt == XN_FLAG_FN_SN) { fld_len = FN_WIDTH_SN; objbuf = OBJ_nid2sn(fn_nid); } else if (fn_opt == XN_FLAG_FN_LN) { fld_len = FN_WIDTH_LN; objbuf = OBJ_nid2ln(fn_nid); } else { fld_len = 0; /* XXX: what should this be? */ objbuf = ""; } } objlen = strlen(objbuf); if (!io_ch(arg, objbuf, objlen)) return -1; if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { if (!do_indent(io_ch, arg, fld_len - objlen)) return -1; outlen += fld_len - objlen; } if (!io_ch(arg, sep_eq, sep_eq_len)) return -1; outlen += objlen + sep_eq_len; } /* * If the field name is unknown then fix up the DER dump flag. We * might want to limit this further so it will DER dump on anything * other than a few 'standard' fields. */ if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) orflags = ASN1_STRFLGS_DUMP_ALL; else orflags = 0; len = do_print_ex(io_ch, arg, flags | orflags, val); if (len < 0) return -1; outlen += len; } return outlen; }
/** * Returns type of proxy certificate. * Valid values are: * NONE * CA * EEC * GT2_PROXY * RFC_PROXY * GT2_LIMITED_PROXY * RFC_LIMITED_PROXY * GT3_PROXY * GT3_LIMITED_PROXY */ proxy_type_t verify_type_of_proxy(X509 * cert) { #ifdef __func__ const char *logstr=__func__; #else const char *logstr="verify_type_of_proxy"; #endif proxy_type_t pt = NONE; char * cert_subjectdn = NULL; char * cert_issuerdn = NULL; char * tail_str = NULL; size_t len_subject_dn; size_t len_issuer_dn; X509_EXTENSION * pci_ext = NULL; PROXYCERTINFO * pci = NULL; PROXYPOLICY * policy = NULL; ASN1_OBJECT * policy_lang = NULL; int policy_nid; int myindex = -1; int i; char s[EXT_TEXT_LEN]; X509_EXTENSION *ex; /* Is it a CA certificate */ if (verify_x509IsCA(cert)) { /* verify_log (L_DEBUG, "%s: Detected CA certificate", logstr); */ pt = CA; goto finalize; } /* Check by OID */ for (i = 0; i < X509_get_ext_count(cert); ++i) { ex = X509_get_ext(cert, i); if (X509_EXTENSION_get_object(ex)) { OBJ_obj2txt(s, EXT_TEXT_LEN, X509_EXTENSION_get_object(ex), 1); if (strcmp(s, OID_RFC_PROXY) == 0) { pt = RFC_PROXY; /* Find index of OID_RFC_PROXY */ if((myindex = X509_get_ext_by_NID(cert, OBJ_txt2nid(OID_RFC_PROXY), -1)) != -1 && (pci_ext = X509_get_ext(cert,myindex)) && X509_EXTENSION_get_critical(pci_ext)) { if((pci = X509V3_EXT_d2i(pci_ext)) == NULL) { verify_error(logstr, "Can't convert DER encoded PROXYCERTINFO extension to internal form"); goto failure; } /* Pull a certificate policy from the extension, note: * pci!=NULL since we've checked that */ if( (policy = pci->policy) == NULL) { verify_error(logstr, "Can't get policy from PROXYCERTINFO extension"); goto failure; } /* Get policy language */ if( (policy_lang = policy->policy_language) == NULL) { verify_error(logstr, "Can't get policy language from PROXYCERTINFO extension"); goto failure; } /* Lang to NID, lang's NID holds RFC Proxy type, like limited. Impersonation is the default */ policy_nid = OBJ_obj2nid(policy_lang); if(policy_nid == OBJ_txt2nid(IMPERSONATION_PROXY_OID)) { pt = RFC_PROXY; } else if(policy_nid == OBJ_txt2nid(INDEPENDENT_PROXY_OID)) { pt = RFC_PROXY; } else if(policy_nid == OBJ_txt2nid(LIMITED_PROXY_OID)) { pt = RFC_LIMITED_PROXY; } else { /* RFC_RESTRICTED_PROXY */ pt = RFC_PROXY; } if(X509_get_ext_by_NID(cert, OBJ_txt2nid(OID_RFC_PROXY), myindex) != -1) { verify_error(logstr, "Found more than one PCI extension"); goto failure; } } goto finalize; } if (strcmp(s, OID_GLOBUS_PROXY_V3) == 0) { pt = GT3_PROXY; /* Find index of OID_GT3_PROXY - Don't make it search for critical extentions... VOMS doesn't set those. */ if((myindex = X509_get_ext_by_NID(cert, OBJ_txt2nid(OID_GLOBUS_PROXY_V3), -1)) != -1 && (pci_ext = X509_get_ext(cert,myindex))) { if((pci = X509V3_EXT_d2i(pci_ext)) == NULL) { verify_error(logstr, "Can't convert DER encoded PROXYCERTINFO extension to internal form"); goto failure; } /* Pull a certificate policy from the extension. Note: pci * != NULL since we've checked that */ if( (policy = pci->policy) == NULL) { verify_error(logstr, "Can't get policy from PROXYCERTINFO extension"); goto failure; } /* Get policy language */ if( (policy_lang = policy->policy_language) == NULL) { verify_error(logstr, "Can't get policy language from PROXYCERTINFO extension"); goto failure; } /* Lang to NID, lang's NID holds RFC Proxy type, like limited. Impersonation is the default */ policy_nid = OBJ_obj2nid(policy_lang); if(policy_nid == OBJ_txt2nid(IMPERSONATION_PROXY_OID)) { pt = GT3_PROXY; } else if(policy_nid == OBJ_txt2nid(INDEPENDENT_PROXY_OID)) { pt = GT3_PROXY; } else if(policy_nid == OBJ_txt2nid(LIMITED_PROXY_OID)) { pt = GT3_LIMITED_PROXY; } else { /* GT3_RESTRICTED_PROXY */ pt = GT3_PROXY; } if(X509_get_ext_by_NID(cert, OBJ_txt2nid(OID_GLOBUS_PROXY_V3), myindex) != -1) { verify_error(logstr, "Found more than one PCI extension"); goto failure; } } goto finalize; } if (strcmp(s, OID_GLOBUS_PROXY_V2) == 0) { pt = GT3_PROXY; /* Check for GT2_PROXY tail */ if (cert_subjectdn && (strlen(cert_subjectdn) > strlen("/cn=proxy")) && (tail_str = &cert_subjectdn[strlen(cert_subjectdn) - strlen("/cn=proxy")]) && (strcasecmp(tail_str, "/cn=proxy") == 0) ) { /* verify_log (L_DEBUG, "%s: Detected GT2 proxy certificate", logstr); */ pt = GT2_PROXY; goto finalize; } /* Check for GT2_LIMITED_PROXY tail */ if (cert_subjectdn && (strlen(cert_subjectdn) > strlen("/cn=limited proxy")) && (tail_str = &cert_subjectdn[strlen(cert_subjectdn) - strlen("/cn=limited proxy")]) && (strcasecmp(tail_str, "/cn=limited proxy") == 0) ) { /* verify_log (L_DEBUG, "%s: Detected GT2 limited proxy certificate", logstr); */ pt = GT2_LIMITED_PROXY; goto finalize; } verify_error(logstr, "Detected the Globus GT2 OID in the certificate, " "but seems to have a malformed Subject DN: \"%s\"", cert_subjectdn); goto failure; } } } /* Options left: GT2_PROXY, GT2_LIMITED_PROXY, EEC */ /* Extract Subject DN - Needs free */ if (!(cert_subjectdn = X509_NAME_oneline (X509_get_subject_name (cert), NULL, 0))) { verify_error (logstr, "Error in %s: Couldn't get the subject DN from the certificate.", logstr); goto failure; } if (!(cert_issuerdn = X509_NAME_oneline (X509_get_issuer_name (cert), NULL, 0))) { verify_error (logstr, "Error in %s: Couldn't get the issuer DN from the certificate.", logstr); goto failure; } /* Check length of the DNs */ len_subject_dn = strlen(cert_subjectdn); len_issuer_dn = strlen(cert_issuerdn); /* Lower case the Subject DN */ /* for (j = 0; j < strlen(cert_subjectdn); j++) { cert_subjectdn[j] = tolower(cert_subjectdn[j]); } */ /* Proxies always has a longer subject_dn then a issuer_dn and * the issuer_dn is a substring of the subject_dn */ if ( (len_issuer_dn < len_subject_dn) && (strncmp(cert_subjectdn, cert_issuerdn, len_issuer_dn) == 0) ) { /* Check for GT2_PROXY tail */ if (cert_subjectdn && (strlen(cert_subjectdn) > strlen("/cn=proxy")) && (tail_str = &cert_subjectdn[strlen(cert_subjectdn) - strlen("/cn=proxy")]) && (strcasecmp(tail_str, "/cn=proxy") == 0) ) { /* verify_log (L_DEBUG, "%s: Detected GT2 proxy certificate", logstr); */ pt = GT2_PROXY; goto finalize; } /* Check for GT2_LIMITED_PROXY tail */ if (cert_subjectdn && (strlen(cert_subjectdn) > strlen("/cn=limited proxy")) && (tail_str = &cert_subjectdn[strlen(cert_subjectdn) - strlen("/cn=limited proxy")]) && (strcasecmp(tail_str, "/cn=limited proxy") == 0) ) { /* verify_log (L_DEBUG, "%s: Detected GT2 limited proxy certificate", logstr); */ pt = GT2_LIMITED_PROXY; goto finalize; } /* Check for RFC_PROXY, without the need for OpenSSL proxy support */ /* Method: Check if the subject_dn is long enough, grab its tail and * snip of the 10 characters. Then check if the 10 characters are * numbers. */ if (cert_subjectdn && (strlen(cert_subjectdn) > strlen("/cn=0123456789")) && (tail_str = strrchr(cert_subjectdn, '=')) && (tail_str = &tail_str[1]) && (strtol(tail_str, NULL, 10)) && (errno != ERANGE) ) { /* verify_log (L_DEBUG, "%s: Detected RFC proxy certificate", logstr); */ pt = RFC_PROXY; goto finalize; } /* Don't know the type of proxy, could be an RFC proxy with * improper/incomplete implementation in the active OpenSSL version or * a mistake in the client software */ goto failure; } /* I have no idea what else it is, so I conclude that it's an EEC */ pt = EEC; goto finalize; failure: /* On failure, or non-distinct selections of the certificate, indicate NONE */ pt = NONE; finalize: if (cert_subjectdn) free(cert_subjectdn); if (cert_issuerdn) free(cert_issuerdn); return pt; }
int genrequest(char department[], char cname0[]) { X509_REQ *webrequest = NULL; EVP_PKEY *pubkey = NULL; X509_NAME *reqname = NULL; DSA *mydsa = NULL; RSA *myrsa = NULL; BIO *outbio = NULL; X509_NAME_ENTRY *e; int i; FILE *fp, *fp2; char buf[80] = ""; char country[81] = "UK"; char province[81] = "Gloucestershire"; char locality[81] = "Tetbury"; char organisation[81] = "TETBURY SOFTWARE SERVICES Ltd"; char email_addr[81] = "*****@*****.**"; char cname1[81] = ""; char cname2[81] = ""; char surname[81] = ""; char givenname[81] = ""; char keytype[81] = "rsa"; int rsastrength = 4096; int dsastrength = 0; /* we do not accept requests with no data, i.e. being empty with just a public key. Although technically possible to sign and create a cert, they don't make much sense. We require here at least one CN supplied. */ if(strlen(cname0) == 0 && strlen(cname1) == 0 && strlen(cname2) == 0) printf("Error supply at least one CNAME in request subject"); /* -------------------------------------------------------------------------- * * These function calls are essential to make many PEM + other openssl * * functions work. It is not well documented, I found out after looking into * * the openssl source directly. * * needed by: PEM_read_PrivateKey(), X509_REQ_verify() ... * * -------------------------------------------------------------------------- */ OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); /* ------------------------------------------------------------------------- * * Generate the key pair based on the selected keytype * * ------------------------------------------------------------------------- */ if ((pubkey=EVP_PKEY_new()) == NULL) printf("Error creating EVP_PKEY structure."); if(strcmp(keytype, "rsa") == 0) { myrsa = RSA_new(); if (! (myrsa = RSA_generate_key(rsastrength, RSA_F4, NULL, NULL))) printf("Error generating the RSA key."); if (!EVP_PKEY_assign_RSA(pubkey,myrsa)) printf("Error assigning RSA key to EVP_PKEY structure."); } else if(strcmp(keytype, "dsa") == 0) { mydsa = DSA_new(); mydsa = DSA_generate_parameters(dsastrength, NULL, 0, NULL, NULL, NULL, NULL); if (! (DSA_generate_key(mydsa))) printf("Error generating the DSA key."); if (!EVP_PKEY_assign_DSA(pubkey,mydsa)) printf("Error assigning DSA key to EVP_PKEY structure."); } else printf("Error: Wrong keytype - choose either RSA or DSA."); /* ------------------------------------------------------------------------- * * Generate the certificate request from scratch * * ------------------------------------------------------------------------- */ if ((webrequest=X509_REQ_new()) == NULL) printf("Error creating new X509_REQ structure."); if (X509_REQ_set_pubkey(webrequest, pubkey) == 0) printf("Error setting public key for X509_REQ structure."); if ((reqname=X509_REQ_get_subject_name(webrequest)) == NULL) printf("Error setting public key for X509_REQ structure."); /* The following functions create and add the entries, working out * * the correct string type and performing checks on its length. * * We also check the return value for errors... */ if(strlen(country) != 0) X509_NAME_add_entry_by_txt(reqname,"C", MBSTRING_ASC, (unsigned char*) country, -1, -1, 0); if(strlen(province) != 0) X509_NAME_add_entry_by_txt(reqname,"ST", MBSTRING_ASC, (unsigned char *) province, -1, -1, 0); if(strlen(locality) != 0) X509_NAME_add_entry_by_txt(reqname,"L", MBSTRING_ASC, (unsigned char *) locality, -1, -1, 0); if(strlen(organisation) != 0) X509_NAME_add_entry_by_txt(reqname,"O", MBSTRING_ASC, (unsigned char *) organisation, -1, -1, 0); if(strlen(department) != 0) X509_NAME_add_entry_by_txt(reqname,"OU", MBSTRING_ASC, (unsigned char *) department, -1, -1, 0); if(strlen(email_addr) != 0) X509_NAME_add_entry_by_txt(reqname,"emailAddress", MBSTRING_ASC, (unsigned char *) email_addr, -1, -1, 0); if(strlen(cname0) != 0) X509_NAME_add_entry_by_txt(reqname,"CN", MBSTRING_ASC, (unsigned char *) cname0, -1, -1, 0); if(strlen(cname1) != 0) X509_NAME_add_entry_by_txt(reqname,"CN", MBSTRING_ASC, (unsigned char *) cname1, -1, -1, 0); if(strlen(cname2) != 0) X509_NAME_add_entry_by_txt(reqname,"CN", MBSTRING_ASC, (unsigned char *) cname2, -1, -1, 0); if(strlen(surname) != 0) X509_NAME_add_entry_by_txt(reqname,"SN", MBSTRING_ASC, (unsigned char *) surname, -1, -1, 0); if(strlen(givenname) != 0) X509_NAME_add_entry_by_txt(reqname,"GN", MBSTRING_ASC, (unsigned char *) givenname, -1, -1, 0); /* ------------------------------------------------------------------------- * * Sign the certificate request: md5 for RSA keys, dss for DSA keys * * ------------------------------------------------------------------------- */ if(strcmp(keytype, "rsa") == 0) { if (!X509_REQ_sign(webrequest,pubkey,EVP_md5())) printf("Error MD5 signing X509_REQ structure."); } else if(strcmp(keytype, "dsa") == 0) { if (!X509_REQ_sign(webrequest,pubkey,EVP_dss())) printf("Error DSS signing X509_REQ structure."); } /* ------------------------------------------------------------------------- * * and sort out the content plus start the html output * * ------------------------------------------------------------------------- */ if (! (fp=fopen("clave_publica.pem", "w"))) printf("No puedo crear el fichero de la request"); if (! (fp2=fopen("clave_privada.pem", "w"))) printf("No puedo crear el fichero de la clave privada"); outbio = BIO_new(BIO_s_file()); BIO_set_fp(outbio, fp, BIO_NOCLOSE); if (! PEM_write_bio_X509_REQ(outbio, webrequest)) printf("Error printing the request"); for (i = 0; i < X509_NAME_entry_count(reqname); i++) { e = X509_NAME_get_entry(reqname, i); OBJ_obj2txt(buf, 80, e->object, 0); } PEM_write_PrivateKey(fp2,pubkey,NULL,NULL,0,0,NULL); BIO_free(outbio); fclose(fp); fclose(fp2); return(0); }
/** * Read the secret key out of the encrypted file. * * This function needs its name corrected and rewritten. * * Example: * @code * <#example#> * @endcode */ static PARCBuffer * _AESKeyStoreInit(const char *filename, const char *password) { PARCBuffer *secret_key = NULL; FILE *fp = NULL; _PARCSymmeticSignerFileStoreInfo *ki = NULL; int version; char oidstr[80]; PARCBuffer *aes_key = NULL; PARCBuffer *mac_key = NULL; unsigned char check[SHA256_DIGEST_LENGTH]; unsigned char *keybuf = NULL; int check_start; EVP_CIPHER_CTX ctx; int length = 0; int final_length = 0; fp = fopen(filename, "rb"); if (fp == NULL) { goto Bail; } ki = _d2iAESKeystoreFp(fp, NULL); fclose(fp); if (ki == NULL) { goto Bail; } version = (int) ASN1_INTEGER_get(ki->version); if (version != AES_KEYSTORE_VERSION) { goto Bail; } OBJ_obj2txt(oidstr, sizeof(oidstr), ki->algorithm_oid, 0); if (strcasecmp(oidstr, AES_DEFAULT_DIGEST_ALGORITHM)) { goto Bail; } if (ki->encrypted_key->length < IV_SIZE + (SHA256_DIGEST_LENGTH * 2) + AES_BLOCK_SIZE) { goto Bail; } aes_key = _createDerivedKey(password, strlen(password), (unsigned char *) "\0", 1); mac_key = _createDerivedKey(password, strlen(password), (unsigned char *) "\1", 1); check_start = ki->encrypted_key->length - SHA256_DIGEST_LENGTH; HMAC(EVP_sha256(), parcByteArray_Array(parcBuffer_Array(mac_key)), SHA256_DIGEST_LENGTH, ki->encrypted_key->data, check_start, check, NULL); if (memcmp(&ki->encrypted_key->data[check_start], check, SHA256_DIGEST_LENGTH)) { goto Bail; } keybuf = malloc(SHA256_DIGEST_LENGTH + AES_BLOCK_SIZE); EVP_CIPHER_CTX_init(&ctx); if (!EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), parcByteArray_Array(parcBuffer_Array(aes_key)), ki->encrypted_key->data)) { goto Bail; } if (!EVP_DecryptUpdate(&ctx, keybuf, &length, &ki->encrypted_key->data[IV_SIZE], ki->encrypted_key->length - IV_SIZE - SHA256_DIGEST_LENGTH)) { goto Bail; } if (!EVP_DecryptFinal(&ctx, keybuf + length, &final_length)) { goto Bail; } secret_key = parcBuffer_CreateFromArray(keybuf, length); parcBuffer_Flip(secret_key); goto out; Bail: free(keybuf); out: if (aes_key) { parcBuffer_Release(&aes_key); } if (mac_key) { parcBuffer_Release(&mac_key); } return secret_key; }