From a5a06d2255530cca08e2aab90eab6496c0964065 Mon Sep 17 00:00:00 2001 From: tom_win Date: Sun, 17 May 2020 15:12:06 +0200 Subject: [PATCH] .. --- .../klient/vygenerovany_certifikat.pem | 26 +- certifikaty/klient/vygenerovany_kluc.key | 50 +-- .../server/vygenerovany_certifikat.pem | 24 +- certifikaty/server/vygenerovany_kluc.key | 50 +-- kniznica/komunikacia.c | 315 ++++++++++-------- kniznica/komunikacia.h | 17 +- kniznica/kryptografia.c | 37 +- kniznica/kryptografia.h | 21 +- rs232_kanal/klient/klient.c | 100 ++++-- rs232_kanal/klient/obr.jpg | Bin 0 -> 51156 bytes rs232_kanal/klient/spustit_klient.bat | 2 +- rs232_kanal/server/obr.jpg | Bin 0 -> 51156 bytes rs232_kanal/server/server.c | 69 ++-- rs232_kanal/server/spustit_server.bat | 2 +- tcpip_kanal/klient/klient.c | 83 +++-- tcpip_kanal/klient/obr.jpg | Bin 0 -> 51156 bytes tcpip_kanal/klient/spustit_klient.bat | 2 +- tcpip_kanal/server/obr.jpg | Bin 0 -> 51156 bytes tcpip_kanal/server/server.c | 70 ++-- tcpip_kanal/server/spustit_server.bat | 2 +- 20 files changed, 532 insertions(+), 338 deletions(-) create mode 100644 rs232_kanal/klient/obr.jpg create mode 100644 rs232_kanal/server/obr.jpg create mode 100644 tcpip_kanal/klient/obr.jpg create mode 100644 tcpip_kanal/server/obr.jpg diff --git a/certifikaty/klient/vygenerovany_certifikat.pem b/certifikaty/klient/vygenerovany_certifikat.pem index f148627..bac18e9 100644 --- a/certifikaty/klient/vygenerovany_certifikat.pem +++ b/certifikaty/klient/vygenerovany_certifikat.pem @@ -1,18 +1,18 @@ -----BEGIN CERTIFICATE----- -MIIC9TCCAl6gAwIBAgIQbFsMsUpL4cQYvdnPsNfEozANBgkqhkiG9w0BAQsFADBz +MIIC9TCCAl6gAwIBAgIQD7QN9LZVR1zGQgnk5Ibj8jANBgkqhkiG9w0BAQsFADBz MQswCQYDVQQGEwJTSzEKMAgGA1UECAwBLTEPMA0GA1UEBwwGS29zaWNlMREwDwYD VQQKDAhBdXRvcml0YTESMBAGA1UEAwwJbG9jYWwuZGV2MSAwHgYJKoZIhvcNAQkB -FhFhdXRvcml0YUB0dWtlLmNvbTAiGA8yMDIwMDMxODEwMzUwOFoYDzIwMjUwMzE4 -MTAzNTA4WjB3MQswCQYDVQQGEwJTUjEKMAgGA1UECAwBLTEPMA0GA1UEBwwGS29z +FhFhdXRvcml0YUB0dWtlLmNvbTAiGA8yMDIwMDUxNjEwNDY1NFoYDzIwMjUwNTE2 +MTA0NjU0WjB3MQswCQYDVQQGEwJTUjEKMAgGA1UECAwBLTEPMA0GA1UEBwwGS29z aWNlMQowCAYDVQQKDAEtMQowCAYDVQQLDAEtMRIwEAYDVQQDDAlsb2NhbC5kZXYx -HzAdBgkqhkiG9w0BCQEWEGtsaWVudEBrbGllbnQuc2swggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDwvJLGxRiSsplAIeOWOeMa4xeh8mVwTVZgJjuOK2xv -Gze6NZ/or9OGHqBMat3rfW9xZazAg+UoL4TzqokVyjo1KQxGwbHuZQdqQ3/MgWnm -1h2cdLicF8hMQtawYhqp1me9+Xh89y+tiBBAAilzGzPRQayYoMoEd9Ics8XPbSX/ -qEzSdVeuqb7AIQIDZ7v4DTnQIarJDFtzE4Rd37Dq+ThMiipe292FKbRqfyhU5974 -QtAfTQ6ReYzuRnO5bveAx20iOHXqhM2ckUNzuAKRk8DKEdh/ucPpJTF5rkJYVmU0 -6qpVAPdfSrovuNe6r3v9JGBCWOb8XPq9cLE0PwRd2U1nAgMBAAEwDQYJKoZIhvcN -AQELBQADgYEAUFd0OaWxtikqd5MRx8LfOKfIoadPxnm7/os6fR8D1K8HMVuinbc4 -6My0jDwVIQQP0ovlGHhntbH+EsXwoB15O2EPtfh5kQjgocKdZitfH3jgaW3ndm1B -RAKOmCfs29IBHN/ZUX8hBaoSfUWJPvwL2DcxzwoeI+h5VRHY68f6cI4= +HzAdBgkqhkiG9w0BCQEWEHNlcnZlckBzZXJ2ZXIuc2swggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCyo30ux5wnoKt7Ew3gLSfjsU9/QUSW44pVMWPLbq61 +eGspm9JsFtLdjDD4EwcE6f8VKKprpzmIXGvgwEcOw+i8eXs/awu9xH+BjlU9fLLS +FVbK3qMoDBlzxx+apsZGj3KRajHGRbapuHM+UxZyHMRKV+w2mBobt+GQ9Wl3dzBG +SfyLcGLNn/cVacWYuBnAqD3edKZjurZpvgjWzSNYI5uKJk3u3uPwECtk1VjUOGgv +yH0/vAbGPhp40Kaz9hl7keQqBmz5fOpNNCR9k8wCnSL7+cSmkXuOHzTgEvFcL1H+ +v4Oq1xcwpS2r2Dt1O2seDVpdpp4/GukPgL35w9ARHI5nAgMBAAEwDQYJKoZIhvcN +AQELBQADgYEALK4Urx0CfKH8+z7NH7GoNtye0KEYAXZuAV86GyASp6Ts9Cf8Oz3s +CizMkG6VcQ9Jm1jMqUKhR/izVDshoBPvdjslBnNVy2frQivx5vDumaYvdPiSxu8P +0SjqybTiBvonOKls/ovOtXKAGmgDv4mo2X5eIB7k5q+4nH6O3IDu2GU= -----END CERTIFICATE----- diff --git a/certifikaty/klient/vygenerovany_kluc.key b/certifikaty/klient/vygenerovany_kluc.key index f3014ba..5ac1683 100644 --- a/certifikaty/klient/vygenerovany_kluc.key +++ b/certifikaty/klient/vygenerovany_kluc.key @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/certifikaty/server/vygenerovany_certifikat.pem b/certifikaty/server/vygenerovany_certifikat.pem index 4369bd4..26340ce 100644 --- a/certifikaty/server/vygenerovany_certifikat.pem +++ b/certifikaty/server/vygenerovany_certifikat.pem @@ -1,18 +1,18 @@ -----BEGIN CERTIFICATE----- -MIIC9TCCAl6gAwIBAgIQbFmaYwjF3/SehWXgHj8HwjANBgkqhkiG9w0BAQsFADBz +MIIC9TCCAl6gAwIBAgIQbqhXQUhaG0nVXxRDTCpRKzANBgkqhkiG9w0BAQsFADBz MQswCQYDVQQGEwJTSzEKMAgGA1UECAwBLTEPMA0GA1UEBwwGS29zaWNlMREwDwYD VQQKDAhBdXRvcml0YTESMBAGA1UEAwwJbG9jYWwuZGV2MSAwHgYJKoZIhvcNAQkB -FhFhdXRvcml0YUB0dWtlLmNvbTAiGA8yMDIwMDMxODEyMjkyOVoYDzIwMjUwMzE4 -MTIyOTI5WjB3MQswCQYDVQQGEwJTUjEKMAgGA1UECAwBLTEPMA0GA1UEBwwGS29z +FhFhdXRvcml0YUB0dWtlLmNvbTAiGA8yMDIwMDUxNjA5NTYyMVoYDzIwMjUwNTE2 +MDk1NjIxWjB3MQswCQYDVQQGEwJTUjEKMAgGA1UECAwBLTEPMA0GA1UEBwwGS29z aWNlMQowCAYDVQQKDAEtMQowCAYDVQQLDAEtMRIwEAYDVQQDDAlsb2NhbC5kZXYx HzAdBgkqhkiG9w0BCQEWEHNlcnZlckBzZXJ2ZXIuc2swggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQC2anE0gd6zuFQw2T+PLZg9KHlm9+TjrkHXc3zxFw4g -uNgGxwi4TMGoUMVyUsEWtBHYkF/Zx5fWD292RItXd5GsrvyUjOgOF9BMfAh8MkHa -HqQiFOzw7LAwbzCiNU82ZIWAbQvivnLXTmygFPbB+LlDcCLS3U738x46rrQaHuGe -wNj4BBDSMVqAeN3z966Yf1YIXIe4rPQivRTGgtJYUfjL4b9sB6dgNmBUzmI5DRil -olEwkHm9AuZ2mwfHcBUvCc24iN9q8lY6fjAqIQo0+NFYhvi2jibvUTy6dOxEUbKg -R14mye/vF+fNaT2NHMVBHqYxA0dnPw3nQQMOuR3WCt9zAgMBAAEwDQYJKoZIhvcN -AQELBQADgYEAiBxxdJm1VUxUVsY31LMpe3pIbicSVi+91rtsii02tbMEBl8o4UKQ -xfJyZaWQW0gZ3rcgcquYU/SKpsjiYwzPjx10IX8htHibmgSS4EC5L5poKBncjSmC -tWmJEILZl9dXPUrIOuJOa4hBeK54chVFsszm2mhbJsYGvOA8z0gcc94= +AQUAA4IBDwAwggEKAoIBAQCUm8dUUfjwuW/2ppSh+HlbLw+inAHk9Ha9N0So3Yfn +45DYWY9c/ZJjLeyagu5H4mHQaRHYkqVb/QEKlacCvA3RqWdTX6IKO+eQhZ9YEpMV +sO/xPzs2EAmqM8R3E2ek7mj3UPEueJMEYy6cr8vH83ILeMLtrjFUJG4T2GexKsIH +KLHAep0yKo4oEfudtpB//jm2NgYdUjuKbGogEUWElS4tQnNEvZ2bC3AN1TB9Wz81 +w7/rR+ekiOVxM19bw2nKs7QX1bG1+PbJPafqj7ysuSIkGnn0Exkqt4QDl6YQtbn9 +JwQYgbAV1lNjSEuSMihqGkptSl89z10xa2LyXm0Vbs2fAgMBAAEwDQYJKoZIhvcN +AQELBQADgYEAiQRgEyTvSfRdTFm4UKijgk5xMJGBCF7pj9H8CWmCl+Y3F2ztoyxw +iJ+qtNTA1jlQiCVKWO4OfysihqVT2jeba9UO7WMSU3+k5B+O/XRJldDKDbiefye8 +1V/qo/2i00vbf1PV8wHfGHdav96fWm9Gla1BYvxHe8xiUFp/3IGqRIE= -----END CERTIFICATE----- diff --git a/certifikaty/server/vygenerovany_kluc.key b/certifikaty/server/vygenerovany_kluc.key index 3825df2..d3f2c89 100644 --- a/certifikaty/server/vygenerovany_kluc.key +++ b/certifikaty/server/vygenerovany_kluc.key @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/kniznica/komunikacia.c b/kniznica/komunikacia.c index ab20931..bf3a001 100644 --- a/kniznica/komunikacia.c +++ b/kniznica/komunikacia.c @@ -9,20 +9,15 @@ #include "komunikacia.h" #include "kryptografia.h" -int poslat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, const char* cesta, nastavenia_aplikacie *nastavenia) +int poslat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, const char* cesta, nastavenia_aplikacie *nastavenia, int velkost_bloku_dat) { int uspech; - - //odoslanie nazvu (resp. cesty) suboru - uspech = 0; - while(uspech < VELKOST_CESTY) + + while(wolfSSL_write(ssl, cesta, SPRAVA_VELKOST_BUFFERA) != SPRAVA_VELKOST_BUFFERA) { - uspech = wolfSSL_write(ssl, cesta, VELKOST_CESTY); - if(uspech <= 0) - { - fprintf(stderr, "Nastala chyba pri posielani dat o subore.\n"); - return -1; - } + if(wolfSSL_want_write(ssl)) continue; + fprintf(stderr, "Nastala chyba pri posielani nazvu suboru\n"); + return -1; } //otvorenie suboru na citanie @@ -40,123 +35,143 @@ int poslat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, const char* cesta, nastavenia_a //nastavi ukazovatel na koniec suboru //a zisti velkost suboru fseek(subor, 0, SEEK_END); - int velkost = (int)ftell(subor); - char velkost_suboru[VELKOST_SUBOR]; - sprintf(velkost_suboru, "%ld", velkost); - printf("Velkost suboru: %s bajtov\n", velkost_suboru); - uspech = 0; - while(uspech < VELKOST_SUBOR) + int velkost_suboru = (int)ftell(subor); + char velkost_suboru_retazec[SPRAVA_VELKOST_BUFFERA]; + sprintf(velkost_suboru_retazec, "%d", velkost_suboru); + printf("Velkost suboru: %s bajtov\n", velkost_suboru_retazec); + + while(wolfSSL_write(ssl, velkost_suboru_retazec, SPRAVA_VELKOST_BUFFERA) != SPRAVA_VELKOST_BUFFERA) { - uspech = wolfSSL_write(ssl, velkost_suboru, VELKOST_SUBOR); - if(uspech <= 0) - { - fprintf(stderr, "Nastala chyba pri posielani dat o velkosti suboru.\n"); - return -1; - } + if(wolfSSL_want_write(ssl)) continue; + fprintf(stderr, "Nastala chyba pri posielani velkosti suboru\n"); + return -1; } //nastavi ukazovatel na zaciatok suboru //a nacita data zo suboru do pola - unsigned char* pole = calloc(velkost, sizeof(unsigned char)); - if(pole == NULL) + unsigned char* data = calloc(velkost_suboru, sizeof(unsigned char)); + if(data == NULL) { - fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre pole\n"); + fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre pole data,\ndo ktoreho sa nacita obsah suboru\n"); return -1; } fseek(subor, 0, SEEK_SET); - fread((unsigned char*)pole, 1, velkost, subor); + fread((unsigned char*)data, 1, velkost_suboru, subor); //posielanie jednotlivych bajtov + unsigned char* data_ukazovatel = data; uspech = 0; - while(uspech < velkost) + int ostava_poslat = velkost_suboru; + for(int i = 0; i < (velkost_suboru/velkost_bloku_dat) + 1; ++i) { - uspech = wolfSSL_write(ssl, pole, velkost); - if(uspech <= 0) + if(ostava_poslat > velkost_bloku_dat) { - fprintf(stderr, "Nastala chyba pri posielani suboru.\n"); - return -1; + while(wolfSSL_write(ssl, data_ukazovatel, velkost_bloku_dat) != velkost_bloku_dat) + { + if(wolfSSL_want_write(ssl)) continue; + fprintf(stderr, "Nastala chyba pri posielani suboru\n"); + return -1; + } } + else + { + uspech = 0; + while(wolfSSL_write(ssl, data_ukazovatel, ostava_poslat) != ostava_poslat) + { + if(wolfSSL_want_write(ssl)) continue; + fprintf(stderr, "Nastala chyba pri posielani suboru\n"); + return -1; + } + } + data_ukazovatel += velkost_bloku_dat; + ostava_poslat -= velkost_bloku_dat; } printf("Subor bol uspesne odoslany.\n"); //generovanie a poslanie kontrolneho suctu serveru pre kontrolu unsigned char* kontrolny_sucet; int velkost_kontrolneho_suctu; - kontrolny_sucet = generovat_kontrolny_sucet_suboru(nastavenia, cesta, velkost, &velkost_kontrolneho_suctu); - - uspech = 0; - while(uspech < velkost_kontrolneho_suctu) + kontrolny_sucet = generovat_kontrolny_sucet_suboru(nastavenia, cesta, velkost_suboru, &velkost_kontrolneho_suctu); + + while(wolfSSL_write(ssl, kontrolny_sucet, velkost_kontrolneho_suctu) != velkost_kontrolneho_suctu) { - uspech = wolfSSL_write(ssl, kontrolny_sucet, velkost_kontrolneho_suctu); + if(wolfSSL_want_write(ssl)) continue; + fprintf(stderr, "Nastala chyba pri posielani kontrolneho suctu\n"); + return -1; } + free(kontrolny_sucet); fclose(subor); return 0; } } -int prijat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, nastavenia_aplikacie* nastavenia) +int prijat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, nastavenia_aplikacie* nastavenia, int velkost_bloku_dat) { int uspech; //prijem dat o subore - char* cesta = calloc(VELKOST_CESTY, sizeof(char)); - char* velkost_suboru = calloc(VELKOST_SUBOR, sizeof(char)); + char* cesta = calloc(SPRAVA_VELKOST_BUFFERA, sizeof(char)); + char* velkost_suboru_retazec = calloc(SPRAVA_VELKOST_BUFFERA, sizeof(char)); - uspech = 0; - while(uspech < VELKOST_CESTY) + while(wolfSSL_read(ssl, cesta, SPRAVA_VELKOST_BUFFERA) != SPRAVA_VELKOST_BUFFERA) { - uspech = wolfSSL_read(ssl, cesta, VELKOST_CESTY); - if(uspech <= 0) - { - fprintf(stderr, "Nastala chyba pri prijati dat o subore\n"); - return -1; - } + if(wolfSSL_want_read(ssl)) continue; + fprintf(stderr, "Nastala chyba pri prijati nazvu suboru\n"); + return -1; } printf("Prebieha prijimanie suboru %s\n", cesta); //ziskanie informacie od klienta o velkosti odoslaneho suboru - uspech = 0; - while(uspech < VELKOST_SUBOR) + while(wolfSSL_read(ssl, velkost_suboru_retazec, SPRAVA_VELKOST_BUFFERA) != SPRAVA_VELKOST_BUFFERA) { - uspech = wolfSSL_read(ssl, velkost_suboru, VELKOST_SUBOR); - if(uspech <= 0) - { - fprintf(stderr, "Nastala chyba pri prijati velkosti suboru\n"); - return -1; - } + if(wolfSSL_want_read(ssl)) continue; + fprintf(stderr, "Nastala chyba pri prijati velkosti suboru\n"); + return -1; } - int velkost = (int)atol(velkost_suboru); - if(velkost < 1) + int velkost_suboru = (int)atol(velkost_suboru_retazec); + if(velkost_suboru <= 0) { - printf("Nastala chyba pri prijati suboru\n"); + printf("Bola prijata informacia o velkosti suboru s hodnotu mensou nez 0\nPravdepodobne nastala chyba pri prenose\n"); return -1; } else { - printf("Velkost suboru: %s bajtov\n", velkost_suboru); + printf("Velkost suboru: %s bajtov\n", velkost_suboru_retazec); } - //prijem jednotlivych bajtov - unsigned char* pole = calloc(velkost, sizeof(unsigned char)); - if(pole == NULL) + unsigned char* data = calloc(velkost_suboru, sizeof(unsigned char)); + if(data == NULL) { - fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre pole\n"); + fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre pole data\ndo ktoreho sa zapisu prijate data\n"); return -1; } - unsigned char* pole_uk = pole; - - uspech = 0; - for(int i = 0; i < (velkost/16384) + 1; ++i) + + unsigned char* data_ukazovatel = data; + int ostava_prijat = velkost_suboru; + for(int i = 0; i < (velkost_suboru/velkost_bloku_dat) + 1; ++i) { - uspech = wolfSSL_read(ssl, pole_uk, velkost); - pole_uk += 16384; - if(uspech <= 0) + if(ostava_prijat > velkost_bloku_dat) + { + while(wolfSSL_read(ssl, data_ukazovatel, velkost_bloku_dat) != velkost_bloku_dat) { - fprintf(stderr, "Nastala chyba pri posielani suboru.\n"); + if(wolfSSL_want_read(ssl)) continue; + fprintf(stderr, "Nastala chyba pri prijimani suboru\n"); return -1; } + } + else + { + while(wolfSSL_read(ssl, data_ukazovatel, ostava_prijat) != ostava_prijat) + { + if(wolfSSL_want_read(ssl)) continue; + fprintf(stderr, "Nastala chyba pri prijimani suboru\n"); + return -1; + } + } + data_ukazovatel += velkost_bloku_dat; + ostava_prijat -= velkost_bloku_dat; } printf("Subor bol uspesne prijaty.\n"); @@ -165,25 +180,34 @@ int prijat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, nastavenia_aplikacie* nastaveni int velkost_kontrolneho_suctu; FILE *subor = fopen(cesta, "wb+"); - int n = fwrite((unsigned char*)pole, 1, velkost, subor); + int pocet_zapisanych_bajtov = fwrite((unsigned char*)data, 1, velkost_suboru, subor); + if(pocet_zapisanych_bajtov <= 0) + { + fprintf(stderr, "Nepodarilo sa zapisat do suboru obsah prijateho suboru\n"); + return -1; + } + else if(pocet_zapisanych_bajtov < velkost_suboru) + { + fprintf(stderr, "Nepodarilo sa zapisat do suboru cely obsah prijateho suboru\n"); + return -1; + } + else + { + printf("Do suboru %s bolo zapisanych %d bajtov\n", cesta, pocet_zapisanych_bajtov); + } fclose(subor); - kontrolny_sucet = generovat_kontrolny_sucet_suboru(nastavenia, cesta, velkost, &velkost_kontrolneho_suctu); + kontrolny_sucet = generovat_kontrolny_sucet_suboru(nastavenia, cesta, velkost_suboru, &velkost_kontrolneho_suctu); - //prijem hashu, ktory vypocital server + //prijem kontrolneho suctu, ktory vypocital server char* prijaty_kontrolny_sucet = calloc(velkost_kontrolneho_suctu, sizeof(char)); - - uspech = 0; - while(uspech != velkost_kontrolneho_suctu) + + while(wolfSSL_read(ssl, (char*)prijaty_kontrolny_sucet, velkost_kontrolneho_suctu) != velkost_kontrolneho_suctu) { - uspech = wolfSSL_read(ssl, (char*)prijaty_kontrolny_sucet, velkost_kontrolneho_suctu); - if(uspech <= 0) - { - fprintf(stderr, "Nastala chyba pri prijati kontrolneho suctu.\n"); - free(prijaty_kontrolny_sucet); - return -1; - } + if(wolfSSL_want_read(ssl)) continue; + fprintf(stderr, "Nastala chyba pri prijati kontrolneho suctu\n"); + return -1; } //kontrola ci sa prijaty a vypocitany kontrolny sucet suboru zhoduju @@ -199,7 +223,7 @@ int prijat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, nastavenia_aplikacie* nastaveni } free(cesta); - free(velkost_suboru); + free(velkost_suboru_retazec); free(kontrolny_sucet); free(prijaty_kontrolny_sucet); return 0; @@ -420,14 +444,19 @@ int rs232_prijat_spravu(int cislo_rozhrania, const char* komunikacny_subor) FILE* subor = fopen(komunikacny_subor, "ab+"); int uspech = 0; - int prebieha_nacitanie_velkosti_spravy = 0; - int prebieha_nacitanie_kontrolneho_suctu = 0; - int prebieha_nacitanie_dat = 0; + stav_nacitania stav; + stav = NEPREBIEHA_NACITANIE; unsigned char znak; //mnozstvo nacitanych dat int nacitane_data = 0; + //kontrolny vzor ktory jednoznacne identifikuje zaciatok spravy + unsigned char kontrolny_vzor[] = {0xAA, 0xAA, 0xAA, 0xAA}; + //urcuje kolko bajtov z kontrolneho vzoru + //uz bolo prijatych z celkoveho poctu (4) + int kontrolny_vzor_pozicia = 0; + //velkost spravy, ktora sa bude prijmat int velkost_spravy = 0; unsigned char velkost_spravy_hex[4]; @@ -443,70 +472,68 @@ int rs232_prijat_spravu(int cislo_rozhrania, const char* komunikacny_subor) int kontrolny_sucet_pozicia = 0; unsigned char* prijate_data; - - //kontrolny vzor ktory jednoznacne identifikuje zaciatok spravy - unsigned char kontrolny_vzor[] = {0xAA, 0xAA, 0xAA, 0xAA}; - int kontrolny_vzor_pozicia = 0; //aktualna pozicia v kontrolnom vzore - int velkost_kontrolneho_vzoru = sizeof(kontrolny_vzor)/sizeof(kontrolny_vzor[0]); - while(1) + while(stav != NACITANIE_UKONCENE) { uspech = RS232_PollComport(cislo_rozhrania, &znak, 1); if(uspech > 0) { - //nacitanie kontrolneho vzoru - if(!prebieha_nacitanie_velkosti_spravy && !prebieha_nacitanie_dat && !prebieha_nacitanie_kontrolneho_suctu && - znak == kontrolny_vzor[kontrolny_vzor_pozicia]) + switch(stav) { - kontrolny_vzor_pozicia++; - if(kontrolny_vzor_pozicia == 4) - { - prebieha_nacitanie_velkosti_spravy = 1; - kontrolny_vzor_pozicia = 0; - } - } - //nacitanie velkosti spravy - else if(!prebieha_nacitanie_dat && prebieha_nacitanie_velkosti_spravy) - { - velkost_spravy_hex[velkost_spravy_pozicia] = znak; - velkost_spravy_pozicia++; - if(velkost_spravy_pozicia == 4) - { - velkost_spravy = (uint32_t)velkost_spravy_hex[0] << 24 | (uint32_t)velkost_spravy_hex[1] << 16 | - (uint32_t)velkost_spravy_hex[2] << 8 | (uint32_t)velkost_spravy_hex[3]; - prebieha_nacitanie_kontrolneho_suctu = 1; - prebieha_nacitanie_velkosti_spravy = 0; - - prijate_data = calloc(velkost_spravy, sizeof(unsigned char)); - if(prijate_data == NULL) + case NEPREBIEHA_NACITANIE: + if(znak == kontrolny_vzor[kontrolny_vzor_pozicia]) { - fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre prijate_data\n"); - return -1; + kontrolny_vzor_pozicia++; } - } - } - //nacitanie kontrolneho vzoru - else if(!prebieha_nacitanie_dat && prebieha_nacitanie_kontrolneho_suctu) - { - kontrolny_sucet_hex[kontrolny_sucet_pozicia] = znak; - kontrolny_sucet_pozicia++; - if(kontrolny_sucet_pozicia == 4) - { - kontrolny_sucet = (uint32_t)kontrolny_sucet_hex[0] << 24 | (uint32_t)kontrolny_sucet_hex[1] << 16 | - (uint32_t)kontrolny_sucet_hex[2] << 8 | (uint32_t)kontrolny_sucet_hex[3]; - prebieha_nacitanie_dat = 1; - prebieha_nacitanie_velkosti_spravy = 0; - } - } - //nacitanie dat - else - { - if(prebieha_nacitanie_dat) - { + if(kontrolny_vzor_pozicia == 4) + { + kontrolny_vzor_pozicia = 0; + stav = PREBIEHA_NACITANIE_VELKOSTI_SPRAVY; + } + break; + case PREBIEHA_NACITANIE_VELKOSTI_SPRAVY: + velkost_spravy_hex[velkost_spravy_pozicia] = znak; + velkost_spravy_pozicia++; + if(velkost_spravy_pozicia == 4) + { + velkost_spravy = (uint32_t)velkost_spravy_hex[0] << 24 | (uint32_t)velkost_spravy_hex[1] << 16 | + (uint32_t)velkost_spravy_hex[2] << 8 | (uint32_t)velkost_spravy_hex[3]; + velkost_spravy_pozicia = 0; + stav = PREBIEHA_NACITANIE_KONTROLNEHO_SUCTU; + + //dynamicka alokacia pola s velkostou, ktora bola prijata + //do neho bude zapisana prijata sprava + prijate_data = calloc(velkost_spravy, sizeof(unsigned char)); + if(prijate_data == NULL) + { + fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre prijate_data\n"); + return -1; + } + } + break; + case PREBIEHA_NACITANIE_KONTROLNEHO_SUCTU: + kontrolny_sucet_hex[kontrolny_sucet_pozicia] = znak; + kontrolny_sucet_pozicia++; + if(kontrolny_sucet_pozicia == 4) + { + kontrolny_sucet = (uint32_t)kontrolny_sucet_hex[0] << 24 | (uint32_t)kontrolny_sucet_hex[1] << 16 | + (uint32_t)kontrolny_sucet_hex[2] << 8 | (uint32_t)kontrolny_sucet_hex[3]; + kontrolny_sucet_pozicia = 0; + stav = PREBIEHA_NACITANIE_DAT; + } + break; + case PREBIEHA_NACITANIE_DAT: prijate_data[nacitane_data] = znak; nacitane_data += uspech; - if(nacitane_data == velkost_spravy) break; - } + if(nacitane_data == velkost_spravy) + { + stav = NACITANIE_UKONCENE; + } + break; + default: + //tento stav by nemal nikdy nastat + fprintf(stderr, "Nepodarilo sa urcit stav nacitania spravy pomocou RS232\n"); + return -1; } } } @@ -531,7 +558,7 @@ int rs232_prijat_spravu(int cislo_rozhrania, const char* komunikacny_subor) } else { - printf("Sprava neprisla v poriadku"); + fprintf(stderr, "Sprava neprisla v poriadku"); return -1; } diff --git a/kniznica/komunikacia.h b/kniznica/komunikacia.h index f536d95..5db3201 100644 --- a/kniznica/komunikacia.h +++ b/kniznica/komunikacia.h @@ -17,8 +17,9 @@ #include "kryptografia.h" #include "../externe_kniznice/teuniz_rs232/rs232.h" -#define VELKOST_CESTY 64 //velkost retazca, kt. uklada lokaciu suboru -#define VELKOST_SUBOR 32 //velkost retazca, kt. uklada velkost prenasaneho suboru +//velkost buffrov ktore ukladaju doplnujuce data pri komunikacii +//napr. velkost suboru, cestu ku suboru a ine +#define SPRAVA_VELKOST_BUFFERA 64 #if defined(_WIN32) //makro ktore urcuje win distribuciu ak nieje detekovana @@ -76,6 +77,12 @@ int cakat_na_komunikaciu(int cislo_portu); // RS232 KOMUNIKACNY KANAL // ///////////////////////////// +typedef enum stav_nacitania { + NEPREBIEHA_NACITANIE, PREBIEHA_NACITANIE_VELKOSTI_SPRAVY, PREBIEHA_NACITANIE_KONTROLNEHO_SUCTU, + PREBIEHA_NACITANIE_DAT, NACITANIE_UKONCENE +} stav_nacitania; + + /** * rs232_otvorit_rozhranie: realizuje otvorenie RS232 serioveho rozhrania * @parameter int cislo_rozhrania: cislo RS232 serioveho rozhrania @@ -119,17 +126,19 @@ int rs232_prijat_spravu(int cislo_rozhrania, const char* komunikacny_subor); * @parameter WOLFSSL_CTX* ctx : ukazuje na WOLFSSL_CTX strukturu * @parameter char* cesta: ukazuje na retazec, ktory reprezentuje cestu k suboru * @parameter nastavenia_aplikacie* nastavenia: reprezentuje nastavenia aplikacie: server alebo klient + * @parameter int velkost_bloku_dat: velkost dat po ktorych sa budu data posielat * @vrati int : operacia bola uspesna(0), neuspesna(-1) */ -int poslat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, const char* cesta, nastavenia_aplikacie* nastavenia); +int poslat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, const char* cesta, nastavenia_aplikacie* nastavenia, int velkost_bloku_dat); /** * prijat_subor: realizuje prijem suboru * @parameter WOLFSSL* ssl : ukazuje na aktualnu relaciu * @parameter WOLFSSL_CTX* ctx : ukazuje na WOLFSSL_CTX strukturu * @parameter nastavenia_aplikacie* nastavenia: reprezentuje nastavenia aplikacie: server alebo klient + * @parameter int velkost_bloku_dat: velkost dat po ktorych sa budu data prijimat * @vrati int : operacia bola uspesna(0), neuspesna(-1) */ -int prijat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, nastavenia_aplikacie* nastavenia); +int prijat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, nastavenia_aplikacie* nastavenia, int velkost_bloku_dat); #endif \ No newline at end of file diff --git a/kniznica/kryptografia.c b/kniznica/kryptografia.c index 919e9ac..0b9a767 100644 --- a/kniznica/kryptografia.c +++ b/kniznica/kryptografia.c @@ -71,7 +71,7 @@ void zobraz_sifru(WOLFSSL* ssl) printf ("Pouzita sifra: %s\n", wolfSSL_get_cipher(ssl)); } -int generovat_rsa_certifikat(int pocet_bitov, int exponent, int algoritmus, char* krajina, char* mesto, char* domena, char* email) +int generovat_rsa_certifikat(const char* subor_certifikat, const char* subor_kluc, int pocet_bitov, int exponent, int algoritmus, char* krajina, char* mesto, char* domena, char* email) { int uspech = 0; @@ -151,7 +151,7 @@ int generovat_rsa_certifikat(int pocet_bitov, int exponent, int algoritmus, char pem_kluc_velkost = uspech; //zapis vygenerovaneho klucu do suboru - subor = fopen("../../certifikaty/vygenerovany_kluc.key", "wb"); + subor = fopen(subor_kluc, "wb+"); fwrite(pem_kluc, 1, pem_kluc_velkost, subor); fclose(subor); @@ -204,8 +204,8 @@ int generovat_rsa_certifikat(int pocet_bitov, int exponent, int algoritmus, char } pem_certifikat_velkost = uspech; - //zapis vygenerovaneho klucu do suboru - subor = fopen("../../certifikaty/vygenerovany_certifikat.pem", "wb"); + //zapis vygenerovaneho certifikatu do suboru + subor = fopen(subor_certifikat, "wb+"); fwrite(pem_certifikat, 1, pem_certifikat_velkost, subor); fclose(subor); @@ -214,7 +214,7 @@ int generovat_rsa_certifikat(int pocet_bitov, int exponent, int algoritmus, char return 0; } -int generovat_ecc_certifikat(int pocet_bitov, ecc_curve_id kluc_krivka, int algoritmus, char* krajina, char* mesto, char* domena, char* email) +int generovat_ecc_certifikat(const char* subor_certifikat, const char* subor_kluc, int pocet_bitov, ecc_curve_id kluc_krivka, int algoritmus, char* krajina, char* mesto, char* domena, char* email) { int uspech = 0 ; @@ -293,7 +293,7 @@ int generovat_ecc_certifikat(int pocet_bitov, ecc_curve_id kluc_krivka, int algo pem_kluc_velkost = uspech; //zapis vygenerovaneho kluca do suboru - subor = fopen("../certifikaty/vygenerovany_kluc.key", "wb"); + subor = fopen(subor_kluc, "wb+"); fwrite(pem_kluc, 1, pem_kluc_velkost, subor); fclose(subor); @@ -347,14 +347,14 @@ int generovat_ecc_certifikat(int pocet_bitov, ecc_curve_id kluc_krivka, int algo pem_certifikat_velkost = uspech; //zapis vygenerovaneho klucu do suboru - subor = fopen("../certifikaty/vygenerovany_certifikat.pem", "wb"); + subor = fopen(subor_certifikat, "wb+"); fwrite(pem_certifikat, 1, pem_certifikat_velkost, subor); fclose(subor); return 0; } -int vygenerovat_rsa_ziadost(int pocet_bitov, int exponent, int algoritmus, char* krajina, char* mesto, char* domena, char* email) +int vygenerovat_rsa_ziadost(const char* subor_ziadost, const char* subor_kluc, int pocet_bitov, int exponent, int algoritmus, char* krajina, char* mesto, char* domena, char* email) { int uspech = 0; @@ -392,6 +392,11 @@ int vygenerovat_rsa_ziadost(int pocet_bitov, int exponent, int algoritmus, char* return -1; } + FILE* subor = fopen(subor_kluc, "wb+"); + fwrite(pem_kluc, 1, pem_kluc_velkost, subor); + fclose(subor); + printf("RSA kluc bol uspesne vygenerovany\n"); + //premenne pre ukladanie dat ziadosti Cert ziadost; unsigned char der_ziadost[VELKOST_BUFFERA]; @@ -429,9 +434,13 @@ int vygenerovat_rsa_ziadost(int pocet_bitov, int exponent, int algoritmus, char* fprintf(stderr, "Nastala chyba pri vytvoreni suboru PEM so ziadostou.\nCislo chyby: %d\nDovod chyby: %s\n", uspech, wc_GetErrorString(uspech)); return -1; } + pem_ziadost_velkost = uspech; + subor = fopen(subor_ziadost, "wb+"); + fwrite(pem_ziadost, 1, pem_ziadost_velkost, subor); + fclose(subor); } -int vygenerovat_ecc_ziadost(int pocet_bitov, ecc_curve_id kluc_krivka, int algoritmus, char* krajina, char* mesto, char* domena, char* email) +int vygenerovat_ecc_ziadost(const char* subor_ziadost, const char* subor_kluc, int pocet_bitov, ecc_curve_id kluc_krivka, int algoritmus, char* krajina, char* mesto, char* domena, char* email) { int uspech = 0; @@ -469,6 +478,11 @@ int vygenerovat_ecc_ziadost(int pocet_bitov, ecc_curve_id kluc_krivka, int algor return -1; } + FILE* subor = fopen(subor_kluc, "wb+"); + fwrite(pem_kluc, 1, pem_kluc_velkost, subor); + fclose(subor); + printf("ECC kluc bol uspesne vygenerovany\n"); + //premenne pre ukladanie dat ziadosti Cert ziadost; unsigned char der_ziadost[VELKOST_BUFFERA]; @@ -506,6 +520,10 @@ int vygenerovat_ecc_ziadost(int pocet_bitov, ecc_curve_id kluc_krivka, int algor fprintf(stderr, "Nastala chyba pri vytvoreni suboru PEM so ziadostou.\nCislo chyby: %d\nDovod chyby: %s\n", uspech, wc_GetErrorString(uspech)); return -1; } + pem_ziadost_velkost = uspech; + subor = fopen(subor_ziadost, "wb+"); + fwrite(pem_ziadost, 1, pem_ziadost_velkost, subor); + fclose(subor); } int nacitat_certifikaty(WOLFSSL_CTX* ctx, const char* subor_certifikat, const char* subor_kluc) @@ -541,7 +559,6 @@ int nacitat_certifikaty(WOLFSSL_CTX* ctx, const char* subor_certifikat, const ch void zobraz_certifikat(WOLFSSL* ssl) { - printf("Informacie o certifikate:\n"); WOLFSSL_X509 *certifikat = wolfSSL_get_peer_certificate(ssl); char* pole; if (!certifikat) diff --git a/kniznica/kryptografia.h b/kniznica/kryptografia.h index 3093fcc..08175ae 100644 --- a/kniznica/kryptografia.h +++ b/kniznica/kryptografia.h @@ -26,8 +26,13 @@ #include #include +//velkost bufferov do ktorych sa ukladaju data certifikatov, klucov, ziadosti #define VELKOST_BUFFERA 4096 + +//pocet bajtov ktore vstupuju do crc funkcie #define CRC32_VELKOST 10 + +//velkost vystupu blake2d hashu v bitoch #define BLAKE2B_VELKOST 64 /** @@ -82,41 +87,49 @@ unsigned char* generovat_kontrolny_sucet_suboru(nastavenia_aplikacie* nastavenia /** * generovat_ecc_certifikat: realizuje vygenerovania sukromneho kluca, nacitanie sukromneho kluca autority, * vygenerovanie a podpis ecc certifikatu pomocou sukromneho kluca a certifikatu autority + * @parameter const char* subor_kluc : absolutna cesta ku suboru so sukromnym klucom vo formate PEM + * @parameter const char* subor_certifikat : absolutna cesta ku suboru s certifikatom vo formate PEM * @parameter int pocet_bitov : velkost kluca * @parameter ecc-curve_id kluc_krivka: kod krivky pre generovanie sukromneho kluca * @parameter int algoritmus: kod algoritmu, sluziaceho na vymenu klucov * @vrati int: operacia bola uspesna(0), neuspesna(-1) */ -int generovat_ecc_certifikat(int pocet_bitov, ecc_curve_id kluc_krivka, int algoritmus, char* krajina, char* mesto, char* domena, char* email); +int generovat_ecc_certifikat(const char* subor_kluc, const char* subor_certifikat, int pocet_bitov, ecc_curve_id kluc_krivka, int algoritmus, char* krajina, char* mesto, char* domena, char* email); /** * generovat_rsa_certifikat: realizuje vygenerovania sukromneho kluca, nacitanie sukromneho kluca autority, * vygenerovanie a podpis rsa certifikatu pomocou sukromneho kluca a certifikatu autority + * @parameter const char* subor_kluc : absolutna cesta ku suboru so sukromnym klucom vo formate PEM + * @parameter const char* subor_certifikat : absolutna cesta ku suboru s certifikatom vo formate PEM * @parameter int pocet_bitov : velkost kluca * @parameter int exponent : hodnota exponentu * @parameter int algoritmus : kod algoritmu, sluziaceho na vymenu klucov * @vrati int : operacia bola uspesna(0), neuspesna(-1) */ -int generovat_rsa_certifikat(int pocet_bitov, int exponent, int algoritmus, char* krajina, char* mesto, char* domena, char* email); +int generovat_rsa_certifikat(const char* subor_kluc, const char* subor_certifikat, int pocet_bitov, int exponent, int algoritmus, char* krajina, char* mesto, char* domena, char* email); /** * generovat_rsa_ziadost: realizuje vygenerovania sukromneho kluca, vygenerovanie a podpis ziadosti + * @parameter const char* subor_kluc : absolutna cesta ku suboru so sukromnym klucom vo formate PEM + * @parameter const char* subor_ziadost : absolutna cesta ku suboru so ziadostou vo formate PEM * @parameter int pocet_bitov : velkost kluca * @parameter int exponent : hodnota exponentu * @parameter int algoritmus: kod algoritmu, sluziaceho na vymenu klucov * @vrati int: operacia bola uspesna(0), neuspesna(-1) */ -int generovat_rsa_ziadost(int pocet_bitov, int exponent, int algoritmus, char* krajina, char* mesto, char* domena, char* email); +int generovat_rsa_ziadost(const char* subor_kluc, const char* subor_ziadost, int pocet_bitov, int exponent, int algoritmus, char* krajina, char* mesto, char* domena, char* email); /** * generovat_ecc_ziadost: realizuje vygenerovania sukromneho kluca, vygenerovanie a podpis ziadosti + * @parameter const char* subor_kluc : absolutna cesta ku suboru so sukromnym klucom vo formate PEM + * @parameter const char* subor_ziadost : absolutna cesta ku suboru so ziadostou vo formate PEM * @parameter int pocet_bitov : velkost kluca * @parameter ecc-curve_id kluc_krivka: kod krivky pre generovanie sukromneho kluca * @parameter int algoritmus: kod algoritmu, sluziaceho na vymenu klucov * @vrati int: operacia bola uspesna(0), neuspesna(-1) */ -int generovat_ecc_ziadost(int pocet_bitov, ecc_curve_id kluc_krivka, int algoritmus, char* krajina, char* mesto, char* domena, char* email); +int generovat_ecc_ziadost(const char* subor_kluc, const char* subor_ziadost, int pocet_bitov, ecc_curve_id kluc_krivka, int algoritmus, char* krajina, char* mesto, char* domena, char* email); /** * nastav_ctx_klient : realizuje vytvorenie a inicializaciu CTX struktury diff --git a/rs232_kanal/klient/klient.c b/rs232_kanal/klient/klient.c index e30fa96..fbb446e 100644 --- a/rs232_kanal/klient/klient.c +++ b/rs232_kanal/klient/klient.c @@ -103,6 +103,7 @@ int main(int argc, char const *argv[]) WOLFSSL *ssl; WOLFSSL_CTX *ctx = NULL; const char* subor = NULL; + int autentizacia = 0; int zadane_rozhranie = 0; int uvedeny_subor = 0; int nacitanie_zo_suboru = 0; @@ -118,9 +119,10 @@ int main(int argc, char const *argv[]) } else { + printf("---------------\n| Certifikaty |\n---------------\n"); for(int i = 0; i < argc; i++) { - if( (!strcmp(argv[i], "-s")) ) + if( (!strcmp(argv[i], "-subor")) ) { uvedeny_subor = 1; if((argv[i+1] == NULL) ) @@ -133,7 +135,7 @@ int main(int argc, char const *argv[]) subor = argv[i+1]; } } - if( (!strcmp(argv[i], "-port")) ) + else if( (!strcmp(argv[i], "-port")) ) { zadane_rozhranie = 1; if((argv[i+1] == NULL)) @@ -150,7 +152,32 @@ int main(int argc, char const *argv[]) } } } - else if( (!strcmp(argv[i], "-n")) ) + else if( (!strcmp(argv[i], "-cert-aut")) ) + { + if((argv[i+1] == NULL) || (i == argc-1)) + { + printf("Nezadali ste typ certifikatu autority ktory chcete nacitat\n"); + return -1; + } + else if(!strcmp(argv[i+1], "rsa")) + { + wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + autentizacia = 1; + } + else if(!strcmp(argv[i+1], "ecc")) + { + wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + autentizacia = 1; + } + else + { + printf("Zadali ste nespravny typ certifikatu\n"); + return -1; + } + } + else if( (!strcmp(argv[i], "-cert")) ) { nacitanie_zo_suboru = 1; if(generovanie_certifikatu) @@ -165,17 +192,11 @@ int main(int argc, char const *argv[]) } else if(!strcmp(argv[i+1], "rsa")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); if(nacitat_certifikaty(ctx, RSA_CERTIFIKAT, RSA_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); - } else if(!strcmp(argv[i+1], "ecc")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); if(nacitat_certifikaty(ctx, ECC_CERTIFIKAT, ECC_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); - } else { @@ -183,7 +204,7 @@ int main(int argc, char const *argv[]) return -1; } } - else if( (!strcmp(argv[i], "-g")) ) + else if( (!strcmp(argv[i], "-cert-gen")) ) { generovanie_certifikatu = 1; if(nacitanie_zo_suboru) @@ -198,18 +219,14 @@ int main(int argc, char const *argv[]) } else if(!strcmp(argv[i+1], "rsa")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); - if(generovat_rsa_certifikat(RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; + if(generovat_rsa_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); } else if(!strcmp(argv[i+1], "ecc")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); - if(generovat_ecc_certifikat(ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; + if(generovat_ecc_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); } else { @@ -219,23 +236,29 @@ int main(int argc, char const *argv[]) } } } + + //vypis upozornenia o autentizacii + if(!autentizacia) + { + printf("Nebol nacitany certifikat autority, takze nebude vykonana autentizacia druhej strany\n"); + } if(!zadane_rozhranie) - { - fprintf(stderr, "Nebol urcene seriove rozhranie\n"); - return -1; - } - else if(!generovanie_certifikatu && !nacitanie_zo_suboru) - { - fprintf(stderr, "Nebola zvolena metoda nacitania certifikatov\n"); - printf("Zadajde prepinac -g (generovanie), alebo -n (nacitanie_zo_suboru) s parametrom rsa alebo ecc\n"); - return -1; - } - else if(!uvedeny_subor) - { - fprintf(stderr, "Nebola uvedena cesta ku suboru na odoslanie\n"); - return -1; - } + { + fprintf(stderr, "Nebol urcene seriove rozhranie\n"); + return -1; + } + else if(!generovanie_certifikatu && !nacitanie_zo_suboru) + { + fprintf(stderr, "Nebola zvolena metoda nacitania certifikatov\n"); + printf("Zadajde prepinac -gen-cert (generovanie), alebo -cert (nacitanie zo suboru) s parametrom rsa alebo ecc\n"); + return -1; + } + else if(!uvedeny_subor) + { + fprintf(stderr, "Nebola uvedena cesta ku suboru na odoslanie\n"); + return -1; + } //nastav_sifry(ctx, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); @@ -256,6 +279,8 @@ int main(int argc, char const *argv[]) wolfSSL_set_using_nonblock(ssl, k_subor); //pokus o inizicalizaciu TLS handshaku so serverom + printf("-----------------\n| TLS Handshake |\n-----------------\n"); + printf("Inicializacia TLS spojenia\n"); uspech = wolfSSL_connect(ssl); if(uspech != SSL_SUCCESS) { @@ -268,19 +293,20 @@ int main(int argc, char const *argv[]) free(popis_chyby); return -1; } - + printf("Podarilo sa vytvorit TLS spojenie\n"); zobraz_sifru(ssl); + printf("----------------------------\n| Informacie o certifikate |\n----------------------------\n"); zobraz_certifikat(ssl); //nastavenie funkcie pre vypocet kontrolneho suctu //nastavime typ "crc" alebo "hash" a nazov funkcie, nazov druhej funkcie nastavime na NULL nastav_funkciu(&nastavenia, "crc", (hashovacia_funkcia)NULL, funkcia_CRC32); - if(poslat_subor(ssl, ctx, subor, &nastavenia) == -1) - { - fclose(fopen(KOMUNIKACNY_SUBOR, "wb")); - return -1; - } + printf("-------------------\n| Poslanie suboru |\n-------------------\n"); + + if(poslat_subor(ssl, ctx, subor, &nastavenia, 4096) == -1) return -1; + + printf("----------------------\n| Ukoncenie spojenia |\n----------------------\n"); //ukoncenie spojenia, vymazanie komunikacneho suboru //a vycistenie serioveho buffera diff --git a/rs232_kanal/klient/obr.jpg b/rs232_kanal/klient/obr.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77d95676bab95b91bbc3c95d2fc663635cbda5a0 GIT binary patch literal 51156 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%0A;> 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 literal 0 HcmV?d00001 diff --git a/rs232_kanal/klient/spustit_klient.bat b/rs232_kanal/klient/spustit_klient.bat index 4566e47..b519ad3 100644 --- a/rs232_kanal/klient/spustit_klient.bat +++ b/rs232_kanal/klient/spustit_klient.bat @@ -13,4 +13,4 @@ :: -s cesta-ku-suboru sluzi na nacitanie cesty k suboru, ktory chceme odoslat ::Priklady spustenia: -klient -port 4 -n rsa -s document.pdf +klient -port 4 -cert rsa -cert-aut rsa -subor obr.jpg diff --git a/rs232_kanal/server/obr.jpg b/rs232_kanal/server/obr.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77d95676bab95b91bbc3c95d2fc663635cbda5a0 GIT binary patch literal 51156 zcmeFaXH-+)x9=SYy$S}Tcd1emdPh1)4ZSHH5_)ecU_l7IV?YQc^dh~gAksx337}M^ zDIh4l3J<^k`JZ#{bH{ygeO}x#o^e@8$l8nVF7vbJ$ewFu&7I57mtO%lbTxG}0eEATg#8+(;SIg!A0F5Tg##N2v>UCYN30xDnCU8yQn!q)I|0@Yt zz`UJ(LIOC9+idJjejB!F~I+-?P>)gJm9}$3ZknK6D9!RRom6r2~7qb z^MBRz@c93&xf*A|$NSIG6Pgly{Qs;|*#CRy|GZzV|Ib(r0PphiA;Hckt0)6e z5D}Mv{Id}}Qc_Y1ata1YN(Klg3n%2S%Vjr!h6M2VDuTk}1mM%)0cr3qKLFUTj*{?d zbm^Y~rhgYad>{cK5itoV8Tpl<`NoySKp;K=kdTnzYS;+x(bfL}1T=)SoZ!1eH;o;L zx%@zo=+r_IZq@o8I_Si29&tziC!}Qbw-^|iZu9c-3kXU`N=eJe%BiVqXliNe=$e?C znOj&|SvxtqxVpK+-~oX_!6Bhx;ZL7Ek9iRrhe%7$$jr*ld5J74EpOGCa0!9f0_BVw7jyq_Wj5D#?J2E{=wnV@yY2wcKu`Lf0q9+ z?0>S0=E^R70sMQW&dT^f7>+!pa9}sojf27KpD^-VMgIgsOmL+)=bDr z030{zDu4qbGsN>u9u{`_^5Yu{8yX2HWd1CQCgTP+^WXg;5EZ7z^EF^g+sR-h3P~;snH*+9a0xl)`PJD6fUS|7NcHJvZfzJ~2TZn0MVJfNh8R7*GOM zz4b@^VdQH8!q_hkE(2LFF9Cs2okn}SThU1w6Sw_~l><%c`^3n^`0=E6DP>bqJ6Wj1 z0m+Pm0G0@htaf%_Lad@yz3$gLchV^ac)W>&Jh3lL!6rNoF%Z&qjc$)ZRcR-JWdyps zMVJTJ)+Z*1Wz$)zlG+gx>4_f4eJ(7y_eFdF&9P@_I&e-bVX0a)Y?)j%jkKL zL6OO=IK+ef@Gvbvh5R-2C+Piqx}_o^ov56OVi{YgiVVf;DtIxSACbl#K?A>0vox9n zs5_a@jr(ve*;4KKCda572pU5yYY!#HzwN z{e~w?DRgzVceICd`Dod53pe`$!`-v&KhQP2O$}GO@!<`)8%;ud7eNFnilUk%Pe3wI z0FizrKrGrat^&n2fG88Fx}EtT4@bf8NQ(@|;3Z;;9ePki6wB?WxWv64K_^+Yff{@W zZ)eP>FT9!4fvG>qiaB;>XWF;qNbeu;sq>0+nk0QGflReKW({XE4>^9G(Pw%Pn^;IQ z#`fclsXsrk$mT5K%!G%!{Vw3Jry^uN2N1(R8D9O603>3H zB*bX6M)RPrOYjHgOm}LDU?}3shCOTA;T01`cjv@eZD?jxVp_Tj2a^L}#RUAsUxpim z2lXJgGBevsseCl9g$up> zr`k@|K?DMnqxTr8N(5E{5P)aDao9dU@KdyiJHw1FK-Zfej~av2;4EwdK^YPRA^i3L z$IMeGezn>PD6LIJT8!~PBITvon&B_%Pbf&C^25hL&WUb%6k;2KT^nQk&hEd7HA@K` z+~zL9V(|#K6Xi)z$tYwvXx5;~-(a zMQK}mL97?ew_Ac~LxL^@?JZehekwOc*!BfU*_KcqULPLs^ea*VbW@)jk@B&QicIdK zfaL4;`^pc$U(;6_C5&*$SLXL1!|WrrMyRV zc-4dViK1T~V((;qo0d7EBd9xDWg9p(Q3t=-c=H}O`F@4wN%;OHfXwl>xvChe4ls|2 zYS9{C@662^&29}T@l&C^BOvXE$ssy7X*I&jhb@EfSbA5NaglOaG;tQ2Dv0giM$uxL zQ>@wBaH8O!0&OK=0T_hiw zE?C#UF{Hw|TqG*qHvnxA-Lg74xh+jCyN zmvMw5DS7EPRi&^j0ho{}9s>csLDuql4Xpv5>3ms_y(f7BDjc3JMBPr+TsxAj#MHqF zLfm9amnA^bAjg!xEfo|Y{u6$NHZ*<|ohb_j;#fk$RyjIqYxL488xb|I=lUuRp9+k0 zeNSzD2aodvZ2VrfxSWaR&kR&7z`{|p{zTs-T_I^9Bj?64>vP%Q{7Pj(HOlycj(3^5 z^@Z$yk%GZD6u@+s0Mmk_!SaVqD!N5aHwXcUU0=8od4Q34t3-THA0da3<}eX6|Evmt z0o}(zVH64iKT}-a4J?T&yKNefZXW04D}_uz6luqnBJo!sSox#Z@S0uP%ts zOqkKUz?u`vEgjB6JOdLm>V+B-r=49>XA?(m2c#2~07Z>3MD(pd5KxoLSJ3GQeoA)8 z0gui~S8KmnD_Hog(sBeW1s`A6li*H&qaF^muU22?MpkN#X;b~ydODRc@Jo$}fH)6Z zKPvP*y7{E?0lUhuJ1|Vpm$Unc7GqAVaIQ(VmQ|topAZ(fB1g*pI*mR z2!Htvyy6}h=qo2G>K!2B;Oyh*BI4xZB^v7BD+(4769p(Jhx$4=dAI~}IJ&sOycPL= zb-v@{fH^DjSxD-O>HDg=xWlx={asAL4NRTFJ)C5n`IMC?$rM86LcM&wTml_9LcKh_ z1LQ&#x&F0vxvTm=&7xdN3jWTna!_^6e=Dw*6uJI=EFmEwA|c`;KK^c^U|CsNQ89=p z1R{K;5Dp0Q4s-|=_733w_XgBm0-XF|zJV|wZ;pR9=-}uR6sX7*6a;gYb9Hc)baZx> z6n1nFcNPYNogIW7oW;Sy&f?pu_B%lE%_|Gz|WwZAKqMc}W**WPuF>#qp>mH67b zu5tYpfxi-8d)GCtzasEg;%o1^#`RYO{z`o9UDvq&iojoquf6LU*IyC%EAh2=UE}&I z0)HjG_O5GOe?{Q0#Mj<+jq9%n{FV6HyRLEl6@kAJUwhXzuD>GiSK@2$y2kZa1pZ2V z?OoTn{))g~iLbru8rNSD_$%?XcU|N9D*}HdzV@zbTz^I2uf*5hb&cz<2>g}!+PnUb zwp}e2jl(l>_nd|9M^&f~zMX$v^qogk;3TL?jes6cprSUVQjC+}XUuH(7v4-pqaaD2i!(IUx|GF6_-z>>()_j%;b#Va0P2Xgc3V!OpZU z0r#6`6oN~)P&E`g@JHZdO!M2xt^B!3OiXI=m^ERc0l!q<_svlQPKDjYSK8e8Xfx2% z^7wNHrLsNruI|zKNkzT3hFu@(L&9Fc>Lp;hf?l|ov75baQx%t~@KKF{@+u8b`BV8A zi8%q)$Db*tb2w}h$abZ+EZ$3USG zro6{%ToJ3c&IJ-1FG4>ke+8Zk_6C@(Jjj>`<{WPdeb`GwJSC}&Dau-yj~=aNe|GNz zH2J8@B;M__aWGVaJW;TxTi5}<_)GQOH`7^l4Exg(tNKd-oW?q>U^w0*fTuViVNbKS z;ZEN-R=TFiPl;uFI0ix&{cm2ZmeFXd=RXxPYli^4!B@GuiYsm(75q#O`P6dLd#&$( zCCYY7x&*Xa*GNU93z-8)RFpRnQ$Ks%zoU(E7wU1r;>z_+W2eN{k&CI&L}>#u0M>J| zaeC1DrA5Uk85C6Fgasi< zN%FyH;K(sftI6qH&@6Pe1d+ zsr}4l^X%WOr58mRzc)i;?np%()o4q5`sDtk>EVEmy5?eiyVIZjGfne!P&5XpoXI*y<6#>wGoeE?dm zPG(J5k<@nkZ*sO0CsQhd!%Kge&J6eIl1eE4i0y1gB zsbRAkeJH`_YcVRLV{o@u9g-=)p`K;5esk7}jeVv=oAQJA@ln0>+u>wJQm>ctikQifEwmNVLsEv>I@m?KV*Db##|3+Nz5}=dzyL;lB z)HakzTul;}Rmau)GCP{_*D;o1&FJ%tylb(0ufGAQJT6?^B`@l($|Z3FVH;5 zN4@ZXiidYw!ELM;8MOq$49f^Lrt+1q;aJ{!+^oKZrg3nCe}dM><~vBc5kuEui=lyE zj{8bYwnWwNYMnA2_R-ztq%MTpq5kx&NY?-n>x&`3&2>bbU)g<;6f0-^uPhw}OZyj1 zwxo2-!74*&_c4@6F+#mDo(#KOH1J@ z=JuYo+T;UR8^CWSdhzx9CQk)q24IfNGwqHsBjf9*6;=1jYX{HY;NIHFO}W^B ztDi}j#9K4X7>!47ag~|MS?;@IXhkBmRg71~;hCvtlT*7_~V^mDXZnmM8q&ni6k`vI*WhEjzHFcrhTjKof>L(#m&Qhna zP_*S^;7umn;h6>F+@ z0Rd*gIiH=4;=C*)?knUheiB$0%=7w+(}WDj`{|~#E@T#_^TC3X^exi#=g89372%y! z@RZnjZTuqc-&GVua<~XsG`Xn3K9-$3!R$%Xd{+`bUS-B!VjJieABXWO4HgNAXDCAN zjy>jgzXUK5Xdv`Vhx6D35*bk>Kjv;#^eK->6e-{5ztLwO&Vr3$U<%3pb(h(6Zz?)< zDI0`0dXFhTppPK6lBmLI@YLi9HcJ^!M20T8ufnk!usKr)pNj3%X|*gJ_(k`4?a|%J z;at1$M^_o=n>Xm|IoTi53IVEpyT1kRmm zB|vb@V67oOzEN)F&x(5&-3BubT5ZLX8Z$;|wZPDfz^XRI2rRdebUyr%q!zHbZao`Z ztFx3SpCaz)O;8Fx#Wbb9ul_Wva-ozl8$VcM4`Vrhqs+8B#_Z85uHl;~&%;W`t^6rU z-eZw{o$0aJ_dUDt6W4OB9S^lISz2{PYMDBMXuWiCp1ha~?&(dt;DWL-#ag$PXS2)M z_nU)(vw>rv^_hO9(O{PRygeK6YYSpN_E!(b4s8;toPyjqlN7$MDn^nWD8GoLAv{iE zE@h7GH*g1HCqrswIrgR*svq6!3wO;q6SvvHxwn6AVJLozBAUUY^VXN#bEa|!F zZ^)+28gDADt)WvgBDC}fqA0r6AFNG&66VYq9}dve*Fk#(Bj4p7S~zlVvc#HY?}0{j z?u{te9x@ z{-miWBxDz-)XS~=DYedoam9Q(b?@d;`;epsG;y?gL6| zphhk!X#n{$*BAcOa4el;_hHt88iij0JpbN7vNLLhh{Z{qJ%5O=iSf|Xx0_K(ogMs@ zWWg#ZWMtDXeXrAsuUm zl2%)TrLhHPtD9uFUM~-XVu&{F9t~1bsQg#8OB_XlWe8NjQud|pvMF*=CuZZeW{3+# z`wv0tV{H*`Tmr3n(Vf}{`QlLh!gw3zfE&S12^HVz1h6F?$aNO4In;{*zj0#++vj!L zE64+o=yo3R9(8BHZ54YXpe1`mk+&%v=Lg9+TZw2;Z^uDzzpVxnbfRV#d%k+ZhBNpb)tg z^^=&ZdBU>4a55lCHAyg#yzzOvgCwp_VVdUQ3Zd;%^{5*trQ5zOwg0!Je5By4lw7*R zi_umZa5viniO)^+yT3=zCS@s;2=P8zOrye@j;E9}_2Sdlp^H}Jb&Xjk4;y3-=wvb5 zQcVGRJmxII#>J{AM#$jCalZ7i7sP9ml41>b9eytZau9R@2zBf|U5qdK_K zq-LbPK7z}Sn07oo#GkpPFs~erqJaROp4{raH4Uh@VHq_QqC=JxQH=zmLXif^HHUb zwUfxQ?l-?%d+5zA?VAgERb$p6cxHa)TPuQKv-kUDb*ut&loIyKh`36Uwa=gV=%ltU znnT7(zQE|HHX@*?wai~APn%}zaqYuNp~uZ(Hj-U|^eYo+`4Nz?GOLG2F@!iFurlp# zr-Gj~MHw=x#)St8ac%v+JsJFBrr9|;9a+O;mTP@0KzV3Gelm>nj&F0(FkNMpW=LT5 z&z>I%Uuq`XxRFJNPJV++EpEwc43!OhlE&%*jEO!iD3{qSYbgJ^shh3Y=h2i-$~W*% zvX?P%DTY2VW(|OAHVj3SLT#=3G{NK$DK(C7tZRY2dIw(hMp{y{qPV@m=?EXzB)DBO z%d2)20k`6gPV3zGT~;c03atfH%52ga^7GFC-H%cS<)>>=Yz5&Z^GRRIvpL(!S31Ch zW}0iiROr>8zGJrz|5#jQMmgr&!{SK?XP~A3Tp6$tF;4hu|2b|&kKH>Q@eQEfy`zb2e9HIux5=A0$QrEO0UdLarCT05>4b;qCFEyHfuRHqD3 z8$1hGH{40eM`rG04a;XgD;PhS$oXUyv9d4O2`gEj;fq6OSsg7d3@+$}ouQUnefsOW z>^z*PULQ?2EU3>~jB2AqLD4$1S^dQ3zeaVcUyWV@NbXBc#o@t<^YG2sXqv_30P^hC zKez{&V>J9OZsMwE-s?!LrD?Odx58q1 zUf=K-S!px80XLtqWyEX1NY{c3Mow`TB0Jn860tUk11SOK7u288AF?ellv{ZM0|rgq zGwI)&Q|e9QV_32VtPA}L7uTf>>R+cx?$fQmb?h%B8n+DOZ49z1qW_s>ro;HXOlg0d zjVFi?xl@=)MyMA9l%qH*C9XeL+zB~c%X+`iw9rLw2!cuPTx-ky2oSOSfp?A2=_slKN*bU1Nts zpT02p5-C?)2&Yl2)`0n;Ddm=2L}~0wAUpXl77wa%iWbzn*0iO`fYg?mMozvvGCzcRlS7cWq>@FS4Q+&t`rD=ilabS!~-`oN8EZv${2E(x8{R2YhPa z@zl@TRMT=BC|E*fP3xXpKG-Wp{JJE@@6L;nAz&TDMG(>jynJM!+QPhA!)*1u-&pPW zR=Xb}M2-6b^E`J1ul0LACASAnF(9>3RDWTAGJ0i_;n|7m4Q5tKlP6Q|d!Uqh-<9pb zJ|^(oYf1YrqU0ovM~xQ3zvv@iwiM45XyNFjBeHf14{)96An>>F5Mpu6^5WXCiT14` z2kX}`vn-`+Glxhxii{W9zkMfA0wMHdxiC!~xMN)6O(T^gwSQE;hFxvTpwFZu=2%Hy z)gfGj!n})HIkXw-*PCt{&%<>*7{egO;jOmNYRH{r-UGMUCJ{j?tX}NSFHRnIvHpM! z!P*yr_Y=DYC!^1Lxj{dTy=Y=+7#|IHi86HWR|HS^c5s)N9aiWr*RVAOP{h`uiebMD zXSHGTfbpiU@1Enq{057D0KK?{b*uWg0df<8gu&KvS=9|VFIHzlUR~EY*BXc^Lh^16m@0RAb_&jO{?JVAf2-i5)m7g?L>;9--p#7!mGN#Q2xQc1*I zsTpe(VoIxpMKm|z{6*=2;-$uBC7XRVZMJ4wCF(ED?@m?8?U^rB>FD1uO$}4Z)cqDh zlQa+C&(Ab>Azw^4D^%1~cPujd6k)n8ka?S8w)wf_+XL;piUJA^5k{QR`XbnMD4hb- z>qz+(K-{6UA+sX*45|4b91w%>(}Nm;+v!*`cFTfc4Zcl)#WxGck>l}qV1@BT!2=Y@ zOpXoP)!o;u6EhAsb$?jjSg>U<<(IeXFlO=2y|1-kGmBPPeD^X}7MxFfa%wie;Gb|_ zhRLC=a~;5xY2HzDBC0CdvNfGW)T)f)i+HQv3V7y(&AVwG5;auP{T|=;EiN;3p!OH0 zy^%4 z?$Vaj)CtYD@UPM+BJ-?%{pwpuhLO8)ef0Rm?+@T!FU7L_h9*x^a$1y;7Q;ZTvTl6; zG`rL9tr6;UcnU+rWF$dt)~Gm4+QgQK{CoATk8^+U_k;5);4*#1?b_^BA!j9DWkHd< zOEWR3iwGjw2i9AG%n`E>sAn03zjXEA!B7R)u^e0iWa?zvaz8#S(0eSoFWS3a)b;yM z3wC#_XBkrwJ$P)OsNcLY$FqCH`tdFxY2I+E`k{K7mm0JMo28i`7wjlMU1VoSS@}dP zuHa?Mex1Z|_9GZueVINeca4lOQ;|sSA~1y|>ve03pyw3dD`Ms+?6{-qS4yxzFYAT- z7I%O|3`=kN+?sHK<=#g24bB4h^+N{|-KZ6;f#!boEr#h$NXsf0} z(BXVfgQ#0!T#Q`q`ASqfQ*WKd4`i!d%oFRMP=zTZ6->QN`ki0#=S^X+aHHqTX{W(( z;36VM{uOBEpyt__Pm5=*_~4AqxGCiL)5m^tHIc9-$+^c}=JGWkpkc1ZZh{O198bj4 z^CA#&ah8YVEf!>&Kiw)$O?M0T#LF;2Bad`Sb{$d~$&wcZ2)-+d@7KWSkn}TWcG-1k zzwn2U(I7?}jFqzmA8Z8>THB@9Mlsy$E5mrc{#idSD{ZvHS38K7MO%LIL~K~Y#d6eJ zwDyC1@t^ObH-k*Zl#};sf{j}h;S;x|-uHL!*e1PA5U~K(Mxujn0zi9~a?Nc%IZ2T* zIV|aFdrU%FKfS|d+)-{*(BxbsyhbtF^{`BE$~D&17Nd<4VC<=&3!{5r)S9$Glw|I# zxiRbupXv#al*r*sTH?-5a^=~ZzUl*<$z%wLvDkY*TtZ*;w!|m^em-qaNmu>R;;~1P zoxd743el7>5-eY2oE_h$W4^;U#Q!c)Z%XPcO1pTuMl_SGW$}){ulx*3NPA~vEAe+m z1yQf>=sh% ztz{2|c+*mRCaOPat9_Ad`7_dxcmL0qRb@i7hy1(cj27i|@`;+Sp{SeAGS{3~CMN z$-q%RWW*zWipjWNZ|*WMEI(-n6d7RFEWGDk5mni8Q{wlFhi;0M)7JV`6jB%(#Do4P zf+{eA{gTfx9rT0Y0&&2s0jcIf#(@ccVWzE=1FKaSG;3N5h z)ftnqLb`%Y@mZtRX;sSM^>oe;a&R{AFuAp&b*uUWu59n{09_m*_e=_D6GHc~l1UP* zgk~y=Ni$*z*~{=zQhE#fP%`k|5q%a?Sg`N2kQu@hES_U|ho-*>u5Ep4p*uENG_S|Js!Bk`gpZ^2gIh(tD z>=+mRQ=j_F&+mwhQ;U>XuPyZM`Q);EQh4C`=FNcxj>&A(7OaP1 z`R23Z8L}}rBIHhd>Z!%OZ(;lB=`2>^(l*-n>e;lNjegkMFIWwAt9ER98{zjng7CAn zGh$?crTp#0W0-#PZ#@inRg;fzZqiET&V0`~A>SH1w#b3cW^JhR6*IMd`xE|v`u>35 zP4J3PxuRB$J8{RxeV%5lQ|Pu+*sFdsW1T-9V+tCTuS;@~dc4z97jPWuC?Txs!M`?7-k8A6Hc5~(4r2-jw=kF{)H3=YeCuC|$tMtqTnh$te$}M#!N;hAysMaLOmv zDNLeW-9DQKfY%2T!b2*Ve|y0S&xr9)9a0EQycb8z?5lk=dhcZz=^EiSi84A6-s^W; zYZ^31@>@};-FKB#3rqCNE)9rS;E~6mO)YqUkFIi^*Q z7Q)Ty8s~%&MTC3uPpvVJ&1hTX_H_RYc!`+AJsA0H?1bklJ0^+$W$uo=G-r4BQq$PS zd4cfYVilX09_aI(>{Q>b6x7~5;U`1B&LXO`qzTjpnJCNQh8X%ogRFVtbJwBR20m??plS8Q|m-QR0rWjfJ0;zZ{gJBMYC`Lj0*HT6Xn zRBRmP6YR$W2k|p$h}qWawn}C-db~{#llBSK?v-!+kj_~;yrY8{R+xBMoy< z84<|qpx6tbUBY70Lq|^aEU4nv8e2?-SNZtWN6=^=ufPv*({x#?KAhPcpXisF^U7qq z{G|D&Rhor8T(Pt|XM>)OBj$OZqK5bzeWtZ%KpYdJzILTwpJZDpL7;KM_zeuc`>1s? z+BCtd%6O84cMPptEwfgYj@weYOWha8SNdwoH`rbzGQiR6E=>O$3Z^)72x{iIIF@sEije-A_d#N7AUwsB8J4ui9CGk@ks)Kmn3u%K$1gKB8YnweB(sL4_J?XHp$>izkD23HfcojG?e}OxjZP>a z>|B*!gWpkpy*EO7V?~bTcetA*=0T`;$jEK1mvZl@{{ym@OOwwik6a#H0xb6G+-ztI z{ZSFnHa7MpcB)Z=Xj}2lJdufX+r}?BA{71<5GjUm3oP*769J{^JMg_IRROxMk7Zlv znN~In7UXX|j5sXwWh~t=Z`m&Y0P<#jI)DxreR}RjpTD5@6QiO{GBjKF0MlhTG@US+ z8}a?A_ZPb`M!=2=yTx(jhpCxj33Ckbj5M9_AYI2t=2XmE)87Rj$P38eh9N98bM#-g zd05=?ELuW+mf2n`@xNCXFzgsReR)j$LyNuU9%0-5(-%5&C7VlFHe4jkO@R z3LmgF`9U+UK5Hg)Qm&@b7;qOBqfy(Yvtyux3W~?Lep|;J@L6byJ+XCol5FYFEJ!iV zyq#PWG}S90Gz5^ZksV4$7C)eH2SC=5(UFbw`41ro25{yglO`6 z2K_VPfsD)o%lOHi20k^?bq4N}fSU%TG*B;2cpduvvURb#}zshZ(= zc*bHNW_&dB)lp!1E>e?6nmv)_>RiPqI3(b_7SQm7icu!2l{@W+KdEwrzv{W^xdSUW@R`Xl0$&If>qy$c%aj1vwij;Rf;N$(3249QwOh3zV z1gKCtB*E8mxoU=+CK^A;bsQKTR_1>j&S%CFRj)&ITZce;G&zyC=6wzgr%$1bW1)LC zjlUNPB+o==S!6A961JVN=g8u3iM|_1#pa(~@*?bj-(S{k^2L4+hnDNO@0@VDEI^e2 z1AEn*)D(S%pNsk%?h&Y*&qt4iYp~huq<=W7sS_!H2_X2>g`Xy*C;$HA@rlVLUr!-T z{7AMgXovVczk*sNtLjo1CZet_wwHlb_LKaStun#>m;1(t@%22)p?(+oOcXoETSy%Y z=+3To@cs|^i_Fb@w%>Vgc`(-WLCvoRvTrz~4?GMW+pm&}B;5+k9q~A5YcopoGJoi$ z)V{xUKi&iGxVvShc1j-=QGG%bBoUd_czh|ELmQ#a-;f0EW&H|bY$ zVT^HgiuouKD(4kbt*zj2qwX82i-Q zSJM(V>tNY(9y&a1_Pt?`{O*S?0-9D^#dFV^qLrX#cmvazXT&jL8~)$}(DO$-$I~4n zXG)fo@qY?K@7pq5nDx3XR1KXepZG&!x-ztSw?9i=G^>QB*ambSppC==@(u?F>)`Bw zZ+OmO-o@rJanaD)h{P`gW#3Keex8BGR-2AsGIsA3YPAnGwW)c2AH_*hQ!n)RQQ|hZ zJWuXB%=EVP)RjI|t`vD!GP_VmF82b6o$C7hkX+q7MG_ZV=HXm7l6SE7hP~&4A-(r4 zds73K#f)zaCrh#;|7(!XZT6YkO0s=M?i!E&PUDEY0ISpO+z6@~MnY?m;ZPw=Go6)L z$a3mT4(*3Bu4+hLk|4vyVT9=)OOv*zz89->B0cLG@@Wy83;OIK3nli_OdkBT0cg%Q z5yl5g8MTTPlx9Of)dZxjG0xbRr@K$AMt)O+a?aUn7aIaJ6w1TuIR}?Sk(89tN#q*H znOOl|tQ#-qXYyk8XJDSUSh|AHJWwwQFNvQuew4FFC#@~$mc(-d{_zm*@0cQZZhI*N zJ1(NGFNR3>;x=uljjf=T_<2*y4+`$uFD`2qqJlByI<>_h1!nanwIqf7;tl%EGj1#U z3~R!-Ulh^{Na1qBvD6?t5`zP7C-*){3%|8IiyC2Jdro-mJp5y(RW>jBvo(bTrgtiT zq)#p3CR97O!t|hIR;NDM0Ol?qKUo>!>7}q#XgvGIkoK!tNsMAvvCBb)WnfA7fP{P? zK7R8}5x8slsKzttk)x`q6;A-Nl+Zd^2w`u~&9)!U{!xHXpJ9Y-LIh=LdZL0(3|?Uq zIP)bG>9x6ys^z2u<>7wHRPOraO~w1$XtweuchUAA?4W2yv}3sEF5wct`T(1rv=uz){e1&?%Hdm?qJj2o025?tndi{s1Y)l8-{v(n_% zb$#~><9nHe!;c?WBeeezS_cUkH5BOT6At%7BA_Q;S6`i;3#be{#1ZzNIAJoK4$DlI z2g31J^hr2&5C{*KG=-3Zs&~R-{NE*hesC?y^=o>XY;Ep7jTaLz$Cml9e1!_$_@!dL z$$vgTW!P$N&YxJcxT{YF5vyS5&BbVy zfw*nLkLfS)Rv7%gRJyx5koBdnK7IA}1$}CDeQr|jAYhx)n@V~`II&YJ(%$e- zh2UuL&?P{4nu1u>@Z=AirhJU9MC$9B%*7AystpZO*Y8t_z3=Eatlo7!(%sy;Nw|mq zd~m~W4lC`=lHi0^m;Ggs`dS91HrcMQRF=%RT8XHi^Y?=e@XiIO*kYHb5H;T;CRCDx zl|!-m_xhOOVFnq4w$4yN+{b3NIn&v;n1(Z`s4&zq1HeB{lqtgkC6rj()H%j561h5+Yt`Nn^-mQ3&OxE zd~-g(abD1dJX5b~CqF19Fc>dMX?}BWfl8G=iV~A>8l;N0VKeU| zfe13)T6;Q}0DsxXTP#gCb*pq*UXAy+>elwsIkZ)7!>;C)1@>D9!>+=GHgq4TN`)#> z!?0hbJgtPNl3OimRAjL~H3HkoRG*@sB*@yV5XFKs>|Sf|Osy3B;F15Tk`8JB;FsBBcI=53}Ngif;}RlUNy_L#4g*u=>g7gEn+ey6BVcZ=UzWJUFkhF4&+*x ze`CNu`^%`dzU&e(7R>(p=GeNPmw&%B;L~@d*vR+ss5@c<;rj1H>#)e;O8}|n%kK=& zK4F|>cE^rQRwjRj@>J601LJw(mJ}&nTGcS6f2T-x~J8?{{;H zDu2`e7J-YLneum|IKKLgm@8{UUr~JSr8yvK#Me0KFlos@H}%WGJ3$Y8h2K?t&F9&E zPJL`v`&B;iO@J;+tW4# zRr#CtC@`q)KOhUyn!EJttG#w!tAVI@Z{;dSmow4XK0K*l1mc5{PYgRP6y9kWUmU3M z$j2%<(#jh_DkndmQo*Skx9!zaujW~{RHIzA2hK^1Af8dL;9c<@SJVB-*ZN5>0q$gO zne8vtCpxJLolTOjLe#C3N}Q$Vp3$Eyy`82@K=;5gZl{+Au49{gsI5GVZgN?ouaB3wk9Kbr5KA%Xq9VKX;{Uy1icJ4_!QgzOIN9h zBB2h=i-n5qm!_(0YtBIzdm*B&{|`mi8O~PU#$&f?bVTh@JVulnv8h#CjMyF(PQKs#z3ORB7p(_uKi9>wL&{&VBCR{72tc{B(XI za=vOS1+NAdYvtJpImyoRE}hywSD@W zsbIGJZ3Ubic{efJ;JEfAY$M%G%&|`ktB4V=rMFS9T^x{c<0$0%vMv}p^Y}%13t!2j zp#*z}ymYD=JiOND^;}upv&q0aB~87tzIg|XH8C~q?h@nWdFtqGmv+3++U$R^Rfy}` zY2j&n)q=vqbD7Vl-UrP~ICXvu;b0kI07ur%Xb;{l3eTX6p)3|b|5N0*s!{}*QRp7P~CnRB*ho`U>N|_*9d_^zD9YqULu3;Mxy`| zod=49TD!ICP%)x(n*>t&5#=Fu&2avO{~FaKl5i_4@I?yO4!P-5q^F^0^MZmT;CxD( z^&j9#_OO?b*v6RhGO9^1^~P9eo_t+k&0Kw7inyP6VYwG;RszX3?#iN2mdHcdmc?$q zR7=K-qJ}G*xh(RMbXzuiZ7Ut~S1)!{L~Z#6#=gSV-dE}bjhm$-Y$uS_c_S~gZVgvl zx&I^Q9pbyo30ps%wcyRmBCOo~9t$(hOEwdh^c#3my-<%ZPA6QP*&HSJ*_)AZ<>XZM9kUS49iq-jZq{{ zj^~d)9$^kO;khMNL1ChY3<7SN<{**pJ^~vrQe%wNLrj`}+lUG*OmqoQoMAWiYS)m3 z6|~X+*U4ox8PE6n2y(09WDFfpS@=Z)q?;rCQ- z=~C|du~%bTVI}&iw95y4D7oJ}_#otu)@oXA^Gl)vc?BLK?`@N=js#1^*{S1<Tsc8EjMShBe+{tdtJLM;;X)1Hq!B401Ev#{mD(oyF1U6aJnc^)$*eEt zZ_On}EKGZbz0eO6khX@il&uH?5(W((#lCW!`^K5}x zzY=e_SfT3~JvoOq6fXD;XMtDGq=sTD=vjyN^_0}Dh-XlaMeV=+iZa{CIi(4yG$g$5 zodv>cO8b%;TB5p5h}oAtItV<+JOSt6l{TW}iA;IwirmfRA{kG$(Ql+NQ(m}Z=3+rG zy@Z*(K|}pJz-tE7r#NBXc&bPBF{1beMdcWSEQQa*xnsA9Qo1+q4^}>`7proUh@o*N zD0sJ-jc!4t9G_(bwDHE`|3G*l03lcwyaGBw|H9(K>H&^M=QMg+OrHA_QZZ?Ty>O2G z431tXZj7-Le5T@S{p~%~Lp`SJ^a4?XvC%c#WGok^TA_q@Db==M(rt&p17zeG2XRFL{8IAh8 zL0|>_TOirPz>j~P*9bBU1o$>v6fAZssXd4npH^gV-g14gqU`6-wU%RAu>^@ivb@`5 z!b0MzWa>SD$WK{Dr%(N?{X*gX5&1dUk!O~S9$*6C{OAhC4Vm%F*eqo9qAJU-b3pSiX8zQH?2<2AVqrN4Xk(KE)d{ceT%0A;> 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 literal 0 HcmV?d00001 diff --git a/rs232_kanal/server/server.c b/rs232_kanal/server/server.c index 7a6b79a..98a72e2 100644 --- a/rs232_kanal/server/server.c +++ b/rs232_kanal/server/server.c @@ -100,6 +100,7 @@ int main(int argc, char const *argv[]) WOLFSSL *ssl; WOLFSSL_CTX *ctx = NULL; + int autentizacia = 0; int zadane_rozhranie = 0; int generovanie_certifikatu = 0; int nacitanie_zo_suboru = 0; @@ -115,9 +116,10 @@ int main(int argc, char const *argv[]) } else { + printf("---------------\n| Certifikaty |\n---------------\n"); for(int i = 0; i < argc; i++) { - if( (!strcmp(argv[i], "-port")) ) + if( (!strcmp(argv[i], "-port")) ) { zadane_rozhranie = 1; if((argv[i+1] == NULL)) @@ -134,7 +136,32 @@ int main(int argc, char const *argv[]) } } } - else if( (!strcmp(argv[i], "-n")) ) + else if( (!strcmp(argv[i], "-cert-aut")) ) + { + if((argv[i+1] == NULL) || (i == argc-1)) + { + printf("Nezadali ste typ certifikatu autority ktory chcete nacitat\n"); + return -1; + } + else if(!strcmp(argv[i+1], "rsa")) + { + wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + autentizacia = 1; + } + else if(!strcmp(argv[i+1], "ecc")) + { + wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + autentizacia = 1; + } + else + { + printf("Zadali ste nespravny typ certifikatu\n"); + return -1; + } + } + else if( (!strcmp(argv[i], "-cert")) ) { nacitanie_zo_suboru = 1; if(generovanie_certifikatu) @@ -149,17 +176,11 @@ int main(int argc, char const *argv[]) } else if(!strcmp(argv[i+1], "rsa")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); if(nacitat_certifikaty(ctx, RSA_CERTIFIKAT, RSA_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); - } else if(!strcmp(argv[i+1], "ecc")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); if(nacitat_certifikaty(ctx, ECC_CERTIFIKAT, ECC_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); - } else { @@ -167,7 +188,7 @@ int main(int argc, char const *argv[]) return -1; } } - else if( (!strcmp(argv[i], "-g")) ) + else if( (!strcmp(argv[i], "-cert-gen")) ) { generovanie_certifikatu = 1; if(nacitanie_zo_suboru) @@ -182,15 +203,13 @@ int main(int argc, char const *argv[]) } else if(!strcmp(argv[i+1], "rsa")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); - if(generovat_rsa_certifikat(RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; + if(generovat_rsa_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; } else if(!strcmp(argv[i+1], "ecc")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); - if(generovat_ecc_certifikat(ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; + if(generovat_ecc_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; } else @@ -201,6 +220,12 @@ int main(int argc, char const *argv[]) } } } + + //vypis upozornenia o autentizacii + if(!autentizacia) + { + printf("Nebol nacitany certifikat autority, takze nebude vykonana autentizacia druhej strany\n"); + } if(!zadane_rozhranie) { @@ -233,6 +258,8 @@ int main(int argc, char const *argv[]) wolfSSL_set_using_nonblock(ssl, k_subor); //cakanie na inicializaciu TLS handshaku klientom + printf("-----------------\n| TLS Handshake |\n-----------------\n"); + printf("Inicializacia TLS spojenia\n"); uspech = wolfSSL_accept(ssl); if(uspech != SSL_SUCCESS) { @@ -245,24 +272,24 @@ int main(int argc, char const *argv[]) free(popis_chyby); return -1; } + printf("Podarilo sa vytvorit TLS spojenie\n"); zobraz_sifru(ssl); + printf("----------------------------\n| Informacie o certifikate |\n----------------------------\n"); zobraz_certifikat(ssl); - + //nastavenie funkcie pre vypocet kontrolneho suctu //nastavime typ "crc" alebo "hash" a nazov funkcie, nazov druhej funkcie nastavime na NULL nastav_funkciu(&nastavenia, "crc", (hashovacia_funkcia)NULL, funkcia_CRC32); - + //vypocet casu prenosu suboru + printf("-------------------\n| Prijatie suboru |\n-------------------\n"); clock_t cas; cas = clock(); - if(prijat_subor(ssl, ctx, &nastavenia) == -1) - { - fclose(fopen(KOMUNIKACNY_SUBOR, "wb")); - return -1; - } - + if(prijat_subor(ssl, ctx, &nastavenia, 4096) == -1) return -1; cas = clock() - cas; printf("Cas prenosu suboru: %f sekund\n", (double)cas/CLOCKS_PER_SEC); + + printf("----------------------\n| Ukoncenie spojenia |\n----------------------\n"); //ukoncenie spojenia, vymazanie komunikacneho suboru //a vycistenie serioveho buffera diff --git a/rs232_kanal/server/spustit_server.bat b/rs232_kanal/server/spustit_server.bat index 30ae5a6..3ca3f07 100644 --- a/rs232_kanal/server/spustit_server.bat +++ b/rs232_kanal/server/spustit_server.bat @@ -11,4 +11,4 @@ :: -g rsa|ecc sluzi na generovanie certifikatu :: -n rsa|ecc sluzi na nacitanie uz vygenerovanych certifikatov z adresara /certifikaty -server -port 5 -n rsa \ No newline at end of file +server -port 5 -cert rsa -cert-aut rsa \ No newline at end of file diff --git a/tcpip_kanal/klient/klient.c b/tcpip_kanal/klient/klient.c index fa85116..35bb8e7 100644 --- a/tcpip_kanal/klient/klient.c +++ b/tcpip_kanal/klient/klient.c @@ -22,9 +22,12 @@ #define ECC_CERTIFIKAT "../../certifikaty/klient/klient_ecc.pem" #define VYGENEROVANY_KLUC "../../certifikaty/klient/vygenerovany_kluc.key" #define VYGENEROVANY_CERTIFIKAT "../../certifikaty/klient/vygenerovany_certifikat.pem" +#define VYGENEROVANA_ZIADOST "../../certifikaty/klient/vygenerovana_ziadost.pem" int main(int argc, char** argv) { + int autentizacia = 0; + clock_t cas; int uspech; int generovanie_certifikatu = 0; int nacitanie_zo_suboru = 0; @@ -56,9 +59,10 @@ int main(int argc, char** argv) { //skontroluje ci nebol zadany prepinac "-g" pre moznost generovanie certifikatu, //ak ano pozrie aky typ certifikatu (v CLI argument hned za nim) bol zvoleny + printf("---------------\n| Certifikaty |\n---------------\n"); for(int i = 0; i < argc; i++) { - if( (!strcmp(argv[i], "-s")) ) + if( (!strcmp(argv[i], "-subor")) ) { uvedeny_subor = 1; if((argv[i+1] == NULL) ) @@ -71,9 +75,9 @@ int main(int argc, char** argv) subor = argv[i+1]; } } - if( (!strcmp(argv[i], "-ip")) ) + if( (!strcmp(argv[i], "-ip-adr")) ) { - port = 1; + ip = 1; if((argv[i+1] == NULL) ) { printf("Nezadali ste ip adresu\n"); @@ -86,7 +90,7 @@ int main(int argc, char** argv) } else if( (!strcmp(argv[i], "-port")) ) { - ip = 1; + port = 1; if((argv[i+1] == NULL) ) { printf("Nezadali ste cislo portu\n"); @@ -97,7 +101,32 @@ int main(int argc, char** argv) cislo_portu = atoi(argv[i+1]); } } - else if( (!strcmp(argv[i], "-n")) ) + else if( (!strcmp(argv[i], "-cert-aut")) ) + { + if((argv[i+1] == NULL) || (i == argc-1)) + { + printf("Nezadali ste typ certifikatu autority ktory chcete nacitat\n"); + return -1; + } + else if(!strcmp(argv[i+1], "rsa")) + { + wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + autentizacia = 1; + } + else if(!strcmp(argv[i+1], "ecc")) + { + wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + autentizacia = 1; + } + else + { + printf("Zadali ste nespravny typ certifikatu\n"); + return -1; + } + } + else if( (!strcmp(argv[i], "-cert")) ) { nacitanie_zo_suboru = 1; if(generovanie_certifikatu) @@ -112,12 +141,10 @@ int main(int argc, char** argv) } else if(!strcmp(argv[i+1], "rsa")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); if(nacitat_certifikaty(ctx, RSA_CERTIFIKAT, RSA_KLUC) == -1) return -1; } else if(!strcmp(argv[i+1], "ecc")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); if(nacitat_certifikaty(ctx, ECC_CERTIFIKAT, ECC_KLUC) == -1) return -1; } else @@ -126,9 +153,14 @@ int main(int argc, char** argv) return -1; } } - else if( (!strcmp(argv[i], "-g")) ) + else if( (!strcmp(argv[i], "-cert-gen")) ) { generovanie_certifikatu = 1; + if(nacitanie_zo_suboru) + { + fprintf(stderr, "Nie je mozne zvolit obidve metody nacitania certifikatov naraz\n"); + return -1; + } if((argv[i+1] == NULL) || (i == argc-1)) { printf("Nezadali ste typ certifikatu ktory chcete vygenerovat\n"); @@ -136,17 +168,14 @@ int main(int argc, char** argv) } else if(!strcmp(argv[i+1], "rsa")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita_rsa.pem", NULL); - if(generovat_rsa_certifikat(RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "klient@klient.sk") == -1) return -1; + if(generovat_rsa_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + } else if(!strcmp(argv[i+1], "ecc")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); - if(generovat_ecc_certifikat(ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "klient@klient.sk") == -1) return -1; + if(generovat_ecc_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); } else { @@ -155,6 +184,12 @@ int main(int argc, char** argv) } } } + + //vypis upozornenia o autentizacii + if(!autentizacia) + { + printf("Nebol nacitany certifikat autority, takze nebude vykonana autentizacia druhej strany\n"); + } if(!ip) { @@ -181,18 +216,23 @@ int main(int argc, char** argv) //nastav_sifry(ctx, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); //pokus o inicializaciu TCP/IP prenosoveho kanala + printf("----------------\n| TCP/IP kanal |\n----------------\n"); + printf("Pokus o inicializaciu TCP/IP prenosoveho kanala\n"); cislo_soketu = pripojit_na_server(ip_adresa, cislo_portu, 5); - if(!cislo_soketu) return -1; + printf("TCP/IP kanal bol uspesne vytvoreny\n"); //pokus o vytvorenie novej wolfSSL relacie ssl = wolfSSL_new(ctx); //priradenie file descriptora soketu ako I/O pre TLS spojenie wolfSSL_set_fd(ssl, cislo_soketu); + wolfSSL_set_using_nonblock(ssl, 1); //pokus o inizicalizaciu TLS handshaku so serverom uspech = wolfSSL_connect(ssl); + printf("-----------------\n| TLS Handshake |\n-----------------\n"); + printf("Inicializacia TLS spojenia\n"); if(uspech != SSL_SUCCESS) { char* popis_chyby = calloc(100, sizeof(char)); @@ -202,18 +242,21 @@ int main(int argc, char** argv) printf("Skontrolujte certifikaty.\n"); free(popis_chyby); return -1; - } + } + printf("Podarilo sa vytvorit TLS spojenie\n"); zobraz_sifru(ssl); + printf("----------------------------\n| Informacie o certifikate |\n----------------------------\n"); zobraz_certifikat(ssl); //nastavenie funkcie pre vypocet kontrolneho suctu //nastavime typ "crc" alebo "hash" a nazov funkcie, nazov druhej funkcie nastavime na NULL nastav_funkciu(&nastavenia, "crc", (hashovacia_funkcia)NULL, funkcia_CRC32); + + printf("-------------------\n| Poslanie suboru |\n-------------------\n"); + + if(poslat_subor(ssl, ctx, subor, &nastavenia, 16384) == -1) return -1; - if(poslat_subor(ssl, ctx, subor, &nastavenia) == -1) - { - return -1; - } + printf("----------------------\n| Ukoncenie spojenia |\n----------------------\n"); ukoncit_spojenie(ssl, ctx); } ukoncit_soket(cislo_soketu); diff --git a/tcpip_kanal/klient/obr.jpg b/tcpip_kanal/klient/obr.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77d95676bab95b91bbc3c95d2fc663635cbda5a0 GIT binary patch literal 51156 zcmeFaXH-+)x9=SYy$S}Tcd1emdPh1)4ZSHH5_)ecU_l7IV?YQc^dh~gAksx337}M^ zDIh4l3J<^k`JZ#{bH{ygeO}x#o^e@8$l8nVF7vbJ$ewFu&7I57mtO%lbTxG}0eEATg#8+(;SIg!A0F5Tg##N2v>UCYN30xDnCU8yQn!q)I|0@Yt zz`UJ(LIOC9+idJjejB!F~I+-?P>)gJm9}$3ZknK6D9!RRom6r2~7qb z^MBRz@c93&xf*A|$NSIG6Pgly{Qs;|*#CRy|GZzV|Ib(r0PphiA;Hckt0)6e z5D}Mv{Id}}Qc_Y1ata1YN(Klg3n%2S%Vjr!h6M2VDuTk}1mM%)0cr3qKLFUTj*{?d zbm^Y~rhgYad>{cK5itoV8Tpl<`NoySKp;K=kdTnzYS;+x(bfL}1T=)SoZ!1eH;o;L zx%@zo=+r_IZq@o8I_Si29&tziC!}Qbw-^|iZu9c-3kXU`N=eJe%BiVqXliNe=$e?C znOj&|SvxtqxVpK+-~oX_!6Bhx;ZL7Ek9iRrhe%7$$jr*ld5J74EpOGCa0!9f0_BVw7jyq_Wj5D#?J2E{=wnV@yY2wcKu`Lf0q9+ z?0>S0=E^R70sMQW&dT^f7>+!pa9}sojf27KpD^-VMgIgsOmL+)=bDr z030{zDu4qbGsN>u9u{`_^5Yu{8yX2HWd1CQCgTP+^WXg;5EZ7z^EF^g+sR-h3P~;snH*+9a0xl)`PJD6fUS|7NcHJvZfzJ~2TZn0MVJfNh8R7*GOM zz4b@^VdQH8!q_hkE(2LFF9Cs2okn}SThU1w6Sw_~l><%c`^3n^`0=E6DP>bqJ6Wj1 z0m+Pm0G0@htaf%_Lad@yz3$gLchV^ac)W>&Jh3lL!6rNoF%Z&qjc$)ZRcR-JWdyps zMVJTJ)+Z*1Wz$)zlG+gx>4_f4eJ(7y_eFdF&9P@_I&e-bVX0a)Y?)j%jkKL zL6OO=IK+ef@Gvbvh5R-2C+Piqx}_o^ov56OVi{YgiVVf;DtIxSACbl#K?A>0vox9n zs5_a@jr(ve*;4KKCda572pU5yYY!#HzwN z{e~w?DRgzVceICd`Dod53pe`$!`-v&KhQP2O$}GO@!<`)8%;ud7eNFnilUk%Pe3wI z0FizrKrGrat^&n2fG88Fx}EtT4@bf8NQ(@|;3Z;;9ePki6wB?WxWv64K_^+Yff{@W zZ)eP>FT9!4fvG>qiaB;>XWF;qNbeu;sq>0+nk0QGflReKW({XE4>^9G(Pw%Pn^;IQ z#`fclsXsrk$mT5K%!G%!{Vw3Jry^uN2N1(R8D9O603>3H zB*bX6M)RPrOYjHgOm}LDU?}3shCOTA;T01`cjv@eZD?jxVp_Tj2a^L}#RUAsUxpim z2lXJgGBevsseCl9g$up> zr`k@|K?DMnqxTr8N(5E{5P)aDao9dU@KdyiJHw1FK-Zfej~av2;4EwdK^YPRA^i3L z$IMeGezn>PD6LIJT8!~PBITvon&B_%Pbf&C^25hL&WUb%6k;2KT^nQk&hEd7HA@K` z+~zL9V(|#K6Xi)z$tYwvXx5;~-(a zMQK}mL97?ew_Ac~LxL^@?JZehekwOc*!BfU*_KcqULPLs^ea*VbW@)jk@B&QicIdK zfaL4;`^pc$U(;6_C5&*$SLXL1!|WrrMyRV zc-4dViK1T~V((;qo0d7EBd9xDWg9p(Q3t=-c=H}O`F@4wN%;OHfXwl>xvChe4ls|2 zYS9{C@662^&29}T@l&C^BOvXE$ssy7X*I&jhb@EfSbA5NaglOaG;tQ2Dv0giM$uxL zQ>@wBaH8O!0&OK=0T_hiw zE?C#UF{Hw|TqG*qHvnxA-Lg74xh+jCyN zmvMw5DS7EPRi&^j0ho{}9s>csLDuql4Xpv5>3ms_y(f7BDjc3JMBPr+TsxAj#MHqF zLfm9amnA^bAjg!xEfo|Y{u6$NHZ*<|ohb_j;#fk$RyjIqYxL488xb|I=lUuRp9+k0 zeNSzD2aodvZ2VrfxSWaR&kR&7z`{|p{zTs-T_I^9Bj?64>vP%Q{7Pj(HOlycj(3^5 z^@Z$yk%GZD6u@+s0Mmk_!SaVqD!N5aHwXcUU0=8od4Q34t3-THA0da3<}eX6|Evmt z0o}(zVH64iKT}-a4J?T&yKNefZXW04D}_uz6luqnBJo!sSox#Z@S0uP%ts zOqkKUz?u`vEgjB6JOdLm>V+B-r=49>XA?(m2c#2~07Z>3MD(pd5KxoLSJ3GQeoA)8 z0gui~S8KmnD_Hog(sBeW1s`A6li*H&qaF^muU22?MpkN#X;b~ydODRc@Jo$}fH)6Z zKPvP*y7{E?0lUhuJ1|Vpm$Unc7GqAVaIQ(VmQ|topAZ(fB1g*pI*mR z2!Htvyy6}h=qo2G>K!2B;Oyh*BI4xZB^v7BD+(4769p(Jhx$4=dAI~}IJ&sOycPL= zb-v@{fH^DjSxD-O>HDg=xWlx={asAL4NRTFJ)C5n`IMC?$rM86LcM&wTml_9LcKh_ z1LQ&#x&F0vxvTm=&7xdN3jWTna!_^6e=Dw*6uJI=EFmEwA|c`;KK^c^U|CsNQ89=p z1R{K;5Dp0Q4s-|=_733w_XgBm0-XF|zJV|wZ;pR9=-}uR6sX7*6a;gYb9Hc)baZx> z6n1nFcNPYNogIW7oW;Sy&f?pu_B%lE%_|Gz|WwZAKqMc}W**WPuF>#qp>mH67b zu5tYpfxi-8d)GCtzasEg;%o1^#`RYO{z`o9UDvq&iojoquf6LU*IyC%EAh2=UE}&I z0)HjG_O5GOe?{Q0#Mj<+jq9%n{FV6HyRLEl6@kAJUwhXzuD>GiSK@2$y2kZa1pZ2V z?OoTn{))g~iLbru8rNSD_$%?XcU|N9D*}HdzV@zbTz^I2uf*5hb&cz<2>g}!+PnUb zwp}e2jl(l>_nd|9M^&f~zMX$v^qogk;3TL?jes6cprSUVQjC+}XUuH(7v4-pqaaD2i!(IUx|GF6_-z>>()_j%;b#Va0P2Xgc3V!OpZU z0r#6`6oN~)P&E`g@JHZdO!M2xt^B!3OiXI=m^ERc0l!q<_svlQPKDjYSK8e8Xfx2% z^7wNHrLsNruI|zKNkzT3hFu@(L&9Fc>Lp;hf?l|ov75baQx%t~@KKF{@+u8b`BV8A zi8%q)$Db*tb2w}h$abZ+EZ$3USG zro6{%ToJ3c&IJ-1FG4>ke+8Zk_6C@(Jjj>`<{WPdeb`GwJSC}&Dau-yj~=aNe|GNz zH2J8@B;M__aWGVaJW;TxTi5}<_)GQOH`7^l4Exg(tNKd-oW?q>U^w0*fTuViVNbKS z;ZEN-R=TFiPl;uFI0ix&{cm2ZmeFXd=RXxPYli^4!B@GuiYsm(75q#O`P6dLd#&$( zCCYY7x&*Xa*GNU93z-8)RFpRnQ$Ks%zoU(E7wU1r;>z_+W2eN{k&CI&L}>#u0M>J| zaeC1DrA5Uk85C6Fgasi< zN%FyH;K(sftI6qH&@6Pe1d+ zsr}4l^X%WOr58mRzc)i;?np%()o4q5`sDtk>EVEmy5?eiyVIZjGfne!P&5XpoXI*y<6#>wGoeE?dm zPG(J5k<@nkZ*sO0CsQhd!%Kge&J6eIl1eE4i0y1gB zsbRAkeJH`_YcVRLV{o@u9g-=)p`K;5esk7}jeVv=oAQJA@ln0>+u>wJQm>ctikQifEwmNVLsEv>I@m?KV*Db##|3+Nz5}=dzyL;lB z)HakzTul;}Rmau)GCP{_*D;o1&FJ%tylb(0ufGAQJT6?^B`@l($|Z3FVH;5 zN4@ZXiidYw!ELM;8MOq$49f^Lrt+1q;aJ{!+^oKZrg3nCe}dM><~vBc5kuEui=lyE zj{8bYwnWwNYMnA2_R-ztq%MTpq5kx&NY?-n>x&`3&2>bbU)g<;6f0-^uPhw}OZyj1 zwxo2-!74*&_c4@6F+#mDo(#KOH1J@ z=JuYo+T;UR8^CWSdhzx9CQk)q24IfNGwqHsBjf9*6;=1jYX{HY;NIHFO}W^B ztDi}j#9K4X7>!47ag~|MS?;@IXhkBmRg71~;hCvtlT*7_~V^mDXZnmM8q&ni6k`vI*WhEjzHFcrhTjKof>L(#m&Qhna zP_*S^;7umn;h6>F+@ z0Rd*gIiH=4;=C*)?knUheiB$0%=7w+(}WDj`{|~#E@T#_^TC3X^exi#=g89372%y! z@RZnjZTuqc-&GVua<~XsG`Xn3K9-$3!R$%Xd{+`bUS-B!VjJieABXWO4HgNAXDCAN zjy>jgzXUK5Xdv`Vhx6D35*bk>Kjv;#^eK->6e-{5ztLwO&Vr3$U<%3pb(h(6Zz?)< zDI0`0dXFhTppPK6lBmLI@YLi9HcJ^!M20T8ufnk!usKr)pNj3%X|*gJ_(k`4?a|%J z;at1$M^_o=n>Xm|IoTi53IVEpyT1kRmm zB|vb@V67oOzEN)F&x(5&-3BubT5ZLX8Z$;|wZPDfz^XRI2rRdebUyr%q!zHbZao`Z ztFx3SpCaz)O;8Fx#Wbb9ul_Wva-ozl8$VcM4`Vrhqs+8B#_Z85uHl;~&%;W`t^6rU z-eZw{o$0aJ_dUDt6W4OB9S^lISz2{PYMDBMXuWiCp1ha~?&(dt;DWL-#ag$PXS2)M z_nU)(vw>rv^_hO9(O{PRygeK6YYSpN_E!(b4s8;toPyjqlN7$MDn^nWD8GoLAv{iE zE@h7GH*g1HCqrswIrgR*svq6!3wO;q6SvvHxwn6AVJLozBAUUY^VXN#bEa|!F zZ^)+28gDADt)WvgBDC}fqA0r6AFNG&66VYq9}dve*Fk#(Bj4p7S~zlVvc#HY?}0{j z?u{te9x@ z{-miWBxDz-)XS~=DYedoam9Q(b?@d;`;epsG;y?gL6| zphhk!X#n{$*BAcOa4el;_hHt88iij0JpbN7vNLLhh{Z{qJ%5O=iSf|Xx0_K(ogMs@ zWWg#ZWMtDXeXrAsuUm zl2%)TrLhHPtD9uFUM~-XVu&{F9t~1bsQg#8OB_XlWe8NjQud|pvMF*=CuZZeW{3+# z`wv0tV{H*`Tmr3n(Vf}{`QlLh!gw3zfE&S12^HVz1h6F?$aNO4In;{*zj0#++vj!L zE64+o=yo3R9(8BHZ54YXpe1`mk+&%v=Lg9+TZw2;Z^uDzzpVxnbfRV#d%k+ZhBNpb)tg z^^=&ZdBU>4a55lCHAyg#yzzOvgCwp_VVdUQ3Zd;%^{5*trQ5zOwg0!Je5By4lw7*R zi_umZa5viniO)^+yT3=zCS@s;2=P8zOrye@j;E9}_2Sdlp^H}Jb&Xjk4;y3-=wvb5 zQcVGRJmxII#>J{AM#$jCalZ7i7sP9ml41>b9eytZau9R@2zBf|U5qdK_K zq-LbPK7z}Sn07oo#GkpPFs~erqJaROp4{raH4Uh@VHq_QqC=JxQH=zmLXif^HHUb zwUfxQ?l-?%d+5zA?VAgERb$p6cxHa)TPuQKv-kUDb*ut&loIyKh`36Uwa=gV=%ltU znnT7(zQE|HHX@*?wai~APn%}zaqYuNp~uZ(Hj-U|^eYo+`4Nz?GOLG2F@!iFurlp# zr-Gj~MHw=x#)St8ac%v+JsJFBrr9|;9a+O;mTP@0KzV3Gelm>nj&F0(FkNMpW=LT5 z&z>I%Uuq`XxRFJNPJV++EpEwc43!OhlE&%*jEO!iD3{qSYbgJ^shh3Y=h2i-$~W*% zvX?P%DTY2VW(|OAHVj3SLT#=3G{NK$DK(C7tZRY2dIw(hMp{y{qPV@m=?EXzB)DBO z%d2)20k`6gPV3zGT~;c03atfH%52ga^7GFC-H%cS<)>>=Yz5&Z^GRRIvpL(!S31Ch zW}0iiROr>8zGJrz|5#jQMmgr&!{SK?XP~A3Tp6$tF;4hu|2b|&kKH>Q@eQEfy`zb2e9HIux5=A0$QrEO0UdLarCT05>4b;qCFEyHfuRHqD3 z8$1hGH{40eM`rG04a;XgD;PhS$oXUyv9d4O2`gEj;fq6OSsg7d3@+$}ouQUnefsOW z>^z*PULQ?2EU3>~jB2AqLD4$1S^dQ3zeaVcUyWV@NbXBc#o@t<^YG2sXqv_30P^hC zKez{&V>J9OZsMwE-s?!LrD?Odx58q1 zUf=K-S!px80XLtqWyEX1NY{c3Mow`TB0Jn860tUk11SOK7u288AF?ellv{ZM0|rgq zGwI)&Q|e9QV_32VtPA}L7uTf>>R+cx?$fQmb?h%B8n+DOZ49z1qW_s>ro;HXOlg0d zjVFi?xl@=)MyMA9l%qH*C9XeL+zB~c%X+`iw9rLw2!cuPTx-ky2oSOSfp?A2=_slKN*bU1Nts zpT02p5-C?)2&Yl2)`0n;Ddm=2L}~0wAUpXl77wa%iWbzn*0iO`fYg?mMozvvGCzcRlS7cWq>@FS4Q+&t`rD=ilabS!~-`oN8EZv${2E(x8{R2YhPa z@zl@TRMT=BC|E*fP3xXpKG-Wp{JJE@@6L;nAz&TDMG(>jynJM!+QPhA!)*1u-&pPW zR=Xb}M2-6b^E`J1ul0LACASAnF(9>3RDWTAGJ0i_;n|7m4Q5tKlP6Q|d!Uqh-<9pb zJ|^(oYf1YrqU0ovM~xQ3zvv@iwiM45XyNFjBeHf14{)96An>>F5Mpu6^5WXCiT14` z2kX}`vn-`+Glxhxii{W9zkMfA0wMHdxiC!~xMN)6O(T^gwSQE;hFxvTpwFZu=2%Hy z)gfGj!n})HIkXw-*PCt{&%<>*7{egO;jOmNYRH{r-UGMUCJ{j?tX}NSFHRnIvHpM! z!P*yr_Y=DYC!^1Lxj{dTy=Y=+7#|IHi86HWR|HS^c5s)N9aiWr*RVAOP{h`uiebMD zXSHGTfbpiU@1Enq{057D0KK?{b*uWg0df<8gu&KvS=9|VFIHzlUR~EY*BXc^Lh^16m@0RAb_&jO{?JVAf2-i5)m7g?L>;9--p#7!mGN#Q2xQc1*I zsTpe(VoIxpMKm|z{6*=2;-$uBC7XRVZMJ4wCF(ED?@m?8?U^rB>FD1uO$}4Z)cqDh zlQa+C&(Ab>Azw^4D^%1~cPujd6k)n8ka?S8w)wf_+XL;piUJA^5k{QR`XbnMD4hb- z>qz+(K-{6UA+sX*45|4b91w%>(}Nm;+v!*`cFTfc4Zcl)#WxGck>l}qV1@BT!2=Y@ zOpXoP)!o;u6EhAsb$?jjSg>U<<(IeXFlO=2y|1-kGmBPPeD^X}7MxFfa%wie;Gb|_ zhRLC=a~;5xY2HzDBC0CdvNfGW)T)f)i+HQv3V7y(&AVwG5;auP{T|=;EiN;3p!OH0 zy^%4 z?$Vaj)CtYD@UPM+BJ-?%{pwpuhLO8)ef0Rm?+@T!FU7L_h9*x^a$1y;7Q;ZTvTl6; zG`rL9tr6;UcnU+rWF$dt)~Gm4+QgQK{CoATk8^+U_k;5);4*#1?b_^BA!j9DWkHd< zOEWR3iwGjw2i9AG%n`E>sAn03zjXEA!B7R)u^e0iWa?zvaz8#S(0eSoFWS3a)b;yM z3wC#_XBkrwJ$P)OsNcLY$FqCH`tdFxY2I+E`k{K7mm0JMo28i`7wjlMU1VoSS@}dP zuHa?Mex1Z|_9GZueVINeca4lOQ;|sSA~1y|>ve03pyw3dD`Ms+?6{-qS4yxzFYAT- z7I%O|3`=kN+?sHK<=#g24bB4h^+N{|-KZ6;f#!boEr#h$NXsf0} z(BXVfgQ#0!T#Q`q`ASqfQ*WKd4`i!d%oFRMP=zTZ6->QN`ki0#=S^X+aHHqTX{W(( z;36VM{uOBEpyt__Pm5=*_~4AqxGCiL)5m^tHIc9-$+^c}=JGWkpkc1ZZh{O198bj4 z^CA#&ah8YVEf!>&Kiw)$O?M0T#LF;2Bad`Sb{$d~$&wcZ2)-+d@7KWSkn}TWcG-1k zzwn2U(I7?}jFqzmA8Z8>THB@9Mlsy$E5mrc{#idSD{ZvHS38K7MO%LIL~K~Y#d6eJ zwDyC1@t^ObH-k*Zl#};sf{j}h;S;x|-uHL!*e1PA5U~K(Mxujn0zi9~a?Nc%IZ2T* zIV|aFdrU%FKfS|d+)-{*(BxbsyhbtF^{`BE$~D&17Nd<4VC<=&3!{5r)S9$Glw|I# zxiRbupXv#al*r*sTH?-5a^=~ZzUl*<$z%wLvDkY*TtZ*;w!|m^em-qaNmu>R;;~1P zoxd743el7>5-eY2oE_h$W4^;U#Q!c)Z%XPcO1pTuMl_SGW$}){ulx*3NPA~vEAe+m z1yQf>=sh% ztz{2|c+*mRCaOPat9_Ad`7_dxcmL0qRb@i7hy1(cj27i|@`;+Sp{SeAGS{3~CMN z$-q%RWW*zWipjWNZ|*WMEI(-n6d7RFEWGDk5mni8Q{wlFhi;0M)7JV`6jB%(#Do4P zf+{eA{gTfx9rT0Y0&&2s0jcIf#(@ccVWzE=1FKaSG;3N5h z)ftnqLb`%Y@mZtRX;sSM^>oe;a&R{AFuAp&b*uUWu59n{09_m*_e=_D6GHc~l1UP* zgk~y=Ni$*z*~{=zQhE#fP%`k|5q%a?Sg`N2kQu@hES_U|ho-*>u5Ep4p*uENG_S|Js!Bk`gpZ^2gIh(tD z>=+mRQ=j_F&+mwhQ;U>XuPyZM`Q);EQh4C`=FNcxj>&A(7OaP1 z`R23Z8L}}rBIHhd>Z!%OZ(;lB=`2>^(l*-n>e;lNjegkMFIWwAt9ER98{zjng7CAn zGh$?crTp#0W0-#PZ#@inRg;fzZqiET&V0`~A>SH1w#b3cW^JhR6*IMd`xE|v`u>35 zP4J3PxuRB$J8{RxeV%5lQ|Pu+*sFdsW1T-9V+tCTuS;@~dc4z97jPWuC?Txs!M`?7-k8A6Hc5~(4r2-jw=kF{)H3=YeCuC|$tMtqTnh$te$}M#!N;hAysMaLOmv zDNLeW-9DQKfY%2T!b2*Ve|y0S&xr9)9a0EQycb8z?5lk=dhcZz=^EiSi84A6-s^W; zYZ^31@>@};-FKB#3rqCNE)9rS;E~6mO)YqUkFIi^*Q z7Q)Ty8s~%&MTC3uPpvVJ&1hTX_H_RYc!`+AJsA0H?1bklJ0^+$W$uo=G-r4BQq$PS zd4cfYVilX09_aI(>{Q>b6x7~5;U`1B&LXO`qzTjpnJCNQh8X%ogRFVtbJwBR20m??plS8Q|m-QR0rWjfJ0;zZ{gJBMYC`Lj0*HT6Xn zRBRmP6YR$W2k|p$h}qWawn}C-db~{#llBSK?v-!+kj_~;yrY8{R+xBMoy< z84<|qpx6tbUBY70Lq|^aEU4nv8e2?-SNZtWN6=^=ufPv*({x#?KAhPcpXisF^U7qq z{G|D&Rhor8T(Pt|XM>)OBj$OZqK5bzeWtZ%KpYdJzILTwpJZDpL7;KM_zeuc`>1s? z+BCtd%6O84cMPptEwfgYj@weYOWha8SNdwoH`rbzGQiR6E=>O$3Z^)72x{iIIF@sEije-A_d#N7AUwsB8J4ui9CGk@ks)Kmn3u%K$1gKB8YnweB(sL4_J?XHp$>izkD23HfcojG?e}OxjZP>a z>|B*!gWpkpy*EO7V?~bTcetA*=0T`;$jEK1mvZl@{{ym@OOwwik6a#H0xb6G+-ztI z{ZSFnHa7MpcB)Z=Xj}2lJdufX+r}?BA{71<5GjUm3oP*769J{^JMg_IRROxMk7Zlv znN~In7UXX|j5sXwWh~t=Z`m&Y0P<#jI)DxreR}RjpTD5@6QiO{GBjKF0MlhTG@US+ z8}a?A_ZPb`M!=2=yTx(jhpCxj33Ckbj5M9_AYI2t=2XmE)87Rj$P38eh9N98bM#-g zd05=?ELuW+mf2n`@xNCXFzgsReR)j$LyNuU9%0-5(-%5&C7VlFHe4jkO@R z3LmgF`9U+UK5Hg)Qm&@b7;qOBqfy(Yvtyux3W~?Lep|;J@L6byJ+XCol5FYFEJ!iV zyq#PWG}S90Gz5^ZksV4$7C)eH2SC=5(UFbw`41ro25{yglO`6 z2K_VPfsD)o%lOHi20k^?bq4N}fSU%TG*B;2cpduvvURb#}zshZ(= zc*bHNW_&dB)lp!1E>e?6nmv)_>RiPqI3(b_7SQm7icu!2l{@W+KdEwrzv{W^xdSUW@R`Xl0$&If>qy$c%aj1vwij;Rf;N$(3249QwOh3zV z1gKCtB*E8mxoU=+CK^A;bsQKTR_1>j&S%CFRj)&ITZce;G&zyC=6wzgr%$1bW1)LC zjlUNPB+o==S!6A961JVN=g8u3iM|_1#pa(~@*?bj-(S{k^2L4+hnDNO@0@VDEI^e2 z1AEn*)D(S%pNsk%?h&Y*&qt4iYp~huq<=W7sS_!H2_X2>g`Xy*C;$HA@rlVLUr!-T z{7AMgXovVczk*sNtLjo1CZet_wwHlb_LKaStun#>m;1(t@%22)p?(+oOcXoETSy%Y z=+3To@cs|^i_Fb@w%>Vgc`(-WLCvoRvTrz~4?GMW+pm&}B;5+k9q~A5YcopoGJoi$ z)V{xUKi&iGxVvShc1j-=QGG%bBoUd_czh|ELmQ#a-;f0EW&H|bY$ zVT^HgiuouKD(4kbt*zj2qwX82i-Q zSJM(V>tNY(9y&a1_Pt?`{O*S?0-9D^#dFV^qLrX#cmvazXT&jL8~)$}(DO$-$I~4n zXG)fo@qY?K@7pq5nDx3XR1KXepZG&!x-ztSw?9i=G^>QB*ambSppC==@(u?F>)`Bw zZ+OmO-o@rJanaD)h{P`gW#3Keex8BGR-2AsGIsA3YPAnGwW)c2AH_*hQ!n)RQQ|hZ zJWuXB%=EVP)RjI|t`vD!GP_VmF82b6o$C7hkX+q7MG_ZV=HXm7l6SE7hP~&4A-(r4 zds73K#f)zaCrh#;|7(!XZT6YkO0s=M?i!E&PUDEY0ISpO+z6@~MnY?m;ZPw=Go6)L z$a3mT4(*3Bu4+hLk|4vyVT9=)OOv*zz89->B0cLG@@Wy83;OIK3nli_OdkBT0cg%Q z5yl5g8MTTPlx9Of)dZxjG0xbRr@K$AMt)O+a?aUn7aIaJ6w1TuIR}?Sk(89tN#q*H znOOl|tQ#-qXYyk8XJDSUSh|AHJWwwQFNvQuew4FFC#@~$mc(-d{_zm*@0cQZZhI*N zJ1(NGFNR3>;x=uljjf=T_<2*y4+`$uFD`2qqJlByI<>_h1!nanwIqf7;tl%EGj1#U z3~R!-Ulh^{Na1qBvD6?t5`zP7C-*){3%|8IiyC2Jdro-mJp5y(RW>jBvo(bTrgtiT zq)#p3CR97O!t|hIR;NDM0Ol?qKUo>!>7}q#XgvGIkoK!tNsMAvvCBb)WnfA7fP{P? zK7R8}5x8slsKzttk)x`q6;A-Nl+Zd^2w`u~&9)!U{!xHXpJ9Y-LIh=LdZL0(3|?Uq zIP)bG>9x6ys^z2u<>7wHRPOraO~w1$XtweuchUAA?4W2yv}3sEF5wct`T(1rv=uz){e1&?%Hdm?qJj2o025?tndi{s1Y)l8-{v(n_% zb$#~><9nHe!;c?WBeeezS_cUkH5BOT6At%7BA_Q;S6`i;3#be{#1ZzNIAJoK4$DlI z2g31J^hr2&5C{*KG=-3Zs&~R-{NE*hesC?y^=o>XY;Ep7jTaLz$Cml9e1!_$_@!dL z$$vgTW!P$N&YxJcxT{YF5vyS5&BbVy zfw*nLkLfS)Rv7%gRJyx5koBdnK7IA}1$}CDeQr|jAYhx)n@V~`II&YJ(%$e- zh2UuL&?P{4nu1u>@Z=AirhJU9MC$9B%*7AystpZO*Y8t_z3=Eatlo7!(%sy;Nw|mq zd~m~W4lC`=lHi0^m;Ggs`dS91HrcMQRF=%RT8XHi^Y?=e@XiIO*kYHb5H;T;CRCDx zl|!-m_xhOOVFnq4w$4yN+{b3NIn&v;n1(Z`s4&zq1HeB{lqtgkC6rj()H%j561h5+Yt`Nn^-mQ3&OxE zd~-g(abD1dJX5b~CqF19Fc>dMX?}BWfl8G=iV~A>8l;N0VKeU| zfe13)T6;Q}0DsxXTP#gCb*pq*UXAy+>elwsIkZ)7!>;C)1@>D9!>+=GHgq4TN`)#> z!?0hbJgtPNl3OimRAjL~H3HkoRG*@sB*@yV5XFKs>|Sf|Osy3B;F15Tk`8JB;FsBBcI=53}Ngif;}RlUNy_L#4g*u=>g7gEn+ey6BVcZ=UzWJUFkhF4&+*x ze`CNu`^%`dzU&e(7R>(p=GeNPmw&%B;L~@d*vR+ss5@c<;rj1H>#)e;O8}|n%kK=& zK4F|>cE^rQRwjRj@>J601LJw(mJ}&nTGcS6f2T-x~J8?{{;H zDu2`e7J-YLneum|IKKLgm@8{UUr~JSr8yvK#Me0KFlos@H}%WGJ3$Y8h2K?t&F9&E zPJL`v`&B;iO@J;+tW4# zRr#CtC@`q)KOhUyn!EJttG#w!tAVI@Z{;dSmow4XK0K*l1mc5{PYgRP6y9kWUmU3M z$j2%<(#jh_DkndmQo*Skx9!zaujW~{RHIzA2hK^1Af8dL;9c<@SJVB-*ZN5>0q$gO zne8vtCpxJLolTOjLe#C3N}Q$Vp3$Eyy`82@K=;5gZl{+Au49{gsI5GVZgN?ouaB3wk9Kbr5KA%Xq9VKX;{Uy1icJ4_!QgzOIN9h zBB2h=i-n5qm!_(0YtBIzdm*B&{|`mi8O~PU#$&f?bVTh@JVulnv8h#CjMyF(PQKs#z3ORB7p(_uKi9>wL&{&VBCR{72tc{B(XI za=vOS1+NAdYvtJpImyoRE}hywSD@W zsbIGJZ3Ubic{efJ;JEfAY$M%G%&|`ktB4V=rMFS9T^x{c<0$0%vMv}p^Y}%13t!2j zp#*z}ymYD=JiOND^;}upv&q0aB~87tzIg|XH8C~q?h@nWdFtqGmv+3++U$R^Rfy}` zY2j&n)q=vqbD7Vl-UrP~ICXvu;b0kI07ur%Xb;{l3eTX6p)3|b|5N0*s!{}*QRp7P~CnRB*ho`U>N|_*9d_^zD9YqULu3;Mxy`| zod=49TD!ICP%)x(n*>t&5#=Fu&2avO{~FaKl5i_4@I?yO4!P-5q^F^0^MZmT;CxD( z^&j9#_OO?b*v6RhGO9^1^~P9eo_t+k&0Kw7inyP6VYwG;RszX3?#iN2mdHcdmc?$q zR7=K-qJ}G*xh(RMbXzuiZ7Ut~S1)!{L~Z#6#=gSV-dE}bjhm$-Y$uS_c_S~gZVgvl zx&I^Q9pbyo30ps%wcyRmBCOo~9t$(hOEwdh^c#3my-<%ZPA6QP*&HSJ*_)AZ<>XZM9kUS49iq-jZq{{ zj^~d)9$^kO;khMNL1ChY3<7SN<{**pJ^~vrQe%wNLrj`}+lUG*OmqoQoMAWiYS)m3 z6|~X+*U4ox8PE6n2y(09WDFfpS@=Z)q?;rCQ- z=~C|du~%bTVI}&iw95y4D7oJ}_#otu)@oXA^Gl)vc?BLK?`@N=js#1^*{S1<Tsc8EjMShBe+{tdtJLM;;X)1Hq!B401Ev#{mD(oyF1U6aJnc^)$*eEt zZ_On}EKGZbz0eO6khX@il&uH?5(W((#lCW!`^K5}x zzY=e_SfT3~JvoOq6fXD;XMtDGq=sTD=vjyN^_0}Dh-XlaMeV=+iZa{CIi(4yG$g$5 zodv>cO8b%;TB5p5h}oAtItV<+JOSt6l{TW}iA;IwirmfRA{kG$(Ql+NQ(m}Z=3+rG zy@Z*(K|}pJz-tE7r#NBXc&bPBF{1beMdcWSEQQa*xnsA9Qo1+q4^}>`7proUh@o*N zD0sJ-jc!4t9G_(bwDHE`|3G*l03lcwyaGBw|H9(K>H&^M=QMg+OrHA_QZZ?Ty>O2G z431tXZj7-Le5T@S{p~%~Lp`SJ^a4?XvC%c#WGok^TA_q@Db==M(rt&p17zeG2XRFL{8IAh8 zL0|>_TOirPz>j~P*9bBU1o$>v6fAZssXd4npH^gV-g14gqU`6-wU%RAu>^@ivb@`5 z!b0MzWa>SD$WK{Dr%(N?{X*gX5&1dUk!O~S9$*6C{OAhC4Vm%F*eqo9qAJU-b3pSiX8zQH?2<2AVqrN4Xk(KE)d{ceT%0A;> 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 literal 0 HcmV?d00001 diff --git a/tcpip_kanal/klient/spustit_klient.bat b/tcpip_kanal/klient/spustit_klient.bat index 7f2562b..293766d 100644 --- a/tcpip_kanal/klient/spustit_klient.bat +++ b/tcpip_kanal/klient/spustit_klient.bat @@ -12,4 +12,4 @@ :: -s cesta-ku-suboru sluzi na nacitanie cesty k suboru, ktory chceme odoslat ::Priklady spustenia: -klient -ip 127.0.0.1 -port 8080 -n rsa -s document.pdf +klient -ip-adr 127.0.0.1 -port 8080 -cert rsa -cert-aut rsa -subor obr.jpg diff --git a/tcpip_kanal/server/obr.jpg b/tcpip_kanal/server/obr.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77d95676bab95b91bbc3c95d2fc663635cbda5a0 GIT binary patch literal 51156 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%0A;> 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 literal 0 HcmV?d00001 diff --git a/tcpip_kanal/server/server.c b/tcpip_kanal/server/server.c index c3bef83..dcf4ccf 100644 --- a/tcpip_kanal/server/server.c +++ b/tcpip_kanal/server/server.c @@ -22,9 +22,12 @@ #define ECC_CERTIFIKAT "../../certifikaty/server/server_ecc.pem" #define VYGENEROVANY_KLUC "../../certifikaty/server/vygenerovany_kluc.key" #define VYGENEROVANY_CERTIFIKAT "../../certifikaty/server/vygenerovany_certifikat.pem" +#define VYGENEROVANA_ZIADOST "../../certifikaty/server/vygenerovana_ziadost.pem" int main(int argc, char **argv) { + int autentizacia = 0; + int uspech; int autentizacia_klienta = 0; int generovanie_certifikatu = 0; int nacitanie_zo_suboru = 0; @@ -52,6 +55,7 @@ int main(int argc, char **argv) { //skontroluje ci nebol zadany prepinac "-g" pre moznost generovanie certifikatu, //ak ano pozrie aky typ certifikatu (v CLI argument hned za nim) bol zvoleny + printf("---------------\n| Certifikaty |\n---------------\n"); for(int i = 0; i < argc; i++) { if( (!strcmp(argv[i], "-port")) ) @@ -67,7 +71,32 @@ int main(int argc, char **argv) cislo_portu = atoi(argv[i+1]); } } - else if( (!strcmp(argv[i], "-n")) ) + else if( (!strcmp(argv[i], "-cert-aut")) ) + { + if((argv[i+1] == NULL) || (i == argc-1)) + { + printf("Nezadali ste typ certifikatu autority ktory chcete nacitat\n"); + return -1; + } + else if(!strcmp(argv[i+1], "rsa")) + { + wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + autentizacia = 1; + } + else if(!strcmp(argv[i+1], "ecc")) + { + wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + autentizacia = 1; + } + else + { + printf("Zadali ste nespravny typ certifikatu\n"); + return -1; + } + } + else if( (!strcmp(argv[i], "-cert")) ) { nacitanie_zo_suboru = 1; if(generovanie_certifikatu) @@ -82,18 +111,11 @@ int main(int argc, char **argv) } else if(!strcmp(argv[i+1], "rsa")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); if(nacitat_certifikaty(ctx, RSA_CERTIFIKAT, RSA_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); - } else if(!strcmp(argv[i+1], "ecc")) { - printf("jo\n"); - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); if(nacitat_certifikaty(ctx, ECC_CERTIFIKAT, ECC_KLUC) == -1) return -1; - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); - } else { @@ -101,7 +123,7 @@ int main(int argc, char **argv) return -1; } } - else if( (!strcmp(argv[i], "-g")) ) + else if( (!strcmp(argv[i], "-cert-gen")) ) { generovanie_certifikatu = 1; if(nacitanie_zo_suboru) @@ -116,15 +138,13 @@ int main(int argc, char **argv) } else if(!strcmp(argv[i+1], "rsa")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_rsa.pem", NULL); - if(generovat_rsa_certifikat(RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; + if(generovat_rsa_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, RSA_VELKOST, RSA_EXPONENT, CTC_SHA256wRSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; } else if(!strcmp(argv[i+1], "ecc")) { - wolfSSL_CTX_load_verify_locations(ctx, "../../certifikaty/autorita/autorita_ecc.pem", NULL); - if(generovat_ecc_certifikat(ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; + if(generovat_ecc_certifikat(VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC, ECC_VELKOST, ECC_SECP256R1, CTC_SHAwECDSA, "SR", "Kosice", "local.dev", "server@server.sk") == -1) return -1; if(nacitat_certifikaty(ctx, VYGENEROVANY_CERTIFIKAT, VYGENEROVANY_KLUC) == -1) return -1; } else @@ -135,6 +155,12 @@ int main(int argc, char **argv) } } + //vypis upozornenia o autentizacii + if(!autentizacia) + { + printf("Nebol nacitany certifikat autority, takze nebude vykonana autentizacia druhej strany\n"); + } + if(!port) { fprintf(stderr, "Nebol urceny port\n"); @@ -151,6 +177,8 @@ int main(int argc, char **argv) //nastav_sifry(ctx, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); //pokus vytvorenie TCP/IP prenosoveho kanala + printf("----------------\n| TCP/IP kanal |\n----------------\n"); + printf("Pokus o inicializaciu TCP/IP prenosoveho kanala\n"); cislo_soketu = cakat_na_komunikaciu(cislo_portu); struct sockaddr_in adresa; @@ -158,15 +186,18 @@ int main(int argc, char **argv) int velkost = sizeof(adresa); int cislo_soketu_klienta = accept(cislo_soketu, (struct sockaddr*)&adresa, &velkost); printf("Spojenie [%s:%d]\n", inet_ntoa(adresa.sin_addr), ntohs(adresa.sin_port)); + printf("TCP/IP kanal bol uspesne vytvoreny\n"); //pokus o vytvorenie novej wolfSSL relacie ssl = wolfSSL_new(ctx); //priradenie file descriptora soketu ako I/O pre TLS spojenie wolfSSL_set_fd(ssl, cislo_soketu_klienta); + wolfSSL_set_using_nonblock(ssl, 1); //cakanie na inicializaciu TLS handshaku klientom - int uspech; + printf("-----------------\n| TLS Handshake |\n-----------------\n"); + printf("Inicializacia TLS spojenia\n"); if(wolfSSL_accept(ssl) != SSL_SUCCESS) { char* popis_chyby = calloc(100, sizeof(char)); @@ -177,7 +208,9 @@ int main(int argc, char **argv) free(popis_chyby); return -1; } + printf("Podarilo sa vytvorit TLS spojenie\n"); zobraz_sifru(ssl); + printf("----------------------------\n| Informacie o certifikate |\n----------------------------\n"); zobraz_certifikat(ssl); //nastavenie funkcie pre vypocet kontrolneho suctu @@ -185,15 +218,14 @@ int main(int argc, char **argv) nastav_funkciu(&nastavenia, "crc", (hashovacia_funkcia)NULL, funkcia_CRC32); //vypocet casu prenosu suboru + printf("-------------------\n| Prijatie suboru |\n-------------------\n"); clock_t cas; cas = clock(); - if(prijat_subor(ssl, ctx, &nastavenia) == -1) - { - return -1; - } + if(prijat_subor(ssl, ctx, &nastavenia, 16384) == -1) return -1; cas = clock() - cas; printf("Cas prenosu suboru: %f sekund\n", (double)cas/CLOCKS_PER_SEC); - + + printf("----------------------\n| Ukoncenie spojenia |\n----------------------\n"); ukoncit_spojenie(ssl, ctx); } ukoncit_soket(cislo_soketu); diff --git a/tcpip_kanal/server/spustit_server.bat b/tcpip_kanal/server/spustit_server.bat index b144f38..94a2d44 100644 --- a/tcpip_kanal/server/spustit_server.bat +++ b/tcpip_kanal/server/spustit_server.bat @@ -11,5 +11,5 @@ :: -n rsa|ecc sluzi na nacitanie uz vygenerovanych certifikatov z adresara /certifikaty ::Priklady spustenia: -server -port 8080 -n rsa +server -port 8080 -cert rsa -cert-aut rsa ::server -port 8080 -g ecc \ No newline at end of file