]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_tls.c
Merge pull request #455 from arx11/magma_ctracpkm_omac
[openssl-gost/engine.git] / test_tls.c
1 /*
2  * Simple Client/Server connection test
3  *
4  * Based on OpenSSL example code.
5  * Copyright (C) 2019 vt@altlinux.org. All Rights Reserved.
6  *
7  * Contents licensed under the terms of the OpenSSL license
8  * See https://www.openssl.org/source/license.html for details
9  */
10
11 #ifdef _MSC_VER
12 # pragma warning(push, 3)
13 # include <openssl/applink.c>
14 # pragma warning(pop)
15 #endif
16 #include "e_gost_err.h"
17 #include "gost_lcl.h"
18 #include <openssl/evp.h>
19 #include <openssl/ssl.h>
20 #include <openssl/bio.h>
21 #include <openssl/rand.h>
22 #include <openssl/err.h>
23 #include <openssl/asn1.h>
24 #include <openssl/obj_mac.h>
25 #include <openssl/x509v3.h>
26 #include <openssl/ec.h>
27 #include <openssl/bn.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <sys/types.h>
31
32 #ifdef __GNUC__
33 /* For X509_NAME_add_entry_by_txt */
34 # pragma GCC diagnostic ignored "-Wpointer-sign"
35 #endif
36
37 #define T(e) \
38     if (!(e)) { \
39         ERR_print_errors_fp(stderr); \
40         OpenSSLDie(__FILE__, __LINE__, #e); \
41     }
42 #define TE(e) \
43     if (!(e)) { \
44         ERR_print_errors_fp(stderr); \
45         fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \
46         return -1; \
47     }
48
49 #define cRED    "\033[1;31m"
50 #define cDRED   "\033[0;31m"
51 #define cGREEN  "\033[1;32m"
52 #define cDGREEN "\033[0;32m"
53 #define cBLUE   "\033[1;34m"
54 #define cDBLUE  "\033[0;34m"
55 #define cNORM   "\033[m"
56 #define TEST_ASSERT(e) {if ((test = (e))) \
57                  printf(cRED "  Test FAILED\n" cNORM); \
58              else \
59                  printf(cGREEN "  Test passed\n" cNORM);}
60
61 struct certkey {
62     EVP_PKEY *pkey;
63     X509 *cert;
64 };
65
66 static int verbose;
67 static const char *cipher_list;
68
69 static void err(int eval, const char *fmt, ...)
70 {
71     va_list ap;
72
73     va_start(ap, fmt);
74     vprintf(fmt, ap);
75     va_end(ap);
76     printf(": %s\n", strerror(errno));
77     exit(eval);
78 }
79
80 /* Generate simple cert+key pair. Based on req.c */
81 static void certgen(const char *algname, const char *paramset, struct certkey *ck)
82 {
83     /* Keygen. */
84     EVP_PKEY *tkey;
85     T(tkey = EVP_PKEY_new());
86     T(EVP_PKEY_set_type_str(tkey, algname, strlen(algname)));
87     EVP_PKEY_CTX *ctx;
88     T(ctx = EVP_PKEY_CTX_new(tkey, NULL));
89     T(EVP_PKEY_keygen_init(ctx));
90     if (paramset)
91         T(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", paramset));
92     EVP_PKEY *pkey = NULL;
93     T((EVP_PKEY_keygen(ctx, &pkey)) == 1);
94     EVP_PKEY_CTX_free(ctx);
95     EVP_PKEY_free(tkey);
96
97     /* REQ. */
98     X509_REQ *req = NULL;
99     T(req = X509_REQ_new());
100     T(X509_REQ_set_version(req, 0L));
101     X509_NAME *name;
102     T(name = X509_NAME_new());
103     T(X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char *)"Test CA", -1, -1, 0));
104     T(X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"Test Key", -1, -1, 0));
105     T(X509_REQ_set_subject_name(req, name));
106     T(X509_REQ_set_pubkey(req, pkey));
107     X509_NAME_free(name);
108
109     /* Cert. */
110     X509 *x509ss = NULL;
111     T(x509ss = X509_new());
112     T(X509_set_version(x509ss, 2));
113     BIGNUM *brnd = BN_new();
114     T(BN_rand(brnd, 20 * 8 - 1, -1, 0));
115     T(BN_to_ASN1_INTEGER(brnd, X509_get_serialNumber(x509ss)));
116     T(X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)));
117     T(X509_gmtime_adj(X509_getm_notBefore(x509ss), 0));
118     T(X509_time_adj_ex(X509_getm_notAfter(x509ss), 1, 0, NULL));
119     T(X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req)));
120     T(X509_set_pubkey(x509ss, X509_REQ_get0_pubkey(req)));
121     X509_REQ_free(req);
122     BN_free(brnd);
123
124     X509V3_CTX v3ctx;
125     X509V3_set_ctx_nodb(&v3ctx);
126     X509V3_set_ctx(&v3ctx, x509ss, x509ss, NULL, NULL, 0);
127     X509_EXTENSION *ext;
128     T(ext = X509V3_EXT_conf_nid(NULL, &v3ctx, NID_basic_constraints, "critical,CA:TRUE"));
129     T(X509_add_ext(x509ss, ext, 0));
130     X509_EXTENSION_free(ext);
131     T(ext = X509V3_EXT_conf_nid(NULL, &v3ctx, NID_subject_key_identifier, "hash"));
132     T(X509_add_ext(x509ss, ext, 1));
133     X509_EXTENSION_free(ext);
134     T(ext = X509V3_EXT_conf_nid(NULL, &v3ctx, NID_authority_key_identifier, "keyid:always,issuer"));
135     T(X509_add_ext(x509ss, ext, 2));
136     X509_EXTENSION_free(ext);
137
138     EVP_MD_CTX *mctx;
139     T(mctx = EVP_MD_CTX_new());
140     T(EVP_DigestSignInit(mctx, NULL, NULL, NULL, pkey));
141     T(X509_sign_ctx(x509ss, mctx));
142     EVP_MD_CTX_free(mctx);
143 #if 0
144     /* Print cert in text format. */
145     X509_print_fp(stdout, x509ss);
146 #endif
147 #if 0
148     /* Print cert in PEM format. */
149     BIO *out = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT);
150     PEM_write_bio_X509(out, x509ss);
151     BIO_free_all(out);
152 #endif
153     ck->pkey = pkey;
154     ck->cert = x509ss;
155 }
156
157 /* Non-blocking BIO test mechanic is based on sslapitest.c */
158 int test(const char *algname, const char *paramset)
159 {
160     int ret = 0;
161
162     printf(cBLUE "Test %s", algname);
163     if (paramset)
164         printf(cBLUE ":%s", paramset);
165     printf(cNORM "\n");
166
167     struct certkey ck;
168     certgen(algname, paramset, &ck);
169
170     SSL_CTX *cctx, *sctx;
171
172     T(sctx = SSL_CTX_new(TLS_server_method()));
173     T(SSL_CTX_use_certificate(sctx, ck.cert));
174     T(SSL_CTX_use_PrivateKey(sctx, ck.pkey));
175     T(SSL_CTX_check_private_key(sctx));
176
177     T(cctx = SSL_CTX_new(TLS_client_method()));
178
179     /* create_ssl_objects */
180     SSL *serverssl, *clientssl;
181     T(serverssl = SSL_new(sctx));
182     T(clientssl = SSL_new(cctx));
183     BIO *s_to_c_bio, *c_to_s_bio;
184     T(s_to_c_bio = BIO_new(BIO_s_mem()));
185     T(c_to_s_bio = BIO_new(BIO_s_mem()));
186     /* Non-blocking IO. */
187     BIO_set_mem_eof_return(s_to_c_bio, -1);
188     BIO_set_mem_eof_return(c_to_s_bio, -1);
189     /* Transfer BIOs to SSL objects. */
190     SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio);
191     BIO_up_ref(s_to_c_bio);
192     BIO_up_ref(c_to_s_bio);
193     SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio);
194     c_to_s_bio = NULL;
195     c_to_s_bio = NULL;
196
197     /* create_ssl_connection */
198     int retc = -1, rets = -1, err;
199     do {
200         err = SSL_ERROR_WANT_WRITE;
201         while (retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
202             retc = SSL_connect(clientssl);
203             if (retc <= 0)
204                 err = SSL_get_error(clientssl, retc);
205             if (verbose)
206                 printf("SSL_connect: %d %d\n", retc, err);
207         }
208         if (retc <= 0 && err != SSL_ERROR_WANT_READ) {
209             ERR_print_errors_fp(stderr);
210             OpenSSLDie(__FILE__, __LINE__, "SSL_connect");
211         }
212         err = SSL_ERROR_WANT_WRITE;
213         while (rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
214             rets = SSL_accept(serverssl);
215             if (rets <= 0)
216                 err = SSL_get_error(serverssl, rets);
217             if (verbose)
218                 printf("SSL_accept: %d %d\n", rets, err);
219         }
220         if (rets <= 0 && err != SSL_ERROR_WANT_READ &&
221             err != SSL_ERROR_WANT_X509_LOOKUP) {
222             ERR_print_errors_fp(stderr);
223             OpenSSLDie(__FILE__, __LINE__, "SSL_accept");
224         }
225     } while (retc <=0 || rets <= 0);
226
227     /* Two SSL_read_ex should fail. */
228     unsigned char buf;
229     size_t readbytes;
230     T(!SSL_read_ex(clientssl, &buf, sizeof(buf), &readbytes));
231     T(!SSL_read_ex(clientssl, &buf, sizeof(buf), &readbytes));
232
233     /* Connect client to the server. */
234     T(SSL_do_handshake(clientssl) == 1);
235     printf("Protocol: %s\n", SSL_get_version(clientssl));
236     printf("Cipher:   %s\n", SSL_get_cipher_name(clientssl));
237     if (verbose) {
238         SSL_SESSION *sess = SSL_get0_session(clientssl);
239         SSL_SESSION_print_fp(stdout, sess);
240     }
241
242     /* Transfer some data. */
243     int i;
244     for (i = 0; i < 16; i++) {
245         char pbuf[512], lbuf[512];
246
247         memset(pbuf, 'c' + i, sizeof(pbuf));
248         T(SSL_write(serverssl, pbuf, sizeof(pbuf)) == sizeof(pbuf));
249         T(SSL_read(clientssl, lbuf, sizeof(lbuf)) == sizeof(lbuf));
250         T(memcmp(pbuf, lbuf, sizeof(pbuf)) == 0);
251
252         memset(lbuf, 's' + i, sizeof(lbuf));
253         T(SSL_write(clientssl, lbuf, sizeof(lbuf)) == sizeof(lbuf));
254         T(SSL_read(serverssl, pbuf, sizeof(pbuf)) == sizeof(pbuf));
255         T(memcmp(pbuf, lbuf, sizeof(pbuf)) == 0);
256     }
257
258     SSL_shutdown(clientssl);
259     SSL_shutdown(serverssl);
260
261     SSL_free(serverssl);
262     SSL_free(clientssl);
263     SSL_CTX_free(sctx);
264     SSL_CTX_free(cctx);
265
266     /* Every responsible process should free this. */
267     X509_free(ck.cert);
268     EVP_PKEY_free(ck.pkey);
269     return ret;
270 }
271
272 int main(int argc, char **argv)
273 {
274     int ret = 0;
275
276     OPENSSL_add_all_algorithms_conf();
277
278     char *p;
279     if ((p = getenv("VERBOSE")))
280         verbose = atoi(p);
281
282     ret |= test("rsa", NULL);
283     cipher_list = "LEGACY-GOST2012-GOST8912-GOST8912";
284     ret |= test("gost2012_256", "A");
285     ret |= test("gost2012_256", "B");
286     ret |= test("gost2012_256", "C");
287     ret |= test("gost2012_256", "TCA");
288     ret |= test("gost2012_512", "A");
289     ret |= test("gost2012_512", "B");
290     ret |= test("gost2012_512", "C");
291
292     if (ret)
293         printf(cDRED "= Some tests FAILED!\n" cNORM);
294     else
295         printf(cDGREEN "= All tests passed!\n" cNORM);
296     return ret;
297 }