1*e7be843bSPierre Pronchery=pod 2*e7be843bSPierre Pronchery 3*e7be843bSPierre Pronchery=begin comment 4*e7be843bSPierre Pronchery 5*e7be843bSPierre ProncheryNB: Changes to the source code samples in this file should also be reflected in 6*e7be843bSPierre Proncherydemos/guide/tls-server-block.c 7*e7be843bSPierre Pronchery 8*e7be843bSPierre Pronchery=end comment 9*e7be843bSPierre Pronchery 10*e7be843bSPierre Pronchery=head1 NAME 11*e7be843bSPierre Pronchery 12*e7be843bSPierre Proncheryossl-guide-tls-server-block 13*e7be843bSPierre Pronchery- OpenSSL Guide: Writing a simple blocking TLS server 14*e7be843bSPierre Pronchery 15*e7be843bSPierre Pronchery=head1 SIMPLE BLOCKING TLS SERVER EXAMPLE 16*e7be843bSPierre Pronchery 17*e7be843bSPierre ProncheryThis page will present various source code samples demonstrating how to write a 18*e7be843bSPierre Proncherysimple, non-concurrent, TLS "echo" server application which accepts one client 19*e7be843bSPierre Proncheryconnection at a time, echoing input from the client back to the same client. 20*e7be843bSPierre ProncheryOnce the current client disconnects, the next client connection is accepted. 21*e7be843bSPierre Pronchery 22*e7be843bSPierre ProncheryBoth the acceptor socket and client connections are "blocking". A more typical 23*e7be843bSPierre Proncheryserver might use nonblocking sockets with an event loop and callbacks for I/O 24*e7be843bSPierre Proncheryevents. 25*e7be843bSPierre Pronchery 26*e7be843bSPierre ProncheryThe complete source code for this example blocking TLS server is available in 27*e7be843bSPierre Proncherythe B<demos/guide> directory of the OpenSSL source distribution in the file 28*e7be843bSPierre ProncheryB<tls-server-block.c>. It is also available online at 29*e7be843bSPierre ProncheryL<https://github.com/openssl/openssl/blob/master/demos/guide/tls-server-block.c>. 30*e7be843bSPierre Pronchery 31*e7be843bSPierre ProncheryWe assume that you already have OpenSSL installed on your system; that you 32*e7be843bSPierre Proncheryalready have some fundamental understanding of OpenSSL concepts and TLS (see 33*e7be843bSPierre ProncheryL<ossl-guide-libraries-introduction(7)> and L<ossl-guide-tls-introduction(7)>); 34*e7be843bSPierre Proncheryand that you know how to write and build C code and link it against the 35*e7be843bSPierre Proncherylibcrypto and libssl libraries that are provided by OpenSSL. It also assumes 36*e7be843bSPierre Proncherythat you have a basic understanding of TCP/IP and sockets. 37*e7be843bSPierre Pronchery 38*e7be843bSPierre Pronchery=head2 Creating the SSL_CTX and SSL objects 39*e7be843bSPierre Pronchery 40*e7be843bSPierre ProncheryThe first step is to create an B<SSL_CTX> object for our server. We use the 41*e7be843bSPierre ProncheryL<SSL_CTX_new(3)> function for this purpose. We could alternatively use 42*e7be843bSPierre ProncheryL<SSL_CTX_new_ex(3)> if we want to associate the B<SSL_CTX> with a particular 43*e7be843bSPierre ProncheryB<OSSL_LIB_CTX> (see L<ossl-guide-libraries-introduction(7)> to learn about 44*e7be843bSPierre ProncheryB<OSSL_LIB_CTX>). We pass as an argument the return value of the function 45*e7be843bSPierre ProncheryL<TLS_server_method(3)>. You should use this method whenever you are writing a 46*e7be843bSPierre ProncheryTLS server. This method will automatically use TLS version negotiation to select 47*e7be843bSPierre Proncherythe highest version of the protocol that is mutually supported by both the 48*e7be843bSPierre Proncheryserver and the client. 49*e7be843bSPierre Pronchery 50*e7be843bSPierre Pronchery /* 51*e7be843bSPierre Pronchery * An SSL_CTX holds shared configuration information for multiple 52*e7be843bSPierre Pronchery * subsequent per-client SSL connections. 53*e7be843bSPierre Pronchery */ 54*e7be843bSPierre Pronchery ctx = SSL_CTX_new(TLS_server_method()); 55*e7be843bSPierre Pronchery if (ctx == NULL) { 56*e7be843bSPierre Pronchery ERR_print_errors_fp(stderr); 57*e7be843bSPierre Pronchery errx(res, "Failed to create server SSL_CTX"); 58*e7be843bSPierre Pronchery } 59*e7be843bSPierre Pronchery 60*e7be843bSPierre ProncheryWe would also like to restrict the TLS versions that we are willing to accept to 61*e7be843bSPierre ProncheryTLSv1.2 or above. TLS protocol versions earlier than that are generally to be 62*e7be843bSPierre Proncheryavoided where possible. We can do that using 63*e7be843bSPierre ProncheryL<SSL_CTX_set_min_proto_version(3)>: 64*e7be843bSPierre Pronchery 65*e7be843bSPierre Pronchery /* 66*e7be843bSPierre Pronchery * TLS versions older than TLS 1.2 are deprecated by IETF and SHOULD 67*e7be843bSPierre Pronchery * be avoided if possible. 68*e7be843bSPierre Pronchery */ 69*e7be843bSPierre Pronchery if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) { 70*e7be843bSPierre Pronchery SSL_CTX_free(ctx); 71*e7be843bSPierre Pronchery ERR_print_errors_fp(stderr); 72*e7be843bSPierre Pronchery errx(res, "Failed to set the minimum TLS protocol version"); 73*e7be843bSPierre Pronchery } 74*e7be843bSPierre Pronchery 75*e7be843bSPierre ProncheryNext we configure some option flags, see L<SSL_CTX_set_options(3)> for details: 76*e7be843bSPierre Pronchery 77*e7be843bSPierre Pronchery /* 78*e7be843bSPierre Pronchery * Tolerate clients hanging up without a TLS "shutdown". Appropriate in all 79*e7be843bSPierre Pronchery * application protocols which perform their own message "framing", and 80*e7be843bSPierre Pronchery * don't rely on TLS to defend against "truncation" attacks. 81*e7be843bSPierre Pronchery */ 82*e7be843bSPierre Pronchery opts = SSL_OP_IGNORE_UNEXPECTED_EOF; 83*e7be843bSPierre Pronchery 84*e7be843bSPierre Pronchery /* 85*e7be843bSPierre Pronchery * Block potential CPU-exhaustion attacks by clients that request frequent 86*e7be843bSPierre Pronchery * renegotiation. This is of course only effective if there are existing 87*e7be843bSPierre Pronchery * limits on initial full TLS handshake or connection rates. 88*e7be843bSPierre Pronchery */ 89*e7be843bSPierre Pronchery opts |= SSL_OP_NO_RENEGOTIATION; 90*e7be843bSPierre Pronchery 91*e7be843bSPierre Pronchery /* 92*e7be843bSPierre Pronchery * Most servers elect to use their own cipher preference rather than that of 93*e7be843bSPierre Pronchery * the client. 94*e7be843bSPierre Pronchery */ 95*e7be843bSPierre Pronchery opts |= SSL_OP_CIPHER_SERVER_PREFERENCE; 96*e7be843bSPierre Pronchery 97*e7be843bSPierre Pronchery /* Apply the selection options */ 98*e7be843bSPierre Pronchery SSL_CTX_set_options(ctx, opts); 99*e7be843bSPierre Pronchery 100*e7be843bSPierre ProncheryServers need a private key and certificate. Though anonymous ciphers (no 101*e7be843bSPierre Proncheryserver certificate) are possible in TLS 1.2, they are rarely applicable, and 102*e7be843bSPierre Proncheryare not currently defined for TLS 1.3. Additional intermediate issuer CA 103*e7be843bSPierre Proncherycertificates are often also required, and both the server (end-entity or EE) 104*e7be843bSPierre Proncherycertificate and the issuer ("chain") certificates are most easily configured in 105*e7be843bSPierre Proncherya single "chain file". Below we load such a chain file (the EE certificate 106*e7be843bSPierre Proncherymust appear first), and then load the corresponding private key, checking that 107*e7be843bSPierre Proncheryit matches the server certificate. No checks are performed to check the 108*e7be843bSPierre Proncheryintegrity of the chain (CA signatures or certificate expiration dates, for 109*e7be843bSPierre Proncheryexample). 110*e7be843bSPierre Pronchery 111*e7be843bSPierre Pronchery /* 112*e7be843bSPierre Pronchery * Load the server's certificate *chain* file (PEM format), which includes 113*e7be843bSPierre Pronchery * not only the leaf (end-entity) server certificate, but also any 114*e7be843bSPierre Pronchery * intermediate issuer-CA certificates. The leaf certificate must be the 115*e7be843bSPierre Pronchery * first certificate in the file. 116*e7be843bSPierre Pronchery * 117*e7be843bSPierre Pronchery * In advanced use-cases this can be called multiple times, once per public 118*e7be843bSPierre Pronchery * key algorithm for which the server has a corresponding certificate. 119*e7be843bSPierre Pronchery * However, the corresponding private key (see below) must be loaded first, 120*e7be843bSPierre Pronchery * *before* moving on to the next chain file. 121*e7be843bSPierre Pronchery */ 122*e7be843bSPierre Pronchery if (SSL_CTX_use_certificate_chain_file(ctx, "chain.pem") <= 0) { 123*e7be843bSPierre Pronchery SSL_CTX_free(ctx); 124*e7be843bSPierre Pronchery ERR_print_errors_fp(stderr); 125*e7be843bSPierre Pronchery errx(res, "Failed to load the server certificate chain file"); 126*e7be843bSPierre Pronchery } 127*e7be843bSPierre Pronchery 128*e7be843bSPierre Pronchery /* 129*e7be843bSPierre Pronchery * Load the corresponding private key, this also checks that the private 130*e7be843bSPierre Pronchery * key matches the just loaded end-entity certificate. It does not check 131*e7be843bSPierre Pronchery * whether the certificate chain is valid, the certificates could be 132*e7be843bSPierre Pronchery * expired, or may otherwise fail to form a chain that a client can validate. 133*e7be843bSPierre Pronchery */ 134*e7be843bSPierre Pronchery if (SSL_CTX_use_PrivateKey_file(ctx, "pkey.pem", SSL_FILETYPE_PEM) <= 0) { 135*e7be843bSPierre Pronchery SSL_CTX_free(ctx); 136*e7be843bSPierre Pronchery ERR_print_errors_fp(stderr); 137*e7be843bSPierre Pronchery errx(res, "Error loading the server private key file, " 138*e7be843bSPierre Pronchery "possible key/cert mismatch???"); 139*e7be843bSPierre Pronchery } 140*e7be843bSPierre Pronchery 141*e7be843bSPierre ProncheryNext we enable session caching, which makes it possible for clients to more 142*e7be843bSPierre Proncheryefficiently make additional TLS connections after completing an initial full 143*e7be843bSPierre ProncheryTLS handshake. With TLS 1.3, session resumption typically still performs a fresh 144*e7be843bSPierre Proncherykey agreement, but the certificate exchange is avoided. 145*e7be843bSPierre Pronchery 146*e7be843bSPierre Pronchery /* 147*e7be843bSPierre Pronchery * Servers that want to enable session resumption must specify a cache id 148*e7be843bSPierre Pronchery * byte array, that identifies the server application, and reduces the 149*e7be843bSPierre Pronchery * chance of inappropriate cache sharing. 150*e7be843bSPierre Pronchery */ 151*e7be843bSPierre Pronchery SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id)); 152*e7be843bSPierre Pronchery SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); 153*e7be843bSPierre Pronchery 154*e7be843bSPierre Pronchery /* 155*e7be843bSPierre Pronchery * How many client TLS sessions to cache. The default is 156*e7be843bSPierre Pronchery * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (20k in recent OpenSSL versions), 157*e7be843bSPierre Pronchery * which may be too small or too large. 158*e7be843bSPierre Pronchery */ 159*e7be843bSPierre Pronchery SSL_CTX_sess_set_cache_size(ctx, 1024); 160*e7be843bSPierre Pronchery 161*e7be843bSPierre Pronchery /* 162*e7be843bSPierre Pronchery * Sessions older than this are considered a cache miss even if still in 163*e7be843bSPierre Pronchery * the cache. The default is two hours. Busy servers whose clients make 164*e7be843bSPierre Pronchery * many connections in a short burst may want a shorter timeout, on lightly 165*e7be843bSPierre Pronchery * loaded servers with sporadic connections from any given client, a longer 166*e7be843bSPierre Pronchery * time may be appropriate. 167*e7be843bSPierre Pronchery */ 168*e7be843bSPierre Pronchery SSL_CTX_set_timeout(ctx, 3600); 169*e7be843bSPierre Pronchery 170*e7be843bSPierre ProncheryMost servers, including this one, do not solicit client certificates. We 171*e7be843bSPierre Proncherytherefore do not need a "trust store" and allow the handshake to complete even 172*e7be843bSPierre Proncherywhen the client does not present a certificate. Note: Even if a client did 173*e7be843bSPierre Proncherypresent a trusted ceritificate, for it to be useful, the server application 174*e7be843bSPierre Proncherywould still need custom code to use the verified identity to grant nondefault 175*e7be843bSPierre Proncheryaccess to that particular client. Some servers grant access to all clients 176*e7be843bSPierre Proncherywith certificates from a private CA, this then requires processing of 177*e7be843bSPierre Proncherycertificate revocation lists to deauthorise a client. It is often simpler and 178*e7be843bSPierre Proncherymore secure to instead keep a list of authorised public keys. 179*e7be843bSPierre Pronchery 180*e7be843bSPierre ProncheryThough this is the default setting, we explicitly call the 181*e7be843bSPierre ProncheryL<SSL_CTX_set_verify(3)> function and pass the B<SSL_VERIFY_NONE> value to it. 182*e7be843bSPierre ProncheryThe final argument to this function is a callback that you can optionally 183*e7be843bSPierre Proncherysupply to override the default handling for certificate verification. Most 184*e7be843bSPierre Proncheryapplications do not need to do this so this can safely be set to NULL to get 185*e7be843bSPierre Proncherythe default handling. 186*e7be843bSPierre Pronchery 187*e7be843bSPierre Pronchery /* 188*e7be843bSPierre Pronchery * Clients rarely employ certificate-based authentication, and so we don't 189*e7be843bSPierre Pronchery * require "mutual" TLS authentication (indeed there's no way to know 190*e7be843bSPierre Pronchery * whether or how the client authenticated the server, so the term "mutual" 191*e7be843bSPierre Pronchery * is potentially misleading). 192*e7be843bSPierre Pronchery * 193*e7be843bSPierre Pronchery * Since we're not soliciting or processing client certificates, we don't 194*e7be843bSPierre Pronchery * need to configure a trusted-certificate store, so no call to 195*e7be843bSPierre Pronchery * SSL_CTX_set_default_verify_paths() is needed. The server's own 196*e7be843bSPierre Pronchery * certificate chain is assumed valid. 197*e7be843bSPierre Pronchery */ 198*e7be843bSPierre Pronchery SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); 199*e7be843bSPierre Pronchery 200*e7be843bSPierre ProncheryThat is all the setup that we need to do for the B<SSL_CTX>. Next we create an 201*e7be843bSPierre Proncheryacceptor BIO on which to accept client connections. This just records the 202*e7be843bSPierre Proncheryintended port (and optional "host:" prefix), without actually creating the 203*e7be843bSPierre Proncherysocket. This delayed processing allows the programmer to specify additional 204*e7be843bSPierre Proncherybehaviours before the listening socket is actually created. 205*e7be843bSPierre Pronchery 206*e7be843bSPierre Pronchery /* 207*e7be843bSPierre Pronchery * Create a listener socket wrapped in a BIO. 208*e7be843bSPierre Pronchery * The first call to BIO_do_accept() initialises the socket 209*e7be843bSPierre Pronchery */ 210*e7be843bSPierre Pronchery acceptor_bio = BIO_new_accept(hostport); 211*e7be843bSPierre Pronchery if (acceptor_bio == NULL) { 212*e7be843bSPierre Pronchery SSL_CTX_free(ctx); 213*e7be843bSPierre Pronchery ERR_print_errors_fp(stderr); 214*e7be843bSPierre Pronchery errx(res, "Error creating acceptor bio"); 215*e7be843bSPierre Pronchery } 216*e7be843bSPierre Pronchery 217*e7be843bSPierre ProncheryServers almost always want to use the "SO_REUSEADDR" option to avoid startup 218*e7be843bSPierre Proncheryfailures if there are still lingering client connections, so we do that before 219*e7be843bSPierre Proncherymaking the B<first> call to L<BIO_do_accept(3)> which creates the listening 220*e7be843bSPierre Proncherysocket, without accepting a client connection. Subsequent calls to the same 221*e7be843bSPierre Proncheryfunction will accept new connections. 222*e7be843bSPierre Pronchery 223*e7be843bSPierre Pronchery BIO_set_bind_mode(acceptor_bio, BIO_BIND_REUSEADDR); 224*e7be843bSPierre Pronchery if (BIO_do_accept(acceptor_bio) <= 0) { 225*e7be843bSPierre Pronchery SSL_CTX_free(ctx); 226*e7be843bSPierre Pronchery ERR_print_errors_fp(stderr); 227*e7be843bSPierre Pronchery errx(res, "Error setting up acceptor socket"); 228*e7be843bSPierre Pronchery } 229*e7be843bSPierre Pronchery 230*e7be843bSPierre Pronchery=head2 Server loop 231*e7be843bSPierre Pronchery 232*e7be843bSPierre ProncheryThe server now enters a "forever" loop handling one client connection at a 233*e7be843bSPierre Proncherytime. Before each connection we clear the OpenSSL error stack, so that any 234*e7be843bSPierre Proncheryerror reports are related to just the new connection. 235*e7be843bSPierre Pronchery 236*e7be843bSPierre Pronchery /* Pristine error stack for each new connection */ 237*e7be843bSPierre Pronchery ERR_clear_error(); 238*e7be843bSPierre Pronchery 239*e7be843bSPierre ProncheryAt this point the server blocks to accept the next client: 240*e7be843bSPierre Pronchery 241*e7be843bSPierre Pronchery /* Wait for the next client to connect */ 242*e7be843bSPierre Pronchery if (BIO_do_accept(acceptor_bio) <= 0) { 243*e7be843bSPierre Pronchery /* Client went away before we accepted the connection */ 244*e7be843bSPierre Pronchery continue; 245*e7be843bSPierre Pronchery } 246*e7be843bSPierre Pronchery 247*e7be843bSPierre ProncheryOn success the accepted client connection has been wrapped in a fresh BIO and 248*e7be843bSPierre Proncherypushed onto the end of the acceptor BIO chain. We pop it off returning the 249*e7be843bSPierre Proncheryacceptor BIO to its initial state. 250*e7be843bSPierre Pronchery 251*e7be843bSPierre Pronchery /* Pop the client connection from the BIO chain */ 252*e7be843bSPierre Pronchery client_bio = BIO_pop(acceptor_bio); 253*e7be843bSPierre Pronchery fprintf(stderr, "New client connection accepted\n"); 254*e7be843bSPierre Pronchery 255*e7be843bSPierre ProncheryNext, we create an B<SSL> object by calling the B<SSL_new(3)> function and 256*e7be843bSPierre Proncherypassing the B<SSL_CTX> we created as an argument. The client connection BIO is 257*e7be843bSPierre Proncheryconfigured as the I/O conduit for this SSL handle. SSL_set_bio transfers 258*e7be843bSPierre Proncheryownership of the BIO or BIOs involved (our B<client_bio>) to the SSL handle. 259*e7be843bSPierre Pronchery 260*e7be843bSPierre Pronchery /* Associate a new SSL handle with the new connection */ 261*e7be843bSPierre Pronchery if ((ssl = SSL_new(ctx)) == NULL) { 262*e7be843bSPierre Pronchery ERR_print_errors_fp(stderr); 263*e7be843bSPierre Pronchery warnx("Error creating SSL handle for new connection"); 264*e7be843bSPierre Pronchery BIO_free(client_bio); 265*e7be843bSPierre Pronchery continue; 266*e7be843bSPierre Pronchery } 267*e7be843bSPierre Pronchery SSL_set_bio(ssl, client_bio, client_bio); 268*e7be843bSPierre Pronchery 269*e7be843bSPierre ProncheryAnd now we're ready to attempt the SSL handshake. With a blocking socket 270*e7be843bSPierre ProncheryOpenSSL will perform all the read and write operations required to complete the 271*e7be843bSPierre Proncheryhandshake (or detect and report a failure) before returning. 272*e7be843bSPierre Pronchery 273*e7be843bSPierre Pronchery /* Attempt an SSL handshake with the client */ 274*e7be843bSPierre Pronchery if (SSL_accept(ssl) <= 0) { 275*e7be843bSPierre Pronchery ERR_print_errors_fp(stderr); 276*e7be843bSPierre Pronchery warnx("Error performing SSL handshake with client"); 277*e7be843bSPierre Pronchery SSL_free(ssl); 278*e7be843bSPierre Pronchery continue; 279*e7be843bSPierre Pronchery } 280*e7be843bSPierre Pronchery 281*e7be843bSPierre ProncheryWith the handshake complete, the server loops echoing client input back to the 282*e7be843bSPierre Proncheryclient: 283*e7be843bSPierre Pronchery 284*e7be843bSPierre Pronchery while (SSL_read_ex(ssl, buf, sizeof(buf), &nread) > 0) { 285*e7be843bSPierre Pronchery if (SSL_write_ex(ssl, buf, nread, &nwritten) > 0 && 286*e7be843bSPierre Pronchery nwritten == nread) { 287*e7be843bSPierre Pronchery total += nwritten; 288*e7be843bSPierre Pronchery continue; 289*e7be843bSPierre Pronchery } 290*e7be843bSPierre Pronchery warnx("Error echoing client input"); 291*e7be843bSPierre Pronchery break; 292*e7be843bSPierre Pronchery } 293*e7be843bSPierre Pronchery 294*e7be843bSPierre ProncheryOnce the client closes its connection, we report the number of bytes sent to 295*e7be843bSPierre ProncheryB<stderr> and free the SSL handle, which also frees the B<client_bio> and 296*e7be843bSPierre Proncherycloses the underlying socket. 297*e7be843bSPierre Pronchery 298*e7be843bSPierre Pronchery fprintf(stderr, "Client connection closed, %zu bytes sent\n", total); 299*e7be843bSPierre Pronchery SSL_free(ssl); 300*e7be843bSPierre Pronchery 301*e7be843bSPierre ProncheryThe server is now ready to accept the next client connection. 302*e7be843bSPierre Pronchery 303*e7be843bSPierre Pronchery=head2 Final clean up 304*e7be843bSPierre Pronchery 305*e7be843bSPierre ProncheryIf the server could somehow manage to break out of the infinite loop, and 306*e7be843bSPierre Proncherybe ready to exit, it would first deallocate the constructed B<SSL_CTX>. 307*e7be843bSPierre Pronchery 308*e7be843bSPierre Pronchery /* 309*e7be843bSPierre Pronchery * Unreachable placeholder cleanup code, the above loop runs forever. 310*e7be843bSPierre Pronchery */ 311*e7be843bSPierre Pronchery SSL_CTX_free(ctx); 312*e7be843bSPierre Pronchery return EXIT_SUCCESS; 313*e7be843bSPierre Pronchery 314*e7be843bSPierre Pronchery=head1 SEE ALSO 315*e7be843bSPierre Pronchery 316*e7be843bSPierre ProncheryL<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>, 317*e7be843bSPierre ProncheryL<ossl-guide-libssl-introduction(7)>, L<ossl-guide-tls-introduction(7)>, 318*e7be843bSPierre ProncheryL<ossl-guide-tls-client-non-block(7)>, L<ossl-guide-quic-client-block(7)> 319*e7be843bSPierre Pronchery 320*e7be843bSPierre Pronchery=head1 COPYRIGHT 321*e7be843bSPierre Pronchery 322*e7be843bSPierre ProncheryCopyright 2024 The OpenSSL Project Authors. All Rights Reserved. 323*e7be843bSPierre Pronchery 324*e7be843bSPierre ProncheryLicensed under the Apache License 2.0 (the "License"). You may not use 325*e7be843bSPierre Proncherythis file except in compliance with the License. You can obtain a copy 326*e7be843bSPierre Proncheryin the file LICENSE in the source distribution or at 327*e7be843bSPierre ProncheryL<https://www.openssl.org/source/license.html>. 328*e7be843bSPierre Pronchery 329*e7be843bSPierre Pronchery=cut 330