mutual-TLS / mTLS Example with certificate problem
Hello, I can not find a working mutual-TLS server/client example on github or the whole internet. Only some example for pieces of code. Communication via socket without and with encryption (openSSL) is working, but with mTLS not. I believe that I theoretical understand mTLS, but the practice will not work. The whole (small) project is here: https://github.com/deckard-rick/mTLS-example Server Side = I initialize the SSL-context without errors with (sample, error handling is not in this email) SSL_CTX_set_ecdh_auto(srvCtx->ctx, 1); SSL_CTX_set_verify(srvCtx->ctx, SSL_VERIFY_PEER or SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); SSL_CTX_load_verify_locations(srvCtx->ctx,NULL,"../certs"); // SSL_CTX_use_certificate_chain_file(srvCtx->ctx, "../certs/server/ca.crt"); SSL_CTX_use_certificate_file(srvCtx->ctx, "../certs/server/server.crt", SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(srvCtx->ctx, "../certs/server/server.key", SSL_FILETYPE_PEM); SSL_CTX_check_private_key(srvCtx->ctx); the certificates are: ca.crt: Version: 3 (0x2) Serial Number: 5a:fc:74:e6:28:28:0e:df:5b:7a:50:9e:a8:18:e6:04:42:f0:fd:8d Signature Algorithm: sha256WithRSAEncryption Issuer: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = 42CA Validity Not Before: May 6 09:21:23 2020 GMT Not After : May 6 09:21:23 2022 GMT Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = 42CA server.crt: Version: 1 (0x0) Serial Number: 5f:6f:44:b5:27:47:f2:d2:fe:2b:21:5b:38:7d:e5:f6:e5:d9:c1:23 Signature Algorithm: sha256WithRSAEncryption Issuer: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = 42CA Validity Not Before: May 6 09:30:23 2020 GMT Not After : May 6 09:30:23 2021 GMT Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = debiandevdesktop01.sdctec.lokal debiandevdesktop01.sdctec.lokal is the FQDN of the development server Client Side = SSL_CTX_set_ecdh_auto(ctx, 1); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); SSL_CTX_use_certificate_chain_file(ctx, "../certs/client/ca.crt"); SSL_CTX_use_certificate_file(ctx, "../certs/client/client.crt", SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(ctx, "../certs/client/client.key", SSL_FILETYPE_PEM); ca.crt: (see server) client.crt: Version: 1 (0x0) Serial Number: 5f:6f:44:b5:27:47:f2:d2:fe:2b:21:5b:38:7d:e5:f6:e5:d9:c1:24 Signature Algorithm: sha256WithRSAEncryption Issuer: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = 42CA Validity Not Before: May 6 09:35:51 2020 GMT Not After : May 6 09:35:51 2021 GMT Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = CLIENT001 Error: = If the client connects the server there are the following errors: server: 139918902234240:error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1915: client: 139918902234240:error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1915: I think, there is a problem with the certificates. But where is the problem and why? The statement to create the certificates are in the project ./certs/read.me Thanks for any help, I'm looking since days for a solution and I believe it is only a small bug. Best regards Andreas
Re: mutual-TLS / mTLS Example with certificate problem
Hello Michael, thank you and Viktor for your fast help. Viktor annotations I don't fully understand. Sure there is the openssl test server and client, but the source code is complex for everyone who is new in this encryption tasks. But testing with openssl was a valuable notice: 1) openssl vs openssl openssl s_server -port 8080 -CAfile certs/server/ca.crt -cert certs/server/server.crt -key certs/server/server.key -Verify 99 Is this the right call for "TLS with mutual authentication", I cannot find an other parameter for SSL_VERIFY_PEER? with openssl s_client -connect localhost:8080 -CAfile certs/client/ca.crt -cert certs/client/client.crt -key certs/client/client.key it is working, and the server sees the COMMON NAME of the client (the whole certificate) 2) openssl vs myclient is working 3) myserver vs openssl (and my client) is not working In the openssl server command line I set only CAfile, cert, key and verify I believe I do this also in my source code: int verify_flags = SSL_VERIFY_PEER SSL_CTX_set_verify(srvCtx->ctx, verify_flags, NULL); char cafile[] = "/home/debdev/Projects/clearing/server/certs/client/ca.crt"; Variant 1: SSL_CTX_use_certificate_chain_file(srvCtx->ctx, cafile) Variant 2: STACK_OF(X509_NAME) *calist = SSL_load_client_CA_file(cafile); SSL_CTX_set_client_CA_list(srvCtx->ctx, calist); if (SSL_CTX_use_certificate_file(srvCtx->ctx, srvCtx->cert, SSL_FILETYPE_PEM) <= 0) if (SSL_CTX_use_PrivateKey_file(srvCtx->ctx, srvCtx->key, SSL_FILETYPE_PEM) <= 0 ) But there is still the error: tls_process_client_certificate:certificate verify failed Why? 4) I have looked into apps/s_server.c there is a ctx_set_verify_locations with the cafile information in apps.c this calls: SSL_CTX_load_verify_file, but the compiler can't find this function. Why? Thanks and sorry if I do not understand all details in the first try. Best regards Andreas Am 06.05.2020 um 21:59 schrieb Michael Wojcik: >> From: openssl-users [mailto:openssl-users-boun...@openssl.org] On Behalf Of >> Andreas Tengicki >> Sent: Wednesday, May 06, 2020 12:45 >> To: openssl-users@openssl.org >> Subject: mutual-TLS / mTLS Example with certificate problem >> >> I can not find a working mutual-TLS server/client example on github or >> the whole internet. > By "mutual-TLS" I assume you mean "TLS with mutual authentication". > > I don't know about open-source examples off the top of my head, but all the > products I work on support mutual authentication. > > Oh, wait, of course I know of an open-source example. It's OpenSSL, which > supports mutual authentication in the s_server and s_client apps. > >> SSL_CTX_use_certificate_chain_file(srvCtx->ctx, >> "../certs/server/ca.crt"); >> SSL_CTX_use_certificate_file(srvCtx->ctx, >> "../certs/server/server.crt", SSL_FILETYPE_PEM); > This is very likely wrong. SSL(_CTX)_use_certificate_chain_file sets the > entity certificate and its (partial) chain. So when you call > SSL_CTX_use_certificate_file you're overwriting the entity certificate set by > use_certificate_chain_file. > > Get rid of the call to use_certificate_file and put everything the server > should be sending into the chain file, in the order described in the OpenSSL > documentation: entity certificate, certificate for its issuer, and so on up > to and including the root. (I've just noticed the docs don't say whether > use_certificate_chain_file specifies SSL_BUILD_CHAIN_FLAG_NO_ROOT when it > calls add1_chain_cert, so offhand I don't know whether this will cause the > root to be included in the chain the server sends. But that shouldn't really > matter.) > >> ca.crt: Version: 3 (0x2) >> Serial Number: >> 5a:fc:74:e6:28:28:0e:df:5b:7a:50:9e:a8:18:e6:04:42:f0:fd:8d >> Signature Algorithm: sha256WithRSAEncryption >> Issuer: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = 42CA >> Validity Not Before: May 6 09:21:23 2020 GMT Not After : May 6 >> 09:21:23 2022 GMT >> Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN >> = 42CA > Not enough information. We don't know what the Basic Constraints are for this > certificate, or EKU, or whether it's actually the certificate that signed > your server's entity certificate. > > More importantly, if this is the only certificate in ca.crt, which was what > you passed to use_certificate_chain_file, then this was stored in the context > as the entity cert, and no certificates were added to the chain. Then you > overwrote the entity cert with use_certificate_file, and you still have n
creating certificate by code / problems to load via openssl x509 / pem format
Hello, your first help in this project, helps much, but now some weeks later, there is a new problem, and I cannot find any tipps via google. For all the coding a have looked into the openssl examples. I create a private key per code, the "openssl rsa -in test_privatekey.pem -check" is fine I create a certificate request per code, "openssl req -text -noout -verify -in test_request.pem" is fine I create a certifcate via this reqeust and store it with "PEM_write_bio_X509(out, crt);" like the others. (some more code below) Perhaps there is something wrong, but to detect this, I will use the validation, but it cannot load the certificate to validate it: >> openssl x509 -in test_certificate.pem -text unable to load certificate 14018039872:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:91: 14018039872:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:../crypto/asn1/tasn_dec.c:1118: 14018039872:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:190:Type=ASN1_TIME 14018039872:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:627:Field=notBefore, Type=X509_VAL 14018039872:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:627:Field=validity, Type=X509_CINF 14018039872:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:627:Field=cert_info, Type=X509 14018039872:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:../crypto/pem/pem_oth.c:33: Thanks for any help. Best regards Andreas ErrorHandling should be added in a second step, first debug outputs (I have deleted for here) says everything is created X509* certificate_create(const X509_REQ* req) { //openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt if ((crt = X509_new()) == NULL); //xca = load_cert(CAfile, CAformat, "CA Certificate"); BIO *bio = NULL; bio = BIO_new_file(CAfile, "r"); xca = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); BIO_free(bio); upkey = X509_get0_pubkey(xca); char CAkeyile[] = "ca.key"; int CAkeyformat = 5; //FORMAT_PEM char passin[] = "xyz"; ENGINE *e = NULL; EVP_PKEY * CApkey = NULL; //CApkey = load_key(CAkeyfile, CAkeyformat, 0, passin, e, "CA Private Key"); bio = BIO_new_file(CAkeyile, "r"); CApkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, passin); BIO_free(bio); EVP_PKEY_copy_parameters(upkey, CApkey); X509_STORE *ctx = NULL; ctx = X509_STORE_new(); X509_STORE_CTX *xsc = NULL; xsc = X509_STORE_CTX_new(); if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, crt, NULL)); ASN1_INTEGER *serialno = NULL; serialno = ASN1_INTEGER_new(); BIGNUM *btmp = NULL; btmp = BN_new(); # define SERIAL_RAND_BITS 159 if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)); if (!BN_to_ASN1_INTEGER(btmp, serialno)); BN_free(btmp); X509_STORE_CTX_set_cert(xsc, crt); X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); if (!X509_check_private_key(xca, CApkey)) ; if (!X509_set_issuer_name(crt, X509_get_subject_name(xca))); if (!X509_set_serialNumber(crt, serialno)); int days = 365; if (X509_time_adj_ex(X509_getm_notAfter(crt), days, 0, NULL) == NULL); const char digestname[] = "sha256"; const EVP_MD* md = EVP_get_digestbyname(digestname); EVP_MD_CTX *mctx = EVP_MD_CTX_new(); EVP_PKEY_CTX *pkctx = NULL; EVP_DigestSignInit(mctx, &pkctx, md, NULL, CApkey); //ist CApkey hier der richtige private Key? sollte eigentlich int rv = (X509_sign_ctx(crt, mctx) > 0); EVP_MD_CTX_free(mctx); BIO *out = NULL; out = BIO_new_file("test_certificate.pem", "w"); PEM_write_bio_X509(out, crt); BIO_free_all(out); ...some more frees ... return crt; }
Re: creating certificate by code / problems to load via openssl x509 / pem format
The solution was to choice a EVP by signing the certificate i = X509_sign(x, CApkey, EVP_sha256()); Best regards Andreas Am 09.07.2020 um 11:09 schrieb Andreas Tengicki: Hello, your first help in this project, helps much, but now some weeks later, there is a new problem, and I cannot find any tipps via google. For all the coding a have looked into the openssl examples. I create a private key per code, the "openssl rsa -in test_privatekey.pem -check" is fine I create a certificate request per code, "openssl req -text -noout -verify -in test_request.pem" is fine I create a certifcate via this reqeust and store it with "PEM_write_bio_X509(out, crt);" like the others. (some more code below) Perhaps there is something wrong, but to detect this, I will use the validation, but it cannot load the certificate to validate it: >> openssl x509 -in test_certificate.pem -text unable to load certificate 14018039872:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:../crypto/asn1/asn1_lib.c:91: 14018039872:error:0D068066:asn1 encoding routines:asn1_check_tlen:bad object header:../crypto/asn1/tasn_dec.c:1118: 14018039872:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:190:Type=ASN1_TIME 14018039872:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:627:Field=notBefore, Type=X509_VAL 14018039872:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:627:Field=validity, Type=X509_CINF 14018039872:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:627:Field=cert_info, Type=X509 14018039872:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:../crypto/pem/pem_oth.c:33: Thanks for any help. Best regards Andreas ErrorHandling should be added in a second step, first debug outputs (I have deleted for here) says everything is created X509* certificate_create(const X509_REQ* req) { //openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt if ((crt = X509_new()) == NULL); //xca = load_cert(CAfile, CAformat, "CA Certificate"); BIO *bio = NULL; bio = BIO_new_file(CAfile, "r"); xca = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); BIO_free(bio); upkey = X509_get0_pubkey(xca); char CAkeyile[] = "ca.key"; int CAkeyformat = 5; //FORMAT_PEM char passin[] = "xyz"; ENGINE *e = NULL; EVP_PKEY * CApkey = NULL; //CApkey = load_key(CAkeyfile, CAkeyformat, 0, passin, e, "CA Private Key"); bio = BIO_new_file(CAkeyile, "r"); CApkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, passin); BIO_free(bio); EVP_PKEY_copy_parameters(upkey, CApkey); X509_STORE *ctx = NULL; ctx = X509_STORE_new(); X509_STORE_CTX *xsc = NULL; xsc = X509_STORE_CTX_new(); if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, crt, NULL)); ASN1_INTEGER *serialno = NULL; serialno = ASN1_INTEGER_new(); BIGNUM *btmp = NULL; btmp = BN_new(); # define SERIAL_RAND_BITS 159 if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)); if (!BN_to_ASN1_INTEGER(btmp, serialno)); BN_free(btmp); X509_STORE_CTX_set_cert(xsc, crt); X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); if (!X509_check_private_key(xca, CApkey)) ; if (!X509_set_issuer_name(crt, X509_get_subject_name(xca))); if (!X509_set_serialNumber(crt, serialno)); int days = 365; if (X509_time_adj_ex(X509_getm_notAfter(crt), days, 0, NULL) == NULL); const char digestname[] = "sha256"; const EVP_MD* md = EVP_get_digestbyname(digestname); EVP_MD_CTX *mctx = EVP_MD_CTX_new(); EVP_PKEY_CTX *pkctx = NULL; EVP_DigestSignInit(mctx, &pkctx, md, NULL, CApkey); //ist CApkey hier der richtige private Key? sollte eigentlich int rv = (X509_sign_ctx(crt, mctx) > 0); EVP_MD_CTX_free(mctx); BIO *out = NULL; out = BIO_new_file("test_certificate.pem", "w"); PEM_write_bio_X509(out, crt); BIO_free_all(out); ...some more frees ... return crt; }