int mono_btls_ssl_ctx_set_client_ca_list (MonoBtlsSslCtx *ctx, int count, int *sizes, const void **data) { STACK_OF(X509_NAME) *name_list; int i; name_list = sk_X509_NAME_new_null (); if (!name_list) return 0; for (i = 0; i < count; i++) { X509_NAME *name; const unsigned char *ptr = (const unsigned char*)data[i]; name = d2i_X509_NAME (NULL, &ptr, sizes[i]); if (!name) { sk_X509_NAME_pop_free (name_list, X509_NAME_free); return 0; } sk_X509_NAME_push (name_list, name); } // Takes ownership of the list. SSL_CTX_set_client_CA_list (ctx->ctx, name_list); return 1; }
static int openssl_xname_d2i(lua_State*L) { size_t len; const unsigned char* dat = luaL_checklstring(L, 1, &len); X509_NAME* xn = d2i_X509_NAME(NULL, &dat, len); if (xn) PUSH_OBJECT(xn,"openssl.x509_name"); else openssl_pushresult(L, 0); return 1; };
MONO_API MonoBtlsX509Name * mono_btls_x509_name_from_data (const void *data, int len, int use_canon_enc) { MonoBtlsX509Name *name; uint8_t *buf; const unsigned char *ptr; X509_NAME *ret; name = OPENSSL_malloc (sizeof (MonoBtlsX509Name)); if (!name) return NULL; memset (name, 0, sizeof(MonoBtlsX509Name)); name->owns = 1; name->name = X509_NAME_new (); if (!name->name) { OPENSSL_free (name); return NULL; } if (use_canon_enc) { CBB cbb, contents; size_t buf_len; // re-add ASN1 SEQUENCE header. CBB_init(&cbb, 0); if (!CBB_add_asn1(&cbb, &contents, 0x30) || !CBB_add_bytes(&contents, data, len) || !CBB_finish(&cbb, &buf, &buf_len)) { CBB_cleanup (&cbb); mono_btls_x509_name_free (name); return NULL; } ptr = buf; len = (int)buf_len; } else { ptr = data; buf = NULL; } ret = d2i_X509_NAME (&name->name, &ptr, len); if (buf) OPENSSL_free (buf); if (ret != name->name) { mono_btls_x509_name_free (name); return NULL; } return name; }
static std::string ParseSubject ( IN const void * const p, IN const unsigned s ) { char szSubject[1024]; bool fOK = false; #if defined(_WIN32) CRYPT_DER_BLOB blobSubject = {s, (PBYTE)p}; if ( CertNameToStrA ( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &blobSubject, CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, szSubject, sizeof (szSubject) ) != 0 ) { fOK = true; } #else X509_NAME *name; name = X509_NAME_new (); if (name != NULL) { pkcs11_openssl_d2i_t pp = (pkcs11_openssl_d2i_t)p; if ( d2i_X509_NAME ( &name, &pp, s ) ) { X509_NAME_oneline ( name, szSubject, sizeof (szSubject) ); fOK = true; } X509_NAME_free (name); } #endif if (fOK) { return szSubject; } else { return "ERROR"; } }
char * ca_asn1_name(uint8_t *asn1, size_t len) { X509_NAME *name = NULL; char *str = NULL; const uint8_t *p; p = asn1; if ((name = d2i_X509_NAME(NULL, &p, len)) == NULL) return (NULL); str = ca_x509_name(name); X509_NAME_free(name); return (str); }
void print_dn(FILE *f, CK_ULONG type, CK_VOID_PTR value, CK_ULONG size, CK_VOID_PTR arg) { print_generic(f, type, value, size, arg); #ifdef HAVE_OPENSSL if(size && value) { X509_NAME *name; name = d2i_X509_NAME(NULL, (const unsigned char **)&value, size); if(name) { BIO *bio = BIO_new(BIO_s_file()); BIO_set_fp(bio, f, BIO_NOCLOSE); fprintf(f, " DN: "); X509_NAME_print(bio, name, XN_FLAG_RFC2253); fprintf(f, "\n"); BIO_free(bio); } } #endif }
char * x509_DN_string(u_int8_t *asn1, size_t sz) { X509_NAME *name; u_int8_t *p = asn1; char buf[256]; /* XXX Just a guess at a maximum length. */ name = d2i_X509_NAME(NULL, &p, sz); if (!name) { log_print("x509_DN_string: d2i_X509_NAME failed"); return 0; } if (!X509_NAME_oneline(name, buf, sizeof buf - 1)) { log_print("x509_DN_string: X509_NAME_oneline failed"); X509_NAME_free(name); return 0; } X509_NAME_free(name); buf[sizeof buf - 1] = '\0'; return strdup(buf); }
/* check if subject from cert matches the id */ int ca_x509_subject_cmp(X509 *cert, struct iked_static_id *id) { X509_NAME *subject, *idname = NULL; const uint8_t *idptr; size_t idlen; int ret = -1; if (id->id_type != IKEV2_ID_ASN1_DN) return (-1); if ((subject = X509_get_subject_name(cert)) == NULL) return (-1); if (id->id_length <= id->id_offset) return (-1); idlen = id->id_length - id->id_offset; idptr = id->id_data + id->id_offset; if ((idname = d2i_X509_NAME(NULL, &idptr, idlen)) == NULL) return (-1); if (X509_NAME_cmp(subject, idname) == 0) ret = 0; X509_NAME_free(idname); return (ret); }
static int autoca_gencert( Operation *op, genargs *args ) { X509_NAME *subj_name, *issuer_name; X509 *subj_cert; struct berval derdn; unsigned char *pp; EVP_PKEY *evpk = NULL; int rc; if ((subj_cert = X509_new()) == NULL) return -1; autoca_dnbv2der( op, args->subjectDN, &derdn ); pp = (unsigned char *)derdn.bv_val; subj_name = d2i_X509_NAME( NULL, (const unsigned char **)&pp, derdn.bv_len ); op->o_tmpfree( derdn.bv_val, op->o_tmpmemctx ); if ( subj_name == NULL ) { fail1: X509_free( subj_cert ); return -1; } rc = autoca_genpkey( args->keybits, &evpk ); if ( rc <= 0 ) { fail2: if ( subj_name ) X509_NAME_free( subj_name ); goto fail1; } /* encode DER in PKCS#8 */ { PKCS8_PRIV_KEY_INFO *p8inf; if (( p8inf = EVP_PKEY2PKCS8( evpk )) == NULL ) goto fail2; args->derpkey.bv_len = i2d_PKCS8_PRIV_KEY_INFO( p8inf, NULL ); args->derpkey.bv_val = op->o_tmpalloc( args->derpkey.bv_len, op->o_tmpmemctx ); pp = (unsigned char *)args->derpkey.bv_val; i2d_PKCS8_PRIV_KEY_INFO( p8inf, &pp ); PKCS8_PRIV_KEY_INFO_free( p8inf ); } args->newpkey = evpk; /* set random serial */ { BIGNUM *bn = BN_new(); if ( bn == NULL ) { fail3: EVP_PKEY_free( evpk ); goto fail2; } if (!BN_pseudo_rand(bn, SERIAL_BITS, 0, 0)) { BN_free( bn ); goto fail3; } if (!BN_to_ASN1_INTEGER(bn, X509_get_serialNumber(subj_cert))) { BN_free( bn ); goto fail3; } BN_free(bn); } if (args->issuer_cert) { issuer_name = X509_get_subject_name(args->issuer_cert); } else { issuer_name = subj_name; args->issuer_cert = subj_cert; args->issuer_pkey = evpk; } if (!X509_set_version(subj_cert, 2) || /* set version to V3 */ !X509_set_issuer_name(subj_cert, issuer_name) || !X509_set_subject_name(subj_cert, subj_name) || !X509_gmtime_adj(X509_get_notBefore(subj_cert), 0) || !X509_time_adj_ex(X509_get_notAfter(subj_cert), args->days, 0, NULL) || !X509_set_pubkey(subj_cert, evpk)) { goto fail3; } X509_NAME_free(subj_name); subj_name = NULL; /* set cert extensions */ { X509V3_CTX ctx; X509_EXTENSION *ext; int i; X509V3_set_ctx(&ctx, args->issuer_cert, subj_cert, NULL, NULL, 0); for (i=0; args->cert_exts[i].name; i++) { ext = X509V3_EXT_nconf(NULL, &ctx, args->cert_exts[i].name, args->cert_exts[i].value); if ( ext == NULL ) goto fail3; rc = X509_add_ext(subj_cert, ext, -1); X509_EXTENSION_free(ext); if ( !rc ) goto fail3; } if (args->more_exts) { for (i=0; args->more_exts[i].name; i++) { ext = X509V3_EXT_nconf(NULL, &ctx, args->more_exts[i].name, args->more_exts[i].value); if ( ext == NULL ) goto fail3; rc = X509_add_ext(subj_cert, ext, -1); X509_EXTENSION_free(ext); if ( !rc ) goto fail3; } } } rc = autoca_signcert( subj_cert, args->issuer_pkey ); if ( rc < 0 ) goto fail3; args->dercert.bv_len = i2d_X509( subj_cert, NULL ); args->dercert.bv_val = op->o_tmpalloc( args->dercert.bv_len, op->o_tmpmemctx ); pp = (unsigned char *)args->dercert.bv_val; i2d_X509( subj_cert, &pp ); args->newcert = subj_cert; return 0; }
int ca_validate_cert(struct iked *env, struct iked_static_id *id, void *data, size_t len) { struct ca_store *store = env->sc_priv; X509_STORE_CTX csc; BIO *rawcert = NULL; X509 *cert = NULL; int ret = -1, result, error; size_t idlen, idoff; const u_int8_t *idptr; X509_NAME *idname = NULL, *subject; const char *errstr = "failed"; if (len == 0) { /* Data is already an X509 certificate */ cert = (X509 *)data; } else { /* Convert data to X509 certificate */ if ((rawcert = BIO_new_mem_buf(data, len)) == NULL) goto done; if ((cert = d2i_X509_bio(rawcert, NULL)) == NULL) goto done; } /* Certificate needs a valid subjectName */ if ((subject = X509_get_subject_name(cert)) == NULL) { errstr = "invalid subject"; goto done; } if (id != NULL) { if ((ret = ca_validate_pubkey(env, id, X509_get_pubkey(cert), 0)) == 0) { errstr = "public key found, ok"; goto done; } switch (id->id_type) { case IKEV2_ID_ASN1_DN: idoff = id->id_offset; if (id->id_length <= idoff) { errstr = "invalid ASN1_DN id length"; goto done; } idlen = id->id_length - idoff; idptr = id->id_data + idoff; if ((idname = d2i_X509_NAME(NULL, &idptr, idlen)) == NULL || X509_NAME_cmp(subject, idname) != 0) { errstr = "ASN1_DN identifier mismatch"; goto done; } break; default: if (ca_x509_subjectaltname_cmp(cert, id) != 0) { errstr = "invalid subjectAltName extension"; goto done; } break; } } bzero(&csc, sizeof(csc)); X509_STORE_CTX_init(&csc, store->ca_cas, cert, NULL); if (store->ca_cas->param->flags & X509_V_FLAG_CRL_CHECK) { X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK); X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL); } result = X509_verify_cert(&csc); error = csc.error; X509_STORE_CTX_cleanup(&csc); if (error != 0) { errstr = X509_verify_cert_error_string(error); goto done; } if (!result) { /* XXX should we accept self-signed certificates? */ errstr = "rejecting self-signed certificate"; goto done; } /* Success */ ret = 0; done: if (cert != NULL) log_debug("%s: %s %.100s", __func__, cert->name, ret == 0 ? "ok" : errstr); if (idname != NULL) X509_NAME_free(idname); if (rawcert != NULL) { BIO_free(rawcert); if (cert != NULL) X509_free(cert); } return (ret); }