TASSL 服务端 客户端测试代码
openssl s_client -connect kjt.hebei.gov.cn:443
c:\tassl\bin\openssl.exe s_server -key SS.key -cert SS.pem -www -accept 443
TASSL windows上代码 服务端,需要引入applink.c
/* * ++ * FACILITY: * * Simplest SM2 TLSv1.1 Server * * ABSTRACT: * * This is an example of a SSL server with minimum functionality. * The socket APIs are used to handle TCP/IP operations. This SSL * server loads its own certificate and key, but it does not verify * the certificate of the SSL client. * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <iostream> #if WIN32 #pragma comment(lib,"ws2_32.lib") #include <memory.h> #include <errno.h> #include <WS2tcpip.h> #include <winsock2.h> #include <windows.h> #include <string.h> #else #include <strings.h> #include <netdb.h> #include <unistd.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/select.h> #include <netinet/in.h> #include <arpa/inet.h> #endif #include <sys/types.h> #include "openssl/crypto.h" #include "openssl/ssl.h" #include "openssl/err.h" #include "openssl/evp.h" #define MAX_BUF_LEN 4096 #define SM2_SERVER_CERT "./cert/SS.pem" #define SM2_SERVER_KEY "./cert/SS.pem" #define SM2_SERVER_ENC_CERT "./cert/SE.pem" #define SM2_SERVER_ENC_KEY "./cert/SE.pem" #define SM2_SERVER_CA_CERT "./cert/CA.pem" #define SM2_SERVER_CA_PATH "." #define SSL_ERROR_WANT_HSM_RESULT 10 #define ON 1 #define OFF 0 #define RETURN_NULL(x) if ((x)==NULL) exit(1) #define RETURN_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } #define RETURN_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(1); } int opt = 1; #define strcasecmp strcmp #if WIN32 extern "C" { #include <openssl/applink.c> } #endif void ShowCerts(SSL* ssl) { X509* cert; char* line; cert = SSL_get_peer_certificate(ssl); if (cert != NULL) { printf("数字证书信息:\n"); line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); printf("证书: %s\n", line); free(line); line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); printf("颁发者: %s\n", line); free(line); X509_free(cert); } else printf("无证书信息!\n"); } int verify_callback(int ok, X509_STORE_CTX* ctx) { if (!ok) { ok = 1; } return (ok); } int main(int argc, char** argv) { int err; int verify_client = OFF; /* To verify a client certificate, set ON */ int listen_sock; int sock; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; size_t client_len; char* str; char buf[MAX_BUF_LEN]; char tmpbuf[64] = { 0 }; SSL_CTX* ctx = NULL; SSL* ssl = NULL; const SSL_METHOD* meth; short int s_port = 443; int hsm_tag = 0; int aio_tag = 0; /*----------------------------------------------------------------*/ if (argc > 1) { for (err = 1; err < argc; err++) { if (!strcasecmp(argv[err], "-H")) hsm_tag = 1; else if (!strcasecmp(argv[err], "-A")) aio_tag = 1; else if (!strcasecmp(argv[err], "-P")) { if (argc >= (err + 2)) s_port = atoi(argv[++err]); else s_port = 4433; if (s_port <= 0) s_port = 4433; } } } else { printf("Usage: %s [-h [-a]] [-p port]\n\t-h: Use HSM\n\t-a: Use HSM With Asynchronism Mode\n\t-p port: service port, default 4433\n", argv[0]); } printf("Service With HSM=%s AIO=%s Port=%d\n", (hsm_tag ? "YES" : "NO"), (aio_tag ? "YES" : "NO"), s_port); /* Load encryption & hashing algorithms for the SSL program */ SSL_library_init(); /* Load the error strings for SSL & CRYPTO APIs */ SSL_load_error_strings(); /* Create a SSL_METHOD structure (choose a SSL/TLS protocol version) */ meth = SSLv23_server_method(); //SSL_set_sm2_group_id_custom(29); /*SSL_set_sm2_group_id_custom(59);*/ /* Create a SSL_CTX structure */ ctx = SSL_CTX_new(meth); if (!ctx) { ERR_print_errors_fp(stderr); exit(1); } /* Load the server certificate into the SSL_CTX structure */ if (SSL_CTX_use_certificate_file(ctx, SM2_SERVER_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* Load the private-key corresponding to the server certificate */ if (SSL_CTX_use_PrivateKey_file(ctx, SM2_SERVER_KEY, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* Check if the server certificate and private-key matches */ if (!SSL_CTX_check_private_key(ctx)) { fprintf(stderr, "Private key does not match the certificate public key\n"); exit(1); } /* Load the server encrypt certificate into the SSL_CTX structure */ if (SSL_CTX_use_enc_certificate_file(ctx, SM2_SERVER_ENC_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* Load the private-key corresponding to the server encrypt certificate */ if (SSL_CTX_use_enc_PrivateKey_file(ctx, SM2_SERVER_ENC_KEY, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(1); } /* Check if the server encrypt certificate and private-key matches */ if (!SSL_CTX_check_enc_private_key(ctx)) { fprintf(stderr, "Private key does not match the certificate public key\n"); exit(1); } if (verify_client == ON) { /* Load the RSA CA certificate into the SSL_CTX structure */ if (!SSL_CTX_load_verify_locations(ctx, SM2_SERVER_CA_CERT, NULL)) { ERR_print_errors_fp(stderr); exit(1); } /* Set to require peer (client) certificate verification */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); //SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); //SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); /* Set the verification depth to 1 */ SSL_CTX_set_verify_depth(ctx, 1); } /* ----------------------------------------------- */ #if WIN32 WORD wVersionRequested; WSADATA wsaData; int iLen; wVersionRequested = MAKEWORD(2, 2);//create 16bit data err = WSAStartup(wVersionRequested, &wsaData); //load win socket if (err != 0) { std::cout << "Load WinSock Failed!"; return -1; } #endif /* Set up a TCP socket */ listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt)); RETURN_ERR(listen_sock, "socket"); memset(&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons(s_port); /* Server Port number */ err = bind(listen_sock, (struct sockaddr*) & sa_serv, sizeof(sa_serv)); RETURN_ERR(err, "bind"); /* Wait for an incoming TCP connection. */ err = listen(listen_sock, 5); RETURN_ERR(err, "listen"); client_len = sizeof(sa_cli); printf("Service With HSM=%s AIO=%s Port=%d\n", (hsm_tag ? "YES" : "NO"), (aio_tag ? "YES" : "NO"), s_port); /* Socket for a TCP/IP connection is created */ sock = accept(listen_sock, (struct sockaddr*) & sa_cli, (socklen_t*)&client_len); RETURN_ERR(sock, "accept"); closesocket(listen_sock);//close(listen_sock); inet_ntop(AF_INET, &sa_cli.sin_addr.s_addr, tmpbuf, sizeof(tmpbuf)); printf("Connection from %s, port %d\n", tmpbuf, ntohs(sa_cli.sin_port)); /* ----------------------------------------------- */ /* TCP connection is ready. */ /* A SSL structure is created */ ssl = SSL_new(ctx); RETURN_NULL(ssl); /* Assign the socket into the SSL structure (SSL and socket without BIO) */ SSL_set_fd(ssl, sock); /* Perform SSL Handshake on the SSL server */ /*err = SSL_accept(ssl);*/ SSL_set_accept_state(ssl); while (1) { err = SSL_do_handshake(ssl); if (err <= 0) { if (SSL_get_error(ssl, err) == SSL_ERROR_WANT_HSM_RESULT) continue; else { ERR_print_errors_fp(stderr); goto err; } } else break; } RETURN_SSL(err); /* Informational output (optional) */ printf("SSL connection using %s\n", SSL_get_cipher(ssl)); ShowCerts(ssl); /*------- DATA EXCHANGE - Receive message and send reply. -------*/ /* Receive data from the SSL client */ while (1) { memset(buf, 0x00, sizeof(buf)); err = SSL_read(ssl, buf, sizeof(buf) - 1); if (err <= 0) { printf("ssl_read fail!\n"); break; } break; } RETURN_SSL(err); buf[err] = '\0'; printf("Received %d chars:'%s'\n", err, buf); /* Send data to the SSL client */ err = SSL_write(ssl, "-----This message is from the SSL server-----", strlen("-----This message is from the SSL server-----")); RETURN_SSL(err); /*--------------- SSL closure ---------------*/ /* Shutdown this side (server) of the connection. */ err = SSL_shutdown(ssl); RETURN_SSL(err); /* Terminate communication on a socket */ closesocket(sock); err: /* Free the SSL structure */ if (ssl) SSL_free(ssl); /* Free the SSL_CTX structure */ if (ctx) SSL_CTX_free(ctx); return 0; }
客户端
// #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #if 1 #pragma comment(lib,"ws2_32.lib") #include <memory.h> #include <errno.h> #include <WS2tcpip.h> #include <winsock2.h> #include <windows.h> #else #include <netdb.h> #include <unistd.h> #include <strings.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/select.h> #include <netinet/in.h> #include <arpa/inet.h> #endif // 1 #include "openssl/bio.h" #include "openssl/err.h" #include "openssl/rand.h" #include "openssl/ssl.h" #include "openssl/x509v3.h" #define MAX_BUF_LEN 4096 #define CLIENT_S_CERT "./cert/CS.pem" #define CLIENT_E_CERT "./cert/CE.pem" #define CLIENT_CA_CERT "./cert/CA.pem" #define SSL_ERROR_WANT_HSM_RESULT 10 void Init_OpenSSL() { if (!SSL_library_init()) exit(0); SSL_load_error_strings(); } /* int seed_prng(int bytes) { if (!RAND_load_file("/dev/random", bytes)) return 0; return 1; } */ int main_cli(int argc, char** argv) { setvbuf(stdout, NULL, _IONBF, 0); BIO* conn = NULL; SSL* ssl = NULL; SSL_CTX* ctx = NULL; int usecert = 1; int retval; int aio_tag = 0; char sendbuf[MAX_BUF_LEN]; int i = 0; const SSL_METHOD* meth; /*Detect arguments*/ if (argc < 2) { printf("Usage : %s host:port [use_cert] [aio]\n", argv[0]); exit(0); } if (argc >= 3) usecert = atoi(argv[2]); if (argc >= 4) aio_tag = atoi(argv[3]); Init_OpenSSL(); meth = CNTLS_client_method(); ctx = SSL_CTX_new(meth); if (ctx == NULL) { printf("Error of Create SSL CTX!\n"); goto err; } if (usecert) { if (SSL_CTX_use_certificate_file(ctx, CLIENT_S_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); goto err; } if (SSL_CTX_use_PrivateKey_file(ctx, CLIENT_S_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); goto err; } if (SSL_CTX_use_enc_certificate_file(ctx, CLIENT_E_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); goto err; } if (SSL_CTX_use_enc_PrivateKey_file(ctx, CLIENT_E_CERT, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); goto err; } if (!SSL_CTX_check_private_key(ctx)) { printf("Private key does not match the certificate public key/n"); goto err; } if (!SSL_CTX_check_enc_private_key(ctx)) { printf("Private key does not match the certificate public key/n"); goto err; } if (!SSL_CTX_load_verify_locations(ctx, CLIENT_CA_CERT, NULL)) { ERR_print_errors_fp(stderr); exit(1); } } /*Now Connect host:port*/ conn = BIO_new_connect(argv[1]); if (!conn) { printf("Error Of Create Connection BIO\n"); goto err; } if (BIO_do_connect(conn) <= 0) { printf("Error Of Connect to %s\n", argv[1]); goto err; } if (!SSL_CTX_set_cipher_list(ctx, "ECDHE-SM4-SM3")) { printf("set cipher list fail!\n"); exit(0); } ssl = SSL_new(ctx); if (ssl == NULL) { printf("SSL New Error\n"); goto err; } SSL_set_bio(ssl, conn, conn); /*if (SSL_connect(ssl) <= 0) { printf("Error Of SSL connect server\n"); goto err; }*/ SSL_set_connect_state(ssl); //SSL_set_sm2_group_id_custom(29); while (1) { retval = SSL_do_handshake(ssl); if (retval > 0) break; else { if (SSL_get_error(ssl, retval) == SSL_ERROR_WANT_HSM_RESULT) continue; else { printf("Error Of SSL do handshake\n"); goto err; } } } for (i = 0; i < MAX_BUF_LEN; i++) { sprintf(sendbuf + i, "%d", i % 10); } while (1) { if (SSL_write(ssl, "hello i am from client ", strlen("hello i am from client ")) <= 0) { printf("ssl_write fail!\n"); break; } break; } { char rbuf[2048]; memset(rbuf, 0x0, sizeof(rbuf)); if (SSL_read(ssl, rbuf, 2048) > 0) printf("SSL recv: %s.\n", rbuf); else printf("None recv buf.\n"); SSL_shutdown(ssl); } err: if (ssl) SSL_free(ssl); if (ctx) SSL_CTX_free(ctx); return 0; }