int CA_set_key(const EAC_CTX *ctx, const unsigned char *priv, size_t priv_len, const unsigned char *pub, size_t pub_len) { int r = 0; const unsigned char *p = priv; EVP_PKEY *key = NULL; check(ctx && ctx->ca_ctx && ctx->ca_ctx->ka_ctx, "Invalid arguments"); /* always try d2i_AutoPrivateKey as priv may contain domain parameters */ if (priv && d2i_AutoPrivateKey(&key, &p, priv_len)) { EVP_PKEY_free(ctx->ca_ctx->ka_ctx->key); ctx->ca_ctx->ka_ctx->key = key; if (pub) { /* it's OK if import of public key fails */ EVP_PKEY_set_keys(key, NULL, 0, pub, pub_len, ctx->bn_ctx); } } else { /* wipe errors from d2i_AutoPrivateKey() */ ERR_clear_error(); check(EVP_PKEY_set_keys(ctx->ca_ctx->ka_ctx->key, priv, priv_len, pub, pub_len, ctx->bn_ctx), "no valid keys given"); } r = 1; err: return r; }
static int test_d2i_AutoPrivateKey(const unsigned char *input, size_t input_len, int expected_id) { int ret = 0; const unsigned char *p; EVP_PKEY *pkey = NULL; p = input; pkey = d2i_AutoPrivateKey(NULL, &p, input_len); if (pkey == NULL || p != input + input_len) { fprintf(stderr, "d2i_AutoPrivateKey failed\n"); goto done; } if (EVP_PKEY_id(pkey) != expected_id) { fprintf(stderr, "Did not decode expected type\n"); goto done; } ret = 1; done: if (!ret) { ERR_print_errors_fp(stderr); } EVP_PKEY_free(pkey); return ret; }
int EAC_CTX_init_ta(const EAC_CTX *ctx, const unsigned char *privkey, size_t privkey_len, const unsigned char *cvca, size_t cvca_len) { CVC_CERT *ta_cvca = NULL; int r = 0; check(ctx && ctx->ta_ctx, "Invalid arguments"); if (privkey && privkey_len) { if (ctx->ta_ctx->priv_key) EVP_PKEY_free(ctx->ta_ctx->priv_key); ctx->ta_ctx->priv_key = d2i_AutoPrivateKey(&ctx->ta_ctx->priv_key, &privkey, privkey_len); if (!ctx->ta_ctx->priv_key) goto err; } if (cvca && cvca_len) { ta_cvca = CVC_d2i_CVC_CERT(&ta_cvca, &cvca, cvca_len); } r = TA_CTX_set_trust_anchor(ctx->ta_ctx, ta_cvca, ctx->bn_ctx); err: if (ta_cvca) CVC_CERT_free(ta_cvca); return r; }
int mailstream_ssl_set_client_private_key_data(struct mailstream_ssl_context * ssl_context, unsigned char *pkey_der, size_t len) { #ifdef USE_SSL #ifndef USE_GNUTLS EVP_PKEY *pkey = NULL; if (pkey_der != NULL && len > 0) pkey = d2i_AutoPrivateKey(NULL, (const unsigned char **)&pkey_der, len); ssl_context->client_pkey = (EVP_PKEY *)pkey; return 0; #else gnutls_datum tmp; int r; ssl_context->client_pkey = NULL; if (len == 0) return 0; gnutls_x509_privkey_init(&(ssl_context->client_pkey)); tmp.data = pkey_der; tmp.size = len; if ((r = gnutls_x509_privkey_import(ssl_context->client_pkey, &tmp, GNUTLS_X509_FMT_DER)) < 0) { gnutls_x509_privkey_deinit(ssl_context->client_pkey); ssl_context->client_pkey = NULL; return -1; } return 0; #endif #endif return -1; }
static int test_d2i_AutoPrivateKey(int i) { int ret = 0; const unsigned char *p; EVP_PKEY *pkey = NULL; const APK_DATA *ak = &keydata[i]; const unsigned char *input = ak->kder; size_t input_len = ak->size; int expected_id = ak->evptype; p = input; if (!TEST_ptr(pkey = d2i_AutoPrivateKey(NULL, &p, input_len)) || !TEST_ptr_eq(p, input + input_len) || !TEST_int_eq(EVP_PKEY_id(pkey), expected_id)) goto done; ret = 1; done: EVP_PKEY_free(pkey); return ret; }
static int autoca_db_open( BackendDB *be, ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; autoca_info *ai = on->on_bi.bi_private; Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; void *thrctx; Entry *e; Attribute *a; int rc; if (slapMode & SLAP_TOOL_MODE) return 0; if ( ! *aca_attr2[0].ad ) { int i, code; const char *text; for ( i=0; aca_attr2[i].at; i++ ) { code = slap_str2ad( aca_attr2[i].at, aca_attr2[i].ad, &text ); if ( code ) return code; } /* Schema may not be loaded, ignore if missing */ slap_str2ad( "ipHostNumber", &ad_ipaddr, &text ); for ( i=0; aca_ocs[i].ot; i++ ) { code = register_oc( aca_ocs[i].ot, aca_ocs[i].oc, 0 ); if ( code ) return code; } } thrctx = ldap_pvt_thread_pool_context(); connection_fake_init2( &conn, &opbuf, thrctx, 0 ); op = &opbuf.ob_op; op->o_bd = be; op->o_dn = be->be_rootdn; op->o_ndn = be->be_rootndn; rc = overlay_entry_get_ov( op, be->be_nsuffix, NULL, NULL, 0, &e, on ); if ( e ) { int gotoc = 0, gotat = 0; if ( is_entry_objectclass( e, oc_caObj, 0 )) { gotoc = 1; a = attr_find( e->e_attrs, ad_caPkey ); if ( a ) { const unsigned char *pp; pp = (unsigned char *)a->a_vals[0].bv_val; ai->ai_pkey = d2i_AutoPrivateKey( NULL, &pp, a->a_vals[0].bv_len ); if ( ai->ai_pkey ) { a = attr_find( e->e_attrs, ad_caCert ); if ( a ) { pp = (unsigned char *)a->a_vals[0].bv_val; ai->ai_cert = d2i_X509( NULL, &pp, a->a_vals[0].bv_len ); /* If TLS wasn't configured yet, set this as our CA */ if ( !slap_tls_ctx ) autoca_setca( a->a_vals ); } } gotat = 1; } } overlay_entry_release_ov( op, e, 0, on ); /* generate attrs, store... */ if ( !gotat ) { genargs args; saveargs arg2; args.issuer_cert = NULL; args.issuer_pkey = NULL; args.subjectDN = &be->be_suffix[0]; args.cert_exts = CAexts; args.more_exts = NULL; args.keybits = ai->ai_cakeybits; args.days = ai->ai_cadays; rc = autoca_gencert( op, &args ); if ( rc ) return -1; ai->ai_cert = args.newcert; ai->ai_pkey = args.newpkey; arg2.dn = be->be_suffix; arg2.ndn = be->be_nsuffix; arg2.isca = 1; if ( !gotoc ) arg2.oc = oc_caObj; else arg2.oc = NULL; arg2.on = on; arg2.dercert = &args.dercert; arg2.derpkey = &args.derpkey; autoca_savecert( op, &arg2 ); /* If TLS wasn't configured yet, set this as our CA */ if ( !slap_tls_ctx ) autoca_setca( &args.dercert ); op->o_tmpfree( args.dercert.bv_val, op->o_tmpmemctx ); op->o_tmpfree( args.derpkey.bv_val, op->o_tmpmemctx ); } } return 0; }
static int test_EVP_PKEY_check(int i) { int ret = 0; const unsigned char *p; EVP_PKEY *pkey = NULL; #ifndef OPENSSL_NO_EC EC_KEY *eckey = NULL; #endif EVP_PKEY_CTX *ctx = NULL; EVP_PKEY_CTX *ctx2 = NULL; const APK_DATA *ak = &keycheckdata[i]; const unsigned char *input = ak->kder; size_t input_len = ak->size; int expected_id = ak->evptype; int expected_check = ak->check; int expected_pub_check = ak->pub_check; int expected_param_check = ak->param_check; int type = ak->type; BIO *pubkey = NULL; p = input; switch (type) { case 0: if (!TEST_ptr(pkey = d2i_AutoPrivateKey(NULL, &p, input_len)) || !TEST_ptr_eq(p, input + input_len) || !TEST_int_eq(EVP_PKEY_id(pkey), expected_id)) goto done; break; #ifndef OPENSSL_NO_EC case 1: if (!TEST_ptr(pubkey = BIO_new_mem_buf(input, input_len)) || !TEST_ptr(eckey = d2i_EC_PUBKEY_bio(pubkey, NULL)) || !TEST_ptr(pkey = EVP_PKEY_new()) || !TEST_true(EVP_PKEY_assign_EC_KEY(pkey, eckey))) goto done; break; case 2: if (!TEST_ptr(eckey = d2i_ECParameters(NULL, &p, input_len)) || !TEST_ptr_eq(p, input + input_len) || !TEST_ptr(pkey = EVP_PKEY_new()) || !TEST_true(EVP_PKEY_assign_EC_KEY(pkey, eckey))) goto done; break; #endif default: return 0; } if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL))) goto done; if (!TEST_int_eq(EVP_PKEY_check(ctx), expected_check)) goto done; if (!TEST_int_eq(EVP_PKEY_public_check(ctx), expected_pub_check)) goto done; if (!TEST_int_eq(EVP_PKEY_param_check(ctx), expected_param_check)) goto done; ctx2 = EVP_PKEY_CTX_new_id(0xdefaced, NULL); /* assign the pkey directly, as an internal test */ EVP_PKEY_up_ref(pkey); ctx2->pkey = pkey; if (!TEST_int_eq(EVP_PKEY_check(ctx2), 0xbeef)) goto done; if (!TEST_int_eq(EVP_PKEY_public_check(ctx2), 0xbeef)) goto done; if (!TEST_int_eq(EVP_PKEY_param_check(ctx2), 0xbeef)) goto done; ret = 1; done: EVP_PKEY_CTX_free(ctx); EVP_PKEY_CTX_free(ctx2); EVP_PKEY_free(pkey); BIO_free(pubkey); return ret; }
/** * Esta función se encargará de producir, lo que para el SAT[1], es un sello * digital. Este sello digital consiste en el firmado digital del hash de un * string, que para los casos de un CFDi se trataría de la cadena original * * El usuario es responsable de liberar la memoria del resultado (con free()) * [1]: http://www.sat.gob.mx */ unsigned char * sello_alloc(const char *keyfile, const char *digest, const unsigned char *cadena, const int verbose) { int read = 0; int len = 0; unsigned char *buffer = NULL; const unsigned char *tmp; unsigned char signbuffer[1024]; unsigned int signlen = 0; char *data = NULL; FILE *file = NULL; BIO* err = NULL; EVP_MD_CTX mdctx; EVP_PKEY *privateKey = NULL; file = fopen(keyfile, "rb"); if ( file == NULL ) { /* An error ocurred */ if ( verbose ) { fprintf(stderr, "No fue posible leer correctamente el archivo %s.\n", keyfile); } return NULL; } len = fseek(file, 0, SEEK_END); if ( len ) { /* An error did occur */ if ( verbose ) { fprintf(stderr, "No fue posible obtener el final del archivo %s.\n", keyfile); } fclose(file); return NULL; } len = ftell(file); rewind(file); buffer = (unsigned char *)calloc(len + 1, sizeof(unsigned char)); read = fread(buffer, sizeof(unsigned char), len, file); fclose(file); if ( read != len ) { if ( verbose ) { fprintf(stderr, "An error has ocurred. The number of items read was %d, but it should be %d instead.\n", read, len); free(buffer); } return NULL; } /* Set the BIO method for the error messages */ if ( err == NULL ) { if ( (err = BIO_new(BIO_s_file())) ) { BIO_set_fp(err, stderr, BIO_NOCLOSE|BIO_FP_TEXT); } } /* Now convert the bytes to a EVP_PKEY structure */ tmp = buffer; privateKey = d2i_AutoPrivateKey(NULL, &tmp, len); if ( privateKey == NULL ) { if ( verbose ) { BIO_printf(err, "Error at reading the private key on %s.\n", keyfile); ERR_print_errors(err); } free(buffer); return NULL; } free(buffer); /* Add all digest algorithms to the table */ OpenSSL_add_all_digests(); /* Initialize the digest context */ EVP_MD_CTX_init(&mdctx); if ( EVP_DigestInit_ex(&mdctx, EVP_get_digestbyname(digest), 0 ) == 0 ) { if ( verbose ) { BIO_printf(err, "Error at initializing the digest context to use '%s' as digest algorithm.\n", digest); ERR_print_errors(err); } EVP_PKEY_free(privateKey); EVP_cleanup(); BIO_free(err); return NULL; } /* Sign up the data in the current context */ if ( EVP_SignInit_ex(&mdctx, EVP_get_digestbyname(digest), 0) == 0 ) { if ( verbose ) { BIO_printf(err, "Error at setting up the signing context to use digest '%s'.\n", digest); ERR_print_errors(err); } EVP_PKEY_free(privateKey); EVP_cleanup(); BIO_free(err); return NULL; } if ( EVP_SignUpdate(&mdctx, cadena, strlen((char *)cadena)) == 0 ) { if ( verbose ) { BIO_printf(err, "Error hashing the data into the signing context.\n"); ERR_print_errors(err); } EVP_PKEY_free(privateKey); EVP_cleanup(); BIO_free(err); return NULL; } signlen = sizeof(signbuffer); memset(signbuffer, 0, 1024); if ( EVP_SignFinal(&mdctx, signbuffer, (unsigned int* )&signlen, privateKey) == 0 ) { if ( verbose ) { BIO_printf(err, "Error signing the data in the context with the private key.\n"); ERR_print_errors(err); } EVP_PKEY_free(privateKey); EVP_cleanup(); BIO_free(err); return NULL; } EVP_MD_CTX_cleanup(&mdctx); EVP_PKEY_free(privateKey); EVP_cleanup(); BIO_free(err); /* Now prepare the data to be base64 encoded */ base64_encode_alloc((const char *)signbuffer, signlen, &data); return (unsigned char *)data; }
/* * initialize a new TLS context */ static int tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx; int i; if ( is_server ) { SSL_CTX_set_session_id_context( ctx, (const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 ); } #ifdef SSL_OP_NO_TLSv1 #ifdef SSL_OP_NO_TLSv1_1 #ifdef SSL_OP_NO_TLSv1_2 if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 ); else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 ); if ( lo->ldo_tls_ciphersuite && !SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lo->ldo_tls_ciphersuite, 0, 0 ); tlso_report_error(); return -1; } if ( lo->ldo_tls_cacertfile == NULL && lo->ldo_tls_cacertdir == NULL && lo->ldo_tls_cacert.bv_val == NULL ) { if ( !SSL_CTX_set_default_verify_paths( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not use default certificate paths", 0, 0, 0 ); tlso_report_error(); return -1; } } else { X509 *cert = NULL; if ( lo->ldo_tls_cacert.bv_val ) { const unsigned char *pp = lo->ldo_tls_cacert.bv_val; cert = d2i_X509( NULL, &pp, lo->ldo_tls_cacert.bv_len ); X509_STORE *store = SSL_CTX_get_cert_store( ctx ); if ( !X509_STORE_add_cert( store, cert )) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not use CA certificate", 0, 0, 0 ); tlso_report_error(); return -1; } } if (( lt->lt_cacertfile || lt->lt_cacertdir ) && !SSL_CTX_load_verify_locations( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load verify locations (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } if ( is_server ) { STACK_OF(X509_NAME) *calist; /* List of CA names to send to a client */ calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir, cert ); if ( !calist ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load client CA list (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } SSL_CTX_set_client_CA_list( ctx, calist ); } if ( cert ) X509_free( cert ); } if ( lo->ldo_tls_cert.bv_val ) { const unsigned char *pp = lo->ldo_tls_cert.bv_val; X509 *cert = d2i_X509( NULL, &pp, lo->ldo_tls_cert.bv_len ); if ( !SSL_CTX_use_certificate( ctx, cert )) { Debug( LDAP_DEBUG_ANY, "TLS: could not use certificate.\n", 0,0,0); tlso_report_error(); return -1; } X509_free( cert ); } else if ( lo->ldo_tls_certfile && !SSL_CTX_use_certificate_file( ctx, lt->lt_certfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use certificate file `%s'.\n", lo->ldo_tls_certfile,0,0); tlso_report_error(); return -1; } /* Key validity is checked automatically if cert has already been set */ if ( lo->ldo_tls_key.bv_val ) { const unsigned char *pp = lo->ldo_tls_key.bv_val; EVP_PKEY *pkey = d2i_AutoPrivateKey( NULL, &pp, lo->ldo_tls_key.bv_len ); if ( !SSL_CTX_use_PrivateKey( ctx, pkey )) { Debug( LDAP_DEBUG_ANY, "TLS: could not use private key.\n", 0,0,0); tlso_report_error(); return -1; } EVP_PKEY_free( pkey ); } else if ( lo->ldo_tls_keyfile && !SSL_CTX_use_PrivateKey_file( ctx, lt->lt_keyfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use key file `%s'.\n", lo->ldo_tls_keyfile,0,0); tlso_report_error(); return -1; } if ( is_server && lo->ldo_tls_dhfile ) { DH *dh; BIO *bio; if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use DH parameters file `%s'.\n", lo->ldo_tls_dhfile,0,0); tlso_report_error(); return -1; } if (!( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) { Debug( LDAP_DEBUG_ANY, "TLS: could not read DH parameters file `%s'.\n", lo->ldo_tls_dhfile,0,0); tlso_report_error(); BIO_free( bio ); return -1; } BIO_free( bio ); SSL_CTX_set_tmp_dh( ctx, dh ); SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE ); DH_free( dh ); } if ( is_server && lo->ldo_tls_ecname ) { #ifdef OPENSSL_NO_EC Debug( LDAP_DEBUG_ANY, "TLS: Elliptic Curves not supported.\n", 0,0,0 ); return -1; #else EC_KEY *ecdh; int nid = OBJ_sn2nid( lt->lt_ecname ); if ( nid == NID_undef ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use EC name `%s'.\n", lo->ldo_tls_ecname,0,0); tlso_report_error(); return -1; } ecdh = EC_KEY_new_by_curve_name( nid ); if ( ecdh == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not generate key for EC name `%s'.\n", lo->ldo_tls_ecname,0,0); tlso_report_error(); return -1; } SSL_CTX_set_tmp_ecdh( ctx, ecdh ); SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE ); EC_KEY_free( ecdh ); #endif } if ( tlso_opt_trace ) { SSL_CTX_set_info_callback( ctx, tlso_info_cb ); } i = SSL_VERIFY_NONE; if ( lo->ldo_tls_require_cert ) { i = SSL_VERIFY_PEER; if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND || lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) { i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } } SSL_CTX_set_verify( ctx, i, lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ? tlso_verify_ok : tlso_verify_cb ); #if OPENSSL_VERSION_NUMBER < 0x10100000 SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb ); #endif #ifdef HAVE_OPENSSL_CRL if ( lo->ldo_tls_crlcheck ) { X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx ); if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK ); } else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); } } #endif return 0; }