<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.openssl.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jwalton</id>
	<title>OpenSSLWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.openssl.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jwalton"/>
	<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php/Special:Contributions/Jwalton"/>
	<updated>2026-05-28T23:01:37Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.13</generator>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=SSL/TLS_Client&amp;diff=3222</id>
		<title>SSL/TLS Client</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=SSL/TLS_Client&amp;diff=3222"/>
		<updated>2022-12-12T15:33:28Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Make PREFERRED_CIPHERS a constant array.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SSL/TLS Client]] is sample code for a basic web client that fetches a page. The code shown below omits error checking for brevity, but the sample available for download performs the error checking.&lt;br /&gt;
&lt;br /&gt;
The sample code will set up &amp;lt;tt&amp;gt;BIO&amp;lt;/tt&amp;gt; to fet a page from &amp;lt;tt&amp;gt;www.random.org&amp;lt;/tt&amp;gt;. The code uses TLS (not SSL) and utilizes the Server Name Indication (SNI) extension from [http://tools.ietf.org/rfc/rfc3546.txt RFC 3546, Transport Layer Security (TLS) Extensions].&lt;br /&gt;
&lt;br /&gt;
If you need features beyond the example below, then you should examine &amp;lt;tt&amp;gt;s_client.c&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;apps/&amp;lt;/tt&amp;gt; directory of the OpenSSL distribution. OpenSSL's &amp;lt;tt&amp;gt;s_client&amp;lt;/tt&amp;gt; implements nearly every client side feature available from the library.&lt;br /&gt;
&lt;br /&gt;
The code below does '''not''' perform hostname verification. OpenSSL prior to 1.1.0 does not perform the check, and you must perform the check yourself. The OpenSSL [http://www.openssl.org/news/changelog.html Change Log] for OpenSSL 1.1.0 states you can use &amp;lt;tt&amp;gt;-verify_name&amp;lt;/tt&amp;gt; option, and &amp;lt;tt&amp;gt;apps.c&amp;lt;/tt&amp;gt; offers &amp;lt;tt&amp;gt;-verify_hostname&amp;lt;/tt&amp;gt;. But &amp;lt;tt&amp;gt;s_client&amp;lt;/tt&amp;gt; does not respond to either switch, so its unclear how hostname checking will be implemented or invoked for a client. '''Note (N.B.)''': hostname verification is marked as experimental, so switches, options, and implementations could change.&lt;br /&gt;
&lt;br /&gt;
If you are looking for guidance on which protocols and ciphers you should be using, then see Adam Langley's blog [http://www.imperialviolet.org/2014/12/08/poodleagain.html The POODLE bites again]. The short version: use only TLS 1.2, use only ephemeral key exchanges, and use only AEAD ciphers (like AES/GCM, Camellia/GCM, ChaCha/Poly1305).&lt;br /&gt;
&lt;br /&gt;
An example of a TLS client written by the developer team can be found in the source code at demos/sslecho.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
&lt;br /&gt;
The code below demonstrates a basic client that uses BIOs and TLS to connect to &amp;lt;tt&amp;gt;www.random.org&amp;lt;/tt&amp;gt;, and fetches 32 bytes of random data through an HTTP request. The sample code is available for download below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define HOST_NAME &amp;quot;www.random.org&amp;quot;&lt;br /&gt;
#define HOST_PORT &amp;quot;443&amp;quot;&lt;br /&gt;
#define HOST_RESOURCE &amp;quot;/cgi-bin/randbyte?nbytes=32&amp;amp;format=h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
long res = 1;&lt;br /&gt;
&lt;br /&gt;
SSL_CTX* ctx = NULL;&lt;br /&gt;
BIO *web = NULL, *out = NULL;&lt;br /&gt;
SSL *ssl = NULL;&lt;br /&gt;
&lt;br /&gt;
init_openssl_library();&lt;br /&gt;
&lt;br /&gt;
const SSL_METHOD* method = SSLv23_method();&lt;br /&gt;
if(!(NULL != method)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
ctx = SSL_CTX_new(method);&lt;br /&gt;
if(!(ctx != NULL)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* Cannot fail ??? */&lt;br /&gt;
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);&lt;br /&gt;
&lt;br /&gt;
/* Cannot fail ??? */&lt;br /&gt;
SSL_CTX_set_verify_depth(ctx, 4);&lt;br /&gt;
&lt;br /&gt;
/* Cannot fail ??? */&lt;br /&gt;
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;&lt;br /&gt;
SSL_CTX_set_options(ctx, flags);&lt;br /&gt;
&lt;br /&gt;
res = SSL_CTX_load_verify_locations(ctx, &amp;quot;random-org-chain.pem&amp;quot;, NULL);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
web = BIO_new_ssl_connect(ctx);&lt;br /&gt;
if(!(web != NULL)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
res = BIO_set_conn_hostname(web, HOST_NAME &amp;quot;:&amp;quot; HOST_PORT);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
BIO_get_ssl(web, &amp;amp;ssl);&lt;br /&gt;
if(!(ssl != NULL)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
const char PREFERRED_CIPHERS[] = &amp;quot;HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4&amp;quot;;&lt;br /&gt;
res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
res = SSL_set_tlsext_host_name(ssl, HOST_NAME);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
out = BIO_new_fp(stdout, BIO_NOCLOSE);&lt;br /&gt;
if(!(NULL != out)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
res = BIO_do_connect(web);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
res = BIO_do_handshake(web);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* Step 1: verify a server certificate was presented during the negotiation */&lt;br /&gt;
X509* cert = SSL_get_peer_certificate(ssl);&lt;br /&gt;
if(cert) { X509_free(cert); } /* Free immediately */&lt;br /&gt;
if(NULL == cert) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* Step 2: verify the result of chain verification */&lt;br /&gt;
/* Verification performed according to RFC 4158    */&lt;br /&gt;
res = SSL_get_verify_result(ssl);&lt;br /&gt;
if(!(X509_V_OK == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* Step 3: hostname verification */&lt;br /&gt;
/* An exercise left to the reader */&lt;br /&gt;
&lt;br /&gt;
BIO_puts(web, &amp;quot;GET &amp;quot; HOST_RESOURCE &amp;quot; HTTP/1.1\r\n&amp;quot;&lt;br /&gt;
              &amp;quot;Host: &amp;quot; HOST_NAME &amp;quot;\r\n&amp;quot;&lt;br /&gt;
              &amp;quot;Connection: close\r\n\r\n&amp;quot;);&lt;br /&gt;
BIO_puts(out, &amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
int len = 0;&lt;br /&gt;
do&lt;br /&gt;
{&lt;br /&gt;
  char buff[1536] = {};&lt;br /&gt;
  len = BIO_read(web, buff, sizeof(buff));&lt;br /&gt;
            &lt;br /&gt;
  if(len &amp;gt; 0)&lt;br /&gt;
    BIO_write(out, buff, len);&lt;br /&gt;
&lt;br /&gt;
} while (len &amp;gt; 0 || BIO_should_retry(web));&lt;br /&gt;
&lt;br /&gt;
if(out)&lt;br /&gt;
  BIO_free(out);&lt;br /&gt;
&lt;br /&gt;
if(web != NULL)&lt;br /&gt;
  BIO_free_all(web);&lt;br /&gt;
&lt;br /&gt;
if(NULL != ctx)&lt;br /&gt;
  SSL_CTX_free(ctx);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
The sample program initializes the OpenSSL library with &amp;lt;tt&amp;gt;init_openssl_library&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;init_openssl_library&amp;lt;/tt&amp;gt; calls three OpenSSL functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#if (SSLEAY_VERSION_NUMBER &amp;gt;= 0x0907000L)&lt;br /&gt;
# include &amp;lt;openssl/conf.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
void init_openssl_library(void)&lt;br /&gt;
{&lt;br /&gt;
  (void)SSL_library_init();&lt;br /&gt;
&lt;br /&gt;
  SSL_load_error_strings();&lt;br /&gt;
&lt;br /&gt;
  /* ERR_load_crypto_strings(); */&lt;br /&gt;
  &lt;br /&gt;
  OPENSSL_config(NULL);&lt;br /&gt;
    &lt;br /&gt;
  /* Include &amp;lt;openssl/opensslconf.h&amp;gt; to get this define */&lt;br /&gt;
#if defined (OPENSSL_THREADS)&lt;br /&gt;
  fprintf(stdout, &amp;quot;Warning: thread locking is not implemented\n&amp;quot;);&lt;br /&gt;
#endif&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;''' performs initialization of &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;, and loads required algorithms. The documents state &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; always returns &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;, so its a useless return value.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_load_error_strings&amp;lt;/tt&amp;gt;''' loads error strings from both &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. There's no need to call &amp;lt;tt&amp;gt;ERR_load_crypto_strings&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;OpenSSL_add_ssl_algorithms&amp;lt;/tt&amp;gt;''' is a &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;, so the call is omitted.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt;''' may (or may not) be needed. Internally, &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; is called based on a configuration options via &amp;lt;tt&amp;gt;OPENSSL_LOAD_CONF&amp;lt;/tt&amp;gt;. If you are dynamically loading an engine specified in &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt;, then you might need it so you should call it. That is, don't depend upon the OpenSSL library to call it for you.&lt;br /&gt;
&lt;br /&gt;
If you are building a multi-threaded client, you should set the locking callbacks. See [https://www.openssl.org/docs/crypto/threads.html threads(3)] for details.&lt;br /&gt;
&lt;br /&gt;
A detailed treatment of initialization can be found at [[Library Initialization]].&lt;br /&gt;
&lt;br /&gt;
== Context Setup ==&lt;br /&gt;
&lt;br /&gt;
The sample program uses '''&amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt;''' to create a context. '''&amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt;''' specifies that version negotiation will be used. Do not be confused by the name (it does NOT mean that only SSLv2 or SSLv3 will be used). The name is like that for historical reasons, and the function has been renamed to '''&amp;lt;tt&amp;gt;TLS_method&amp;lt;/tt&amp;gt;''' in the forthcoming OpenSSL version 1.1.0. Using this method will negotiate the highest protocol version supported by both the server and the client. SSL/TLS versions currently supported by OpenSSL 1.0.2 are SSLv2, SSLv3, TLS1.0, TLS1.1 and TLS1.2.&lt;br /&gt;
&lt;br /&gt;
The actual SSL and TLS protocols are further tuned through options. By using &amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt; (and removing the unwanted protocol versions with &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv2&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv3&amp;lt;/tt&amp;gt;), then you will effectively use TLS v1.0 and above, including TLS v1.2. You can also use &amp;lt;tt&amp;gt;SSL_OP_NO_TLSv1&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_OP_NO_TLSv1_1&amp;lt;/tt&amp;gt; if you want to use the TLS 1.2 protocol only.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_new&amp;lt;/tt&amp;gt;''' uses the &amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt; method to create a new '''SSL/TLS context object'''. If you use, for example &amp;lt;tt&amp;gt;TLSv1_method&amp;lt;/tt&amp;gt;, then you will only use TLS v1.0, and if you use &amp;lt;tt&amp;gt;TLSv1_1_method&amp;lt;/tt&amp;gt; then you will only use TLS v1.1. Typically you should always use '''&amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt;''' in preference to the version specific methods.&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 improves protocol selection by providing &amp;lt;tt&amp;gt;SSL_CTX_set_max_proto_version()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_CTX_set_min_proto_version()&amp;lt;/tt&amp;gt;. You no longer need to subtract unwanted options with &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv2&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv3&amp;lt;/tt&amp;gt;. Also see the [http://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_max_proto_version.html &amp;lt;tt&amp;gt;SSL_CTX_set_max_proto_version()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_CTX_set_min_proto_version()&amp;lt;/tt&amp;gt; man pages].&lt;br /&gt;
&lt;br /&gt;
== Options (1) ==&lt;br /&gt;
&lt;br /&gt;
After creating a context with &amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_CTX_new&amp;lt;/tt&amp;gt;, the context object is tuned with the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_CTX_set_verify_depth&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_CTX_set_options&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_CTX_load_verify_locations&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt;''' sets the &amp;lt;tt&amp;gt;SSL_VERIFY_PEER&amp;lt;/tt&amp;gt; flag and the verify callback. This ensures the chain is verified according to [http://tools.ietf.org/html/rfc4158 RFC 4158] and Issuer and Subject information can be printed. If you don't want to perform custom processing (such as printing or checking), then don't set the callback. OpenSSL's default checking should be sufficient, so pass &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;lt;tt&amp;gt;SSL_VERIFY_FAIL_IF_NO_PEER_CERT&amp;lt;/tt&amp;gt; flag, but it is used for servers and has no effect on clients. If you accidentally use &amp;lt;tt&amp;gt;SSL_VERIFY_FAIL_IF_NO_PEER_CERT&amp;lt;/tt&amp;gt;, then you chain will always verify when call &amp;lt;tt&amp;gt;SSL_get_verify_result&amp;lt;/tt&amp;gt; because the flag is ignored for clients (essentially, 0 is passed for the flag which performs no verification).&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_set_verify_depth&amp;lt;/tt&amp;gt;''' sets the chain depth to 4. Chain depth is fairly useless in practice.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_set_options&amp;lt;/tt&amp;gt;''' set the &amp;lt;tt&amp;gt;SSL_OP_ALL&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv2&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv3&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_OP_NO_COMPRESSION&amp;lt;/tt&amp;gt; options. In essence, it takes all the bug fixes and work arounds for the various servers, removes the SSL protocols (leaving only TLS protocols), and removes compression. The remaining TLS protocols are TLS 1.0, TLS 1.1, and TLS 1.2.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_load_verify_locations&amp;lt;/tt&amp;gt;''' loads the certificate chain for the &amp;lt;tt&amp;gt;random.org&amp;lt;/tt&amp;gt; site. The site's CA is Comodo, and the chain includes ''AddTrust External CA Root'', ''COMODO Certification Authority'', and ''COMODO Extended Validation Secure Server CA''. Though the chain is provided, only the single trust anchor is needed for validation. The additional intermediate certs are provided to show how to concatenate and load them.&lt;br /&gt;
&lt;br /&gt;
The PEM format means the file is a concatenation of Base64 encoded certificates with the &amp;lt;tt&amp;gt;-----BEGIN CERTIFICATE-----&amp;lt;/tt&amp;gt; prologue (and associated epilogue). If the server sends all certificates required to verify the chain (which it should), then only the ''AddTrust External CA Root'' certificate is needed.&lt;br /&gt;
&lt;br /&gt;
The options set on the &amp;lt;tt&amp;gt;CTX*&amp;lt;/tt&amp;gt; can be overridden on a per-connection basis by modifying the &amp;lt;tt&amp;gt;SSL*&amp;lt;/tt&amp;gt; using &amp;lt;tt&amp;gt;SSL_set_verify&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_set_verify_depth&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_set_options&amp;lt;/tt&amp;gt; (and friends).&lt;br /&gt;
&lt;br /&gt;
== SSL BIO ==&lt;br /&gt;
&lt;br /&gt;
The sample program uses BIOs for input and output. One BIO is used to connect to &amp;lt;tt&amp;gt;random.org&amp;lt;/tt&amp;gt;, and a second BIO is used to print output to &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_new_ssl_connect&amp;lt;/tt&amp;gt;''' creates a new BIO chain consisting of an SSL BIO (using ctx) followed by a connect BIO.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_set_conn_hostname&amp;lt;/tt&amp;gt;''' is used to set the hostname and port that will be used by the connection.&lt;br /&gt;
&lt;br /&gt;
== Options (2) ==&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_get_ssl&amp;lt;/tt&amp;gt;''' is used to fetch the '''SSL connection object''' created by &amp;lt;tt&amp;gt;BIO_new_ssl_connect&amp;lt;/tt&amp;gt;. The connection object inherits from the context object, and can override the settings on the context. The connection object is tuned with the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_set_cipher_list&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_set_tlsext_host_name&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_set_cipher_list&amp;lt;/tt&amp;gt;''' sets the cipher list. The list prefers elliptic curves, ephemeral [Diffie-Hellman], AES and SHA. It also removes NULL authentication methods and ciphers; and removes medium-security, low-security and export-grade security ciphers, such as 40-bit RC2. If desired, you could set the options on the context with &amp;lt;tt&amp;gt;SSL_CTX_set_cipher_list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_set_tlsext_host_name&amp;lt;/tt&amp;gt;''' uses the TLS SNI extension to set the hostname. If you are connecting to a Server Name Indication-aware server (such as Apache with name-based virtual hosts or IIS 8.0), then you will receive the proper certificate during the handshake.&lt;br /&gt;
&lt;br /&gt;
== Cipher Suites ==&lt;br /&gt;
&lt;br /&gt;
[[File:cipher-suites.png|thumb|right|Wireshark and ClientHello]] According to &amp;lt;tt&amp;gt;openssl ciphers ALL&amp;lt;/tt&amp;gt;, there are just over 110 cipher suites available. Each cipher suite takes 2 bytes in the &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt;, so advertising every cipher suite available at the client is going to cause a big &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt; (or bigger then needed to get the job done). When using &amp;lt;tt&amp;gt;SSL_CTX_set_cipher_list&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_set_cipher_list&amp;lt;/tt&amp;gt; with the string &amp;lt;tt&amp;gt;&amp;quot;HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4&amp;quot;&amp;lt;/tt&amp;gt;, you'll cut the number of cipher suites down to about 45. If you know the server '''does not''' support DSA, then you can add &amp;lt;tt&amp;gt;&amp;quot;!DSS&amp;quot;&amp;lt;/tt&amp;gt; and reduce the list further by about 7. And removing RSA key transport (&amp;lt;tt&amp;gt;&amp;quot;!kRSA&amp;quot;&amp;lt;/tt&amp;gt;) removes another 9 more (this is a good practice because it uses ephemeral key exchanges which provide forward secrecy). Advertising 35 or so ciphers saves about 160 bytes in the &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Better, pick 16 or 20 ciphers you want to support and advertise them. Order them so the GCM mode ciphers from TLS 1.2 are listed first, and the AES-SHA ciphers from TLS 1.0 are listed last. Though TLS 1.0 should be avoided, its probably needed for interop because only about [https://www.trustworthyinternet.org/ssl-pulse/ half the servers on the internet support TLS 1.2]. If you control the server, then it should be offering TLS 1.2 and clients only need to advertise AEAD ciphers like AES/GCM or Camellia/GCM.&lt;br /&gt;
&lt;br /&gt;
Keeping the &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt; small is important for older F5 and IronPort devices. Apparently, the devices used fixed sized buffers and choke on large &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt;'s. In fact, a &amp;quot;large hello&amp;quot; was the cause of the TLS padding bug on IronPort devices. See [http://www.ietf.org/mail-archive/web/tls/current/msg12145.html TLS padding breaks ironport] on the TLS mailing list for details.&lt;br /&gt;
&lt;br /&gt;
== Connection ==&lt;br /&gt;
&lt;br /&gt;
[[File:bio-fetch-3.png|thumb|right|Wireshark and TLS versions]] After setting the connection object options, the sample connects to the site and negotiates a secure channel.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;BIO_do_connect&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;BIO_do_handshake&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_do_connect&amp;lt;/tt&amp;gt;''' performs the name lookup for the host and standard TCP/IP three way handshake.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_do_handshake&amp;lt;/tt&amp;gt;''' performs the SSL/TLS handshake. If you set a callback with &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_set_verify&amp;lt;/tt&amp;gt;, then you callback will be invoked for each certificate in the chain used during the execution of the protocol.&lt;br /&gt;
&lt;br /&gt;
The Wireshark packet capture to the right shows the TLS handshake with the SNI extension encountered during the execution of &amp;lt;tt&amp;gt;BIO_do_handshake&amp;lt;/tt&amp;gt;. OpenSSL 1.0.1e advertises TLSv1.2 as the highest protocol level in its &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Callback ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL provides the ability for an application to interact with the chain validation by way of a callback. Normally, most application don't need to use it since the default OpenSSL behavior is usually adequate. In the callback, you can pass the &amp;lt;tt&amp;gt;preverify&amp;lt;/tt&amp;gt; result back to the library (leaving library behavior unchanged), or you can modify the result to account for a specific issue that your software should address (override default behavior). If you don't need to interact with chain validation, then don't set the callback.&lt;br /&gt;
&lt;br /&gt;
The example program returned the &amp;lt;tt&amp;gt;preverify&amp;lt;/tt&amp;gt; result to the library and just printed information about the certificate in the chain. It did so by using &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;SSL_VERIFY_PEER&amp;lt;/tt&amp;gt; and the &amp;lt;tt&amp;gt;verify_callback&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;int verify_callback(int preverify, X509_STORE_CTX* x509_ctx)&lt;br /&gt;
{&lt;br /&gt;
    int depth = X509_STORE_CTX_get_error_depth(x509_ctx);&lt;br /&gt;
    int err = X509_STORE_CTX_get_error(x509_ctx);&lt;br /&gt;
    &lt;br /&gt;
    X509* cert = X509_STORE_CTX_get_current_cert(x509_ctx);&lt;br /&gt;
    X509_NAME* iname = cert ? X509_get_issuer_name(cert) : NULL;&lt;br /&gt;
    X509_NAME* sname = cert ? X509_get_subject_name(cert) : NULL;&lt;br /&gt;
    &lt;br /&gt;
    print_cn_name(&amp;quot;Issuer (cn)&amp;quot;, iname);&lt;br /&gt;
    print_cn_name(&amp;quot;Subject (cn)&amp;quot;, sname);&lt;br /&gt;
    &lt;br /&gt;
    if(depth == 0) {&lt;br /&gt;
        /* If depth is 0, its the server's certificate. Print the SANs too */&lt;br /&gt;
        print_san_name(&amp;quot;Subject (san)&amp;quot;, cert);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return preverify;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The OpenSSL library will pass in the value of its preliminary checking of the certificate through &amp;lt;tt&amp;gt;preverify&amp;lt;/tt&amp;gt;. '''If''' you always return &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; regardless of the value of &amp;lt;tt&amp;gt;preverify&amp;lt;/tt&amp;gt; or the actual result of your processing, then &amp;lt;tt&amp;gt;SSL_get_verify_result&amp;lt;/tt&amp;gt; will always return &amp;lt;tt&amp;gt;X509_V_OK&amp;lt;/tt&amp;gt;. That's probably a bad idea for production software.&lt;br /&gt;
&lt;br /&gt;
If you don't need to perform special processing on the chain, then you should forgo the &amp;lt;tt&amp;gt;verify_callback&amp;lt;/tt&amp;gt; altogether by supplying &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verification ==&lt;br /&gt;
&lt;br /&gt;
You use one of two verification procedures, depending on the version of OpenSSL you are using. The change occurs at OpenSSL 1.1.0 because 1.1.0 (and above) implements hostname verification that 1.0.2 (and below) lacked. Painting with a broad brush, minimal checking includes: (1) confirm the server has a certificate, (2) confirm the certificate chain verifies back to a trusted root, and (3) confirm the name of the host matches a hostname listed in the server's certificate.&lt;br /&gt;
&lt;br /&gt;
In the end, its probably better to ignore PKI and just use Public Key Pinning (or Certificate Pinning) when a pre-exisiting relationship exists; or use a Perspectives-like system or a Trust-On-First-Use (TOFU) system when there's no ''a priori'' relationship (similar to SSH's &amp;lt;tt&amp;gt;StrictHostkeyChecking&amp;lt;/tt&amp;gt; option). See Peter Gutmann's [https://www.cs.auckland.ac.nz/~pgut001/pubs/book.pdf Engineering Security] for details of a security diversification strategy (Chapter 4, starting on page 292).&lt;br /&gt;
&lt;br /&gt;
You usually don't perform revocation in real time because it essentially creates a denial of service on your application. That is, your app will hang while downloading a multi-megabyte CRL or contacts a missing OCSP responder. For a detailed treatment of problems with PKI and Revocation, see Peter Gutmann's [https://www.cs.auckland.ac.nz/~pgut001/pubs/book.pdf Engineering Security] (Chapters 1 and 8).&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.0.2 ===&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.0.2 and below requires at least three checks. These versions of OpenSSL do ''not'' perform hostname validation and the API user must perform it.&lt;br /&gt;
&lt;br /&gt;
==== Server Certificate ====&lt;br /&gt;
&lt;br /&gt;
You must confirm the server provided a certificate. This is because a server might be misconfigured, or the client and server used Anonymous Diffie-Hellman. You do so as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;X509* cert = SSL_get_peer_certificate(ssl);&lt;br /&gt;
if(cert) { X509_free(cert); }&lt;br /&gt;
if(NULL == cert) handleFailure();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the server has a certificate, then &amp;lt;tt&amp;gt;SSL_get_peer_certificate&amp;lt;/tt&amp;gt; will return a non-NULL value. You don't really need the certificate, so its &amp;lt;tt&amp;gt;free&amp;lt;/tt&amp;gt;'d immediately.&lt;br /&gt;
&lt;br /&gt;
==== Certificate Chain ====&lt;br /&gt;
&lt;br /&gt;
You must confirm the server's certificate chains back to a trusted root, and all the certificates in the chain are valid. You do so as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;long res = SSL_get_verify_result(ssl);&lt;br /&gt;
if(!(X509_V_OK == res)) handleFailure();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;SSL_get_verify_result&amp;lt;/tt&amp;gt; returns the result of verifying the chain. See the earlier warning on doing the wrong thing in the verification callback.&lt;br /&gt;
&lt;br /&gt;
==== Certificate Names ====&lt;br /&gt;
&lt;br /&gt;
You must confirm a match between the hostname you contacted and the hostnames listed in the certificate. OpenSSL prior to 1.1.0 does not perform hostname verification, so you will have to perform the checking yourself. The sample code does not offer code at the moment, so you will need to borrow it or implement it.&lt;br /&gt;
&lt;br /&gt;
If you want to borrow the code, take a look at [http://curl.haxx.se/libcurl/ libcurl] and the verification procedure in source file &amp;lt;tt&amp;gt;ssluse.c&amp;lt;/tt&amp;gt;. Another source is the C/C++ Secure Coding Guide and Section 10.8, [http://etutorials.org/Programming/secure+programming/Chapter+10.+Public+Key+Infrastructure/10.8+Adding+Hostname+Checking+to+Certificate+Verification/ Adding Hostname Checking to Certificate Verification]. If you implement the code for checking, the sample code shows you how to extract the Common Name (CN) and Subject Alternate Names (SAN) from the certificate in &amp;lt;tt&amp;gt;print_cn_name&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;print_san_name&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': matching between the hostname (used in &amp;lt;tt&amp;gt;BIO_do_connect &amp;lt;/tt&amp;gt;) and names in the certificate (from &amp;lt;tt&amp;gt;SSL_get_peer_certificate&amp;lt;/tt&amp;gt;) must also be validated. For example, a certificate cannot claim to be wildcarded for &amp;lt;tt&amp;gt;*.com&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.net&amp;lt;/tt&amp;gt;, or other Top Level Domains (TLDs). In addition to the TLDs, you also have to country level or ccTLDs, so it can't match &amp;lt;tt&amp;gt;*.us&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.cn&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.fed.us&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.公司.cn&amp;lt;/tt&amp;gt; or similar levels either. Mozilla maintains a list of ccTLDs that are off limits at the [http://publicsuffix.org/ Public Suffix List], and there are currently 6136 entries on the list.&lt;br /&gt;
&lt;br /&gt;
== Program Output ==&lt;br /&gt;
&lt;br /&gt;
After all this musing, here's the lousy output you get when running the program:&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
| [[File:bio-fetch-1.png|350px|Figure 1: Chain Output]]&lt;br /&gt;
| &amp;amp;nbsp; &amp;amp;nbsp;&lt;br /&gt;
| [[File:bio-fetch-2.png|350px|Figure 2: Server Response]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Session Reuse ==&lt;br /&gt;
&lt;br /&gt;
According to Viktor Dukhovni at [http://mta.openssl.org/pipermail/openssl-users/2016-September/004564.html Possible to control session reuse from the client]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;gt; For performance testing purposes, I would like to turn off session&lt;br /&gt;
&amp;gt; reuse in the (homegrown) client I use for testing. Is there a function&lt;br /&gt;
&amp;gt; in the openssl library to do it?&lt;br /&gt;
&amp;gt; &lt;br /&gt;
&amp;gt; I tried googling for &amp;quot;openssl client don't send session id&amp;quot; but I didn't&lt;br /&gt;
&amp;gt; find anything useful.&lt;br /&gt;
&lt;br /&gt;
Just do nothing.  Client sessions are not reused unless you explicitly&lt;br /&gt;
arrange for reuse of a session by calling SSL_set_session() before&lt;br /&gt;
SSL_connect().  If you're trying to avoid wasting memory on storing&lt;br /&gt;
client-side sessions that you'll never reuse then this may help:&lt;br /&gt;
&lt;br /&gt;
   SSL_CTX_set_session_cache_mode(client_ctx, SSL_SESS_CACHE_OFF);&lt;br /&gt;
&lt;br /&gt;
but note this is also the default state, so is also not needed unless&lt;br /&gt;
some other code has explicitly enabled client-side caching of sessions.&lt;br /&gt;
&lt;br /&gt;
Only the server-side cache is enabled by default.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Session Tickets ==&lt;br /&gt;
&lt;br /&gt;
Session tickets are specified in [http://www.ietf.org/rfc/rfc5077.txt RFC 5077]. You can disable session tickets with &amp;lt;tt&amp;gt;SSL_OP_NO_TICKET&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;const long flags = SSL_OP_NO_SSLv3 | ... | SSL_OP_NO_TICKET;&lt;br /&gt;
SSL_CTX_set_options(ctx, flags);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 0-RTT ==&lt;br /&gt;
&lt;br /&gt;
0-RTT is specified in XXX (TODO). 0-RTT allows an application to immediately resume a previous session at the expense of consuming unauthenticated data. You should avoid 0-RTT if possible. In fact, an organization's data security policy may not allow it for some higher data sensitivity levels.&lt;br /&gt;
&lt;br /&gt;
Care should be taken if enabling 0-RTT at the client because a number of protections must be enabled at the server. Additionally, some of the protections are required higher up in the stack, outside of the secure socket layer. Below is a list of potential problems from [http://www.ietf.org/mail-archive/web/tls/current/msg15594.html 0-RTT and Anti-Replay] and [http://www.ietf.org/mail-archive/web/tls/current/msg23561.html Closing on 0-RTT] on the IETF TLS working group mailing list.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT without stateful anti-replay allows for very high number of replays, breaking rate limiting systems, even high-performance ones, resulting in an opening for DDoS attacks.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT without stateful anti-replay allows for very high number of replays, allowing exploiting timing side channels for information leakage. Very few if any applications are engineered to mitigate or eliminate such side channels.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT without global anti-replay allows leaking information from the 0-RTT data via cache timing attacks. HTTP GET URLs sent to CDNs are especially vulnerable.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT without global anti-replay allows non-idempotent actions contained in 0-RTT data to be repeated potentially lots of times. Abuse of HTTP GET for non-idempotent actions is fairly common.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT allows easily reordering request with re-transmission from the client. This can lead to various unexpected application behavior if possibility of such reordering is not taken into account. &amp;quot;Eventually consistent&amp;quot; datastores are especially vulnerable.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT exporters are not safe for authentication unless the server does global anti-replay on 0-RTT.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
[[Media:openssl-bio-fetch.tar.gz|openssl-bio-fetch.tar.gz]] - The program and Makefile used for this wiki page.&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=SSL/TLS_Client&amp;diff=3208</id>
		<title>SSL/TLS Client</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=SSL/TLS_Client&amp;diff=3208"/>
		<updated>2022-04-24T23:58:59Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info about demos/sslecho to introduction.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SSL/TLS Client]] is sample code for a basic web client that fetches a page. The code shown below omits error checking for brevity, but the sample available for download performs the error checking.&lt;br /&gt;
&lt;br /&gt;
The sample code will set up &amp;lt;tt&amp;gt;BIO&amp;lt;/tt&amp;gt; to fet a page from &amp;lt;tt&amp;gt;www.random.org&amp;lt;/tt&amp;gt;. The code uses TLS (not SSL) and utilizes the Server Name Indication (SNI) extension from [http://tools.ietf.org/rfc/rfc3546.txt RFC 3546, Transport Layer Security (TLS) Extensions].&lt;br /&gt;
&lt;br /&gt;
If you need features beyond the example below, then you should examine &amp;lt;tt&amp;gt;s_client.c&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;apps/&amp;lt;/tt&amp;gt; directory of the OpenSSL distribution. OpenSSL's &amp;lt;tt&amp;gt;s_client&amp;lt;/tt&amp;gt; implements nearly every client side feature available from the library.&lt;br /&gt;
&lt;br /&gt;
The code below does '''not''' perform hostname verification. OpenSSL prior to 1.1.0 does not perform the check, and you must perform the check yourself. The OpenSSL [http://www.openssl.org/news/changelog.html Change Log] for OpenSSL 1.1.0 states you can use &amp;lt;tt&amp;gt;-verify_name&amp;lt;/tt&amp;gt; option, and &amp;lt;tt&amp;gt;apps.c&amp;lt;/tt&amp;gt; offers &amp;lt;tt&amp;gt;-verify_hostname&amp;lt;/tt&amp;gt;. But &amp;lt;tt&amp;gt;s_client&amp;lt;/tt&amp;gt; does not respond to either switch, so its unclear how hostname checking will be implemented or invoked for a client. '''Note (N.B.)''': hostname verification is marked as experimental, so switches, options, and implementations could change.&lt;br /&gt;
&lt;br /&gt;
If you are looking for guidance on which protocols and ciphers you should be using, then see Adam Langley's blog [http://www.imperialviolet.org/2014/12/08/poodleagain.html The POODLE bites again]. The short version: use only TLS 1.2, use only ephemeral key exchanges, and use only AEAD ciphers (like AES/GCM, Camellia/GCM, ChaCha/Poly1305).&lt;br /&gt;
&lt;br /&gt;
An example of a TLS client written by the developer team can be found in the source code at demos/sslecho.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
&lt;br /&gt;
The code below demonstrates a basic client that uses BIOs and TLS to connect to &amp;lt;tt&amp;gt;www.random.org&amp;lt;/tt&amp;gt;, and fetches 32 bytes of random data through an HTTP request. The sample code is available for download below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define HOST_NAME &amp;quot;www.random.org&amp;quot;&lt;br /&gt;
#define HOST_PORT &amp;quot;443&amp;quot;&lt;br /&gt;
#define HOST_RESOURCE &amp;quot;/cgi-bin/randbyte?nbytes=32&amp;amp;format=h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
long res = 1;&lt;br /&gt;
&lt;br /&gt;
SSL_CTX* ctx = NULL;&lt;br /&gt;
BIO *web = NULL, *out = NULL;&lt;br /&gt;
SSL *ssl = NULL;&lt;br /&gt;
&lt;br /&gt;
init_openssl_library();&lt;br /&gt;
&lt;br /&gt;
const SSL_METHOD* method = SSLv23_method();&lt;br /&gt;
if(!(NULL != method)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
ctx = SSL_CTX_new(method);&lt;br /&gt;
if(!(ctx != NULL)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* Cannot fail ??? */&lt;br /&gt;
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);&lt;br /&gt;
&lt;br /&gt;
/* Cannot fail ??? */&lt;br /&gt;
SSL_CTX_set_verify_depth(ctx, 4);&lt;br /&gt;
&lt;br /&gt;
/* Cannot fail ??? */&lt;br /&gt;
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;&lt;br /&gt;
SSL_CTX_set_options(ctx, flags);&lt;br /&gt;
&lt;br /&gt;
res = SSL_CTX_load_verify_locations(ctx, &amp;quot;random-org-chain.pem&amp;quot;, NULL);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
web = BIO_new_ssl_connect(ctx);&lt;br /&gt;
if(!(web != NULL)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
res = BIO_set_conn_hostname(web, HOST_NAME &amp;quot;:&amp;quot; HOST_PORT);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
BIO_get_ssl(web, &amp;amp;ssl);&lt;br /&gt;
if(!(ssl != NULL)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
const char* const PREFERRED_CIPHERS = &amp;quot;HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4&amp;quot;;&lt;br /&gt;
res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
res = SSL_set_tlsext_host_name(ssl, HOST_NAME);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
out = BIO_new_fp(stdout, BIO_NOCLOSE);&lt;br /&gt;
if(!(NULL != out)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
res = BIO_do_connect(web);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
res = BIO_do_handshake(web);&lt;br /&gt;
if(!(1 == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* Step 1: verify a server certificate was presented during the negotiation */&lt;br /&gt;
X509* cert = SSL_get_peer_certificate(ssl);&lt;br /&gt;
if(cert) { X509_free(cert); } /* Free immediately */&lt;br /&gt;
if(NULL == cert) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* Step 2: verify the result of chain verification */&lt;br /&gt;
/* Verification performed according to RFC 4158    */&lt;br /&gt;
res = SSL_get_verify_result(ssl);&lt;br /&gt;
if(!(X509_V_OK == res)) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* Step 3: hostname verification */&lt;br /&gt;
/* An exercise left to the reader */&lt;br /&gt;
&lt;br /&gt;
BIO_puts(web, &amp;quot;GET &amp;quot; HOST_RESOURCE &amp;quot; HTTP/1.1\r\n&amp;quot;&lt;br /&gt;
              &amp;quot;Host: &amp;quot; HOST_NAME &amp;quot;\r\n&amp;quot;&lt;br /&gt;
              &amp;quot;Connection: close\r\n\r\n&amp;quot;);&lt;br /&gt;
BIO_puts(out, &amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
int len = 0;&lt;br /&gt;
do&lt;br /&gt;
{&lt;br /&gt;
  char buff[1536] = {};&lt;br /&gt;
  len = BIO_read(web, buff, sizeof(buff));&lt;br /&gt;
            &lt;br /&gt;
  if(len &amp;gt; 0)&lt;br /&gt;
    BIO_write(out, buff, len);&lt;br /&gt;
&lt;br /&gt;
} while (len &amp;gt; 0 || BIO_should_retry(web));&lt;br /&gt;
&lt;br /&gt;
if(out)&lt;br /&gt;
  BIO_free(out);&lt;br /&gt;
&lt;br /&gt;
if(web != NULL)&lt;br /&gt;
  BIO_free_all(web);&lt;br /&gt;
&lt;br /&gt;
if(NULL != ctx)&lt;br /&gt;
  SSL_CTX_free(ctx);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
The sample program initializes the OpenSSL library with &amp;lt;tt&amp;gt;init_openssl_library&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;init_openssl_library&amp;lt;/tt&amp;gt; calls three OpenSSL functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#if (SSLEAY_VERSION_NUMBER &amp;gt;= 0x0907000L)&lt;br /&gt;
# include &amp;lt;openssl/conf.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
void init_openssl_library(void)&lt;br /&gt;
{&lt;br /&gt;
  (void)SSL_library_init();&lt;br /&gt;
&lt;br /&gt;
  SSL_load_error_strings();&lt;br /&gt;
&lt;br /&gt;
  /* ERR_load_crypto_strings(); */&lt;br /&gt;
  &lt;br /&gt;
  OPENSSL_config(NULL);&lt;br /&gt;
    &lt;br /&gt;
  /* Include &amp;lt;openssl/opensslconf.h&amp;gt; to get this define */&lt;br /&gt;
#if defined (OPENSSL_THREADS)&lt;br /&gt;
  fprintf(stdout, &amp;quot;Warning: thread locking is not implemented\n&amp;quot;);&lt;br /&gt;
#endif&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;''' performs initialization of &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;, and loads required algorithms. The documents state &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; always returns &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;, so its a useless return value.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_load_error_strings&amp;lt;/tt&amp;gt;''' loads error strings from both &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. There's no need to call &amp;lt;tt&amp;gt;ERR_load_crypto_strings&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;OpenSSL_add_ssl_algorithms&amp;lt;/tt&amp;gt;''' is a &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;, so the call is omitted.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt;''' may (or may not) be needed. Internally, &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; is called based on a configuration options via &amp;lt;tt&amp;gt;OPENSSL_LOAD_CONF&amp;lt;/tt&amp;gt;. If you are dynamically loading an engine specified in &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt;, then you might need it so you should call it. That is, don't depend upon the OpenSSL library to call it for you.&lt;br /&gt;
&lt;br /&gt;
If you are building a multi-threaded client, you should set the locking callbacks. See [https://www.openssl.org/docs/crypto/threads.html threads(3)] for details.&lt;br /&gt;
&lt;br /&gt;
A detailed treatment of initialization can be found at [[Library Initialization]].&lt;br /&gt;
&lt;br /&gt;
== Context Setup ==&lt;br /&gt;
&lt;br /&gt;
The sample program uses '''&amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt;''' to create a context. '''&amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt;''' specifies that version negotiation will be used. Do not be confused by the name (it does NOT mean that only SSLv2 or SSLv3 will be used). The name is like that for historical reasons, and the function has been renamed to '''&amp;lt;tt&amp;gt;TLS_method&amp;lt;/tt&amp;gt;''' in the forthcoming OpenSSL version 1.1.0. Using this method will negotiate the highest protocol version supported by both the server and the client. SSL/TLS versions currently supported by OpenSSL 1.0.2 are SSLv2, SSLv3, TLS1.0, TLS1.1 and TLS1.2.&lt;br /&gt;
&lt;br /&gt;
The actual SSL and TLS protocols are further tuned through options. By using &amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt; (and removing the unwanted protocol versions with &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv2&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv3&amp;lt;/tt&amp;gt;), then you will effectively use TLS v1.0 and above, including TLS v1.2. You can also use &amp;lt;tt&amp;gt;SSL_OP_NO_TLSv1&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_OP_NO_TLSv1_1&amp;lt;/tt&amp;gt; if you want to use the TLS 1.2 protocol only.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_new&amp;lt;/tt&amp;gt;''' uses the &amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt; method to create a new '''SSL/TLS context object'''. If you use, for example &amp;lt;tt&amp;gt;TLSv1_method&amp;lt;/tt&amp;gt;, then you will only use TLS v1.0, and if you use &amp;lt;tt&amp;gt;TLSv1_1_method&amp;lt;/tt&amp;gt; then you will only use TLS v1.1. Typically you should always use '''&amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt;''' in preference to the version specific methods.&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 improves protocol selection by providing &amp;lt;tt&amp;gt;SSL_CTX_set_max_proto_version()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_CTX_set_min_proto_version()&amp;lt;/tt&amp;gt;. You no longer need to subtract unwanted options with &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv2&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv3&amp;lt;/tt&amp;gt;. Also see the [http://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_max_proto_version.html &amp;lt;tt&amp;gt;SSL_CTX_set_max_proto_version()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_CTX_set_min_proto_version()&amp;lt;/tt&amp;gt; man pages].&lt;br /&gt;
&lt;br /&gt;
== Options (1) ==&lt;br /&gt;
&lt;br /&gt;
After creating a context with &amp;lt;tt&amp;gt;SSLv23_method&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_CTX_new&amp;lt;/tt&amp;gt;, the context object is tuned with the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_CTX_set_verify_depth&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_CTX_set_options&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_CTX_load_verify_locations&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt;''' sets the &amp;lt;tt&amp;gt;SSL_VERIFY_PEER&amp;lt;/tt&amp;gt; flag and the verify callback. This ensures the chain is verified according to [http://tools.ietf.org/html/rfc4158 RFC 4158] and Issuer and Subject information can be printed. If you don't want to perform custom processing (such as printing or checking), then don't set the callback. OpenSSL's default checking should be sufficient, so pass &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There is also a &amp;lt;tt&amp;gt;SSL_VERIFY_FAIL_IF_NO_PEER_CERT&amp;lt;/tt&amp;gt; flag, but it is used for servers and has no effect on clients. If you accidentally use &amp;lt;tt&amp;gt;SSL_VERIFY_FAIL_IF_NO_PEER_CERT&amp;lt;/tt&amp;gt;, then you chain will always verify when call &amp;lt;tt&amp;gt;SSL_get_verify_result&amp;lt;/tt&amp;gt; because the flag is ignored for clients (essentially, 0 is passed for the flag which performs no verification).&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_set_verify_depth&amp;lt;/tt&amp;gt;''' sets the chain depth to 4. Chain depth is fairly useless in practice.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_set_options&amp;lt;/tt&amp;gt;''' set the &amp;lt;tt&amp;gt;SSL_OP_ALL&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv2&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_OP_NO_SSLv3&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_OP_NO_COMPRESSION&amp;lt;/tt&amp;gt; options. In essence, it takes all the bug fixes and work arounds for the various servers, removes the SSL protocols (leaving only TLS protocols), and removes compression. The remaining TLS protocols are TLS 1.0, TLS 1.1, and TLS 1.2.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_CTX_load_verify_locations&amp;lt;/tt&amp;gt;''' loads the certificate chain for the &amp;lt;tt&amp;gt;random.org&amp;lt;/tt&amp;gt; site. The site's CA is Comodo, and the chain includes ''AddTrust External CA Root'', ''COMODO Certification Authority'', and ''COMODO Extended Validation Secure Server CA''. Though the chain is provided, only the single trust anchor is needed for validation. The additional intermediate certs are provided to show how to concatenate and load them.&lt;br /&gt;
&lt;br /&gt;
The PEM format means the file is a concatenation of Base64 encoded certificates with the &amp;lt;tt&amp;gt;-----BEGIN CERTIFICATE-----&amp;lt;/tt&amp;gt; prologue (and associated epilogue). If the server sends all certificates required to verify the chain (which it should), then only the ''AddTrust External CA Root'' certificate is needed.&lt;br /&gt;
&lt;br /&gt;
The options set on the &amp;lt;tt&amp;gt;CTX*&amp;lt;/tt&amp;gt; can be overridden on a per-connection basis by modifying the &amp;lt;tt&amp;gt;SSL*&amp;lt;/tt&amp;gt; using &amp;lt;tt&amp;gt;SSL_set_verify&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_set_verify_depth&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_set_options&amp;lt;/tt&amp;gt; (and friends).&lt;br /&gt;
&lt;br /&gt;
== SSL BIO ==&lt;br /&gt;
&lt;br /&gt;
The sample program uses BIOs for input and output. One BIO is used to connect to &amp;lt;tt&amp;gt;random.org&amp;lt;/tt&amp;gt;, and a second BIO is used to print output to &amp;lt;tt&amp;gt;stdout&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_new_ssl_connect&amp;lt;/tt&amp;gt;''' creates a new BIO chain consisting of an SSL BIO (using ctx) followed by a connect BIO.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_set_conn_hostname&amp;lt;/tt&amp;gt;''' is used to set the hostname and port that will be used by the connection.&lt;br /&gt;
&lt;br /&gt;
== Options (2) ==&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_get_ssl&amp;lt;/tt&amp;gt;''' is used to fetch the '''SSL connection object''' created by &amp;lt;tt&amp;gt;BIO_new_ssl_connect&amp;lt;/tt&amp;gt;. The connection object inherits from the context object, and can override the settings on the context. The connection object is tuned with the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_set_cipher_list&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SSL_set_tlsext_host_name&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_set_cipher_list&amp;lt;/tt&amp;gt;''' sets the cipher list. The list prefers elliptic curves, ephemeral [Diffie-Hellman], AES and SHA. It also removes NULL authentication methods and ciphers; and removes medium-security, low-security and export-grade security ciphers, such as 40-bit RC2. If desired, you could set the options on the context with &amp;lt;tt&amp;gt;SSL_CTX_set_cipher_list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;SSL_set_tlsext_host_name&amp;lt;/tt&amp;gt;''' uses the TLS SNI extension to set the hostname. If you are connecting to a Server Name Indication-aware server (such as Apache with name-based virtual hosts or IIS 8.0), then you will receive the proper certificate during the handshake.&lt;br /&gt;
&lt;br /&gt;
== Cipher Suites ==&lt;br /&gt;
&lt;br /&gt;
[[File:cipher-suites.png|thumb|right|Wireshark and ClientHello]] According to &amp;lt;tt&amp;gt;openssl ciphers ALL&amp;lt;/tt&amp;gt;, there are just over 110 cipher suites available. Each cipher suite takes 2 bytes in the &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt;, so advertising every cipher suite available at the client is going to cause a big &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt; (or bigger then needed to get the job done). When using &amp;lt;tt&amp;gt;SSL_CTX_set_cipher_list&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_set_cipher_list&amp;lt;/tt&amp;gt; with the string &amp;lt;tt&amp;gt;&amp;quot;HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4&amp;quot;&amp;lt;/tt&amp;gt;, you'll cut the number of cipher suites down to about 45. If you know the server '''does not''' support DSA, then you can add &amp;lt;tt&amp;gt;&amp;quot;!DSS&amp;quot;&amp;lt;/tt&amp;gt; and reduce the list further by about 7. And removing RSA key transport (&amp;lt;tt&amp;gt;&amp;quot;!kRSA&amp;quot;&amp;lt;/tt&amp;gt;) removes another 9 more (this is a good practice because it uses ephemeral key exchanges which provide forward secrecy). Advertising 35 or so ciphers saves about 160 bytes in the &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Better, pick 16 or 20 ciphers you want to support and advertise them. Order them so the GCM mode ciphers from TLS 1.2 are listed first, and the AES-SHA ciphers from TLS 1.0 are listed last. Though TLS 1.0 should be avoided, its probably needed for interop because only about [https://www.trustworthyinternet.org/ssl-pulse/ half the servers on the internet support TLS 1.2]. If you control the server, then it should be offering TLS 1.2 and clients only need to advertise AEAD ciphers like AES/GCM or Camellia/GCM.&lt;br /&gt;
&lt;br /&gt;
Keeping the &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt; small is important for older F5 and IronPort devices. Apparently, the devices used fixed sized buffers and choke on large &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt;'s. In fact, a &amp;quot;large hello&amp;quot; was the cause of the TLS padding bug on IronPort devices. See [http://www.ietf.org/mail-archive/web/tls/current/msg12145.html TLS padding breaks ironport] on the TLS mailing list for details.&lt;br /&gt;
&lt;br /&gt;
== Connection ==&lt;br /&gt;
&lt;br /&gt;
[[File:bio-fetch-3.png|thumb|right|Wireshark and TLS versions]] After setting the connection object options, the sample connects to the site and negotiates a secure channel.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;BIO_do_connect&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;BIO_do_handshake&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_do_connect&amp;lt;/tt&amp;gt;''' performs the name lookup for the host and standard TCP/IP three way handshake.&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;tt&amp;gt;BIO_do_handshake&amp;lt;/tt&amp;gt;''' performs the SSL/TLS handshake. If you set a callback with &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_set_verify&amp;lt;/tt&amp;gt;, then you callback will be invoked for each certificate in the chain used during the execution of the protocol.&lt;br /&gt;
&lt;br /&gt;
The Wireshark packet capture to the right shows the TLS handshake with the SNI extension encountered during the execution of &amp;lt;tt&amp;gt;BIO_do_handshake&amp;lt;/tt&amp;gt;. OpenSSL 1.0.1e advertises TLSv1.2 as the highest protocol level in its &amp;lt;tt&amp;gt;ClientHello&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Callback ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL provides the ability for an application to interact with the chain validation by way of a callback. Normally, most application don't need to use it since the default OpenSSL behavior is usually adequate. In the callback, you can pass the &amp;lt;tt&amp;gt;preverify&amp;lt;/tt&amp;gt; result back to the library (leaving library behavior unchanged), or you can modify the result to account for a specific issue that your software should address (override default behavior). If you don't need to interact with chain validation, then don't set the callback.&lt;br /&gt;
&lt;br /&gt;
The example program returned the &amp;lt;tt&amp;gt;preverify&amp;lt;/tt&amp;gt; result to the library and just printed information about the certificate in the chain. It did so by using &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;SSL_VERIFY_PEER&amp;lt;/tt&amp;gt; and the &amp;lt;tt&amp;gt;verify_callback&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;int verify_callback(int preverify, X509_STORE_CTX* x509_ctx)&lt;br /&gt;
{&lt;br /&gt;
    int depth = X509_STORE_CTX_get_error_depth(x509_ctx);&lt;br /&gt;
    int err = X509_STORE_CTX_get_error(x509_ctx);&lt;br /&gt;
    &lt;br /&gt;
    X509* cert = X509_STORE_CTX_get_current_cert(x509_ctx);&lt;br /&gt;
    X509_NAME* iname = cert ? X509_get_issuer_name(cert) : NULL;&lt;br /&gt;
    X509_NAME* sname = cert ? X509_get_subject_name(cert) : NULL;&lt;br /&gt;
    &lt;br /&gt;
    print_cn_name(&amp;quot;Issuer (cn)&amp;quot;, iname);&lt;br /&gt;
    print_cn_name(&amp;quot;Subject (cn)&amp;quot;, sname);&lt;br /&gt;
    &lt;br /&gt;
    if(depth == 0) {&lt;br /&gt;
        /* If depth is 0, its the server's certificate. Print the SANs too */&lt;br /&gt;
        print_san_name(&amp;quot;Subject (san)&amp;quot;, cert);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return preverify;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The OpenSSL library will pass in the value of its preliminary checking of the certificate through &amp;lt;tt&amp;gt;preverify&amp;lt;/tt&amp;gt;. '''If''' you always return &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; regardless of the value of &amp;lt;tt&amp;gt;preverify&amp;lt;/tt&amp;gt; or the actual result of your processing, then &amp;lt;tt&amp;gt;SSL_get_verify_result&amp;lt;/tt&amp;gt; will always return &amp;lt;tt&amp;gt;X509_V_OK&amp;lt;/tt&amp;gt;. That's probably a bad idea for production software.&lt;br /&gt;
&lt;br /&gt;
If you don't need to perform special processing on the chain, then you should forgo the &amp;lt;tt&amp;gt;verify_callback&amp;lt;/tt&amp;gt; altogether by supplying &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;SSL_CTX_set_verify&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verification ==&lt;br /&gt;
&lt;br /&gt;
You use one of two verification procedures, depending on the version of OpenSSL you are using. The change occurs at OpenSSL 1.1.0 because 1.1.0 (and above) implements hostname verification that 1.0.2 (and below) lacked. Painting with a broad brush, minimal checking includes: (1) confirm the server has a certificate, (2) confirm the certificate chain verifies back to a trusted root, and (3) confirm the name of the host matches a hostname listed in the server's certificate.&lt;br /&gt;
&lt;br /&gt;
In the end, its probably better to ignore PKI and just use Public Key Pinning (or Certificate Pinning) when a pre-exisiting relationship exists; or use a Perspectives-like system or a Trust-On-First-Use (TOFU) system when there's no ''a priori'' relationship (similar to SSH's &amp;lt;tt&amp;gt;StrictHostkeyChecking&amp;lt;/tt&amp;gt; option). See Peter Gutmann's [https://www.cs.auckland.ac.nz/~pgut001/pubs/book.pdf Engineering Security] for details of a security diversification strategy (Chapter 4, starting on page 292).&lt;br /&gt;
&lt;br /&gt;
You usually don't perform revocation in real time because it essentially creates a denial of service on your application. That is, your app will hang while downloading a multi-megabyte CRL or contacts a missing OCSP responder. For a detailed treatment of problems with PKI and Revocation, see Peter Gutmann's [https://www.cs.auckland.ac.nz/~pgut001/pubs/book.pdf Engineering Security] (Chapters 1 and 8).&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.0.2 ===&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.0.2 and below requires at least three checks. These versions of OpenSSL do ''not'' perform hostname validation and the API user must perform it.&lt;br /&gt;
&lt;br /&gt;
==== Server Certificate ====&lt;br /&gt;
&lt;br /&gt;
You must confirm the server provided a certificate. This is because a server might be misconfigured, or the client and server used Anonymous Diffie-Hellman. You do so as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;X509* cert = SSL_get_peer_certificate(ssl);&lt;br /&gt;
if(cert) { X509_free(cert); }&lt;br /&gt;
if(NULL == cert) handleFailure();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the server has a certificate, then &amp;lt;tt&amp;gt;SSL_get_peer_certificate&amp;lt;/tt&amp;gt; will return a non-NULL value. You don't really need the certificate, so its &amp;lt;tt&amp;gt;free&amp;lt;/tt&amp;gt;'d immediately.&lt;br /&gt;
&lt;br /&gt;
==== Certificate Chain ====&lt;br /&gt;
&lt;br /&gt;
You must confirm the server's certificate chains back to a trusted root, and all the certificates in the chain are valid. You do so as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;long res = SSL_get_verify_result(ssl);&lt;br /&gt;
if(!(X509_V_OK == res)) handleFailure();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;SSL_get_verify_result&amp;lt;/tt&amp;gt; returns the result of verifying the chain. See the earlier warning on doing the wrong thing in the verification callback.&lt;br /&gt;
&lt;br /&gt;
==== Certificate Names ====&lt;br /&gt;
&lt;br /&gt;
You must confirm a match between the hostname you contacted and the hostnames listed in the certificate. OpenSSL prior to 1.1.0 does not perform hostname verification, so you will have to perform the checking yourself. The sample code does not offer code at the moment, so you will need to borrow it or implement it.&lt;br /&gt;
&lt;br /&gt;
If you want to borrow the code, take a look at [http://curl.haxx.se/libcurl/ libcurl] and the verification procedure in source file &amp;lt;tt&amp;gt;ssluse.c&amp;lt;/tt&amp;gt;. Another source is the C/C++ Secure Coding Guide and Section 10.8, [http://etutorials.org/Programming/secure+programming/Chapter+10.+Public+Key+Infrastructure/10.8+Adding+Hostname+Checking+to+Certificate+Verification/ Adding Hostname Checking to Certificate Verification]. If you implement the code for checking, the sample code shows you how to extract the Common Name (CN) and Subject Alternate Names (SAN) from the certificate in &amp;lt;tt&amp;gt;print_cn_name&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;print_san_name&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': matching between the hostname (used in &amp;lt;tt&amp;gt;BIO_do_connect &amp;lt;/tt&amp;gt;) and names in the certificate (from &amp;lt;tt&amp;gt;SSL_get_peer_certificate&amp;lt;/tt&amp;gt;) must also be validated. For example, a certificate cannot claim to be wildcarded for &amp;lt;tt&amp;gt;*.com&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.net&amp;lt;/tt&amp;gt;, or other Top Level Domains (TLDs). In addition to the TLDs, you also have to country level or ccTLDs, so it can't match &amp;lt;tt&amp;gt;*.us&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.cn&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.fed.us&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.公司.cn&amp;lt;/tt&amp;gt; or similar levels either. Mozilla maintains a list of ccTLDs that are off limits at the [http://publicsuffix.org/ Public Suffix List], and there are currently 6136 entries on the list.&lt;br /&gt;
&lt;br /&gt;
== Program Output ==&lt;br /&gt;
&lt;br /&gt;
After all this musing, here's the lousy output you get when running the program:&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
| [[File:bio-fetch-1.png|350px|Figure 1: Chain Output]]&lt;br /&gt;
| &amp;amp;nbsp; &amp;amp;nbsp;&lt;br /&gt;
| [[File:bio-fetch-2.png|350px|Figure 2: Server Response]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Session Reuse ==&lt;br /&gt;
&lt;br /&gt;
According to Viktor Dukhovni at [http://mta.openssl.org/pipermail/openssl-users/2016-September/004564.html Possible to control session reuse from the client]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;gt; For performance testing purposes, I would like to turn off session&lt;br /&gt;
&amp;gt; reuse in the (homegrown) client I use for testing. Is there a function&lt;br /&gt;
&amp;gt; in the openssl library to do it?&lt;br /&gt;
&amp;gt; &lt;br /&gt;
&amp;gt; I tried googling for &amp;quot;openssl client don't send session id&amp;quot; but I didn't&lt;br /&gt;
&amp;gt; find anything useful.&lt;br /&gt;
&lt;br /&gt;
Just do nothing.  Client sessions are not reused unless you explicitly&lt;br /&gt;
arrange for reuse of a session by calling SSL_set_session() before&lt;br /&gt;
SSL_connect().  If you're trying to avoid wasting memory on storing&lt;br /&gt;
client-side sessions that you'll never reuse then this may help:&lt;br /&gt;
&lt;br /&gt;
   SSL_CTX_set_session_cache_mode(client_ctx, SSL_SESS_CACHE_OFF);&lt;br /&gt;
&lt;br /&gt;
but note this is also the default state, so is also not needed unless&lt;br /&gt;
some other code has explicitly enabled client-side caching of sessions.&lt;br /&gt;
&lt;br /&gt;
Only the server-side cache is enabled by default.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Session Tickets ==&lt;br /&gt;
&lt;br /&gt;
Session tickets are specified in [http://www.ietf.org/rfc/rfc5077.txt RFC 5077]. You can disable session tickets with &amp;lt;tt&amp;gt;SSL_OP_NO_TICKET&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;const long flags = SSL_OP_NO_SSLv3 | ... | SSL_OP_NO_TICKET;&lt;br /&gt;
SSL_CTX_set_options(ctx, flags);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 0-RTT ==&lt;br /&gt;
&lt;br /&gt;
0-RTT is specified in XXX (TODO). 0-RTT allows an application to immediately resume a previous session at the expense of consuming unauthenticated data. You should avoid 0-RTT if possible. In fact, an organization's data security policy may not allow it for some higher data sensitivity levels.&lt;br /&gt;
&lt;br /&gt;
Care should be taken if enabling 0-RTT at the client because a number of protections must be enabled at the server. Additionally, some of the protections are required higher up in the stack, outside of the secure socket layer. Below is a list of potential problems from [http://www.ietf.org/mail-archive/web/tls/current/msg15594.html 0-RTT and Anti-Replay] and [http://www.ietf.org/mail-archive/web/tls/current/msg23561.html Closing on 0-RTT] on the IETF TLS working group mailing list.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT without stateful anti-replay allows for very high number of replays, breaking rate limiting systems, even high-performance ones, resulting in an opening for DDoS attacks.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT without stateful anti-replay allows for very high number of replays, allowing exploiting timing side channels for information leakage. Very few if any applications are engineered to mitigate or eliminate such side channels.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT without global anti-replay allows leaking information from the 0-RTT data via cache timing attacks. HTTP GET URLs sent to CDNs are especially vulnerable.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT without global anti-replay allows non-idempotent actions contained in 0-RTT data to be repeated potentially lots of times. Abuse of HTTP GET for non-idempotent actions is fairly common.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT allows easily reordering request with re-transmission from the client. This can lead to various unexpected application behavior if possibility of such reordering is not taken into account. &amp;quot;Eventually consistent&amp;quot; datastores are especially vulnerable.&lt;br /&gt;
&lt;br /&gt;
* 0-RTT exporters are not safe for authentication unless the server does global anti-replay on 0-RTT.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
[[Media:openssl-bio-fetch.tar.gz|openssl-bio-fetch.tar.gz]] - The program and Makefile used for this wiki page.&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Simple_TLS_Client&amp;diff=3202</id>
		<title>Talk:Simple TLS Client</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Simple_TLS_Client&amp;diff=3202"/>
		<updated>2022-04-24T18:50:51Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Created page with &amp;quot;This page should probably redirect to SSL/TLS Client.  If you want to direct people to OpenSSL's demo code, then mention it on the SSL/TLS Client page.  ~~~~&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page should probably redirect to [[SSL/TLS Client]].&lt;br /&gt;
&lt;br /&gt;
If you want to direct people to OpenSSL's demo code, then mention it on the SSL/TLS Client page.&lt;br /&gt;
&lt;br /&gt;
[[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 18:50, 24 April 2022 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Message_Digests&amp;diff=3197</id>
		<title>EVP Message Digests</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Message_Digests&amp;diff=3197"/>
		<updated>2022-01-12T01:51:21Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on EVP_MD_CTX_create and EVP_MD_CTX_destroy from OpenSSL 1.0.2.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DocInclude&lt;br /&gt;
|Name=Message Digests&lt;br /&gt;
|Url=http://wiki.openssl.org/index.php/Manual:Evp(3)&lt;br /&gt;
|Include=evp.h}}&lt;br /&gt;
&lt;br /&gt;
A Message Digest or Hash Function takes any arbitrary message (with any content or length) as an input and provides a fixed size hash value as a result. Specifically the function exhibits the following properties:&lt;br /&gt;
* It is simple to create a hash value for any given message&lt;br /&gt;
* It is computationally infeasible to calculate a message from any given hash (i.e. the function is one-way)&lt;br /&gt;
* It is infeasible to modify a message without also modifying the hash value&lt;br /&gt;
* It is infeasible to find two messages that result in the same hash&lt;br /&gt;
&lt;br /&gt;
The OpenSSL library supports a wide number of different hash functions including the popular [[:Category:SHA-2]] set of hash functions (i.e. [[SHA-224]], [[SHA-256]], [[SHA-384]] and [[SHA-512]]).&lt;br /&gt;
&lt;br /&gt;
==An Example use of a Hash Function==&lt;br /&gt;
&lt;br /&gt;
Using an OpenSSL message digest/hash function, consists of the following steps:&lt;br /&gt;
* Create a Message Digest context&lt;br /&gt;
* Initialise the context by identifying the algorithm to be used (built-in algorithms are defined in &amp;lt;code&amp;gt;evp.h&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Provide the message whose digest needs to be calculated. Messages can be divided into sections and provided over a number of calls to the library if necessary&lt;br /&gt;
* Caclulate the digest&lt;br /&gt;
* Clean up the context if no longer required&lt;br /&gt;
&lt;br /&gt;
Message digest algorithms are identified using an EVP_MD object. These are built-in to the library and obtained through appropriate library calls (e.g. such as EVP_sha256() or EVP_sha512()).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void digest_message(const unsigned char *message, size_t message_len, unsigned char **digest, unsigned int *digest_len)&lt;br /&gt;
{&lt;br /&gt;
	EVP_MD_CTX *mdctx;&lt;br /&gt;
&lt;br /&gt;
	if((mdctx = EVP_MD_CTX_new()) == NULL)&lt;br /&gt;
		handleErrors();&lt;br /&gt;
&lt;br /&gt;
	if(1 != EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL))&lt;br /&gt;
		handleErrors();&lt;br /&gt;
&lt;br /&gt;
	if(1 != EVP_DigestUpdate(mdctx, message, message_len))&lt;br /&gt;
		handleErrors();&lt;br /&gt;
&lt;br /&gt;
	if((*digest = (unsigned char *)OPENSSL_malloc(EVP_MD_size(EVP_sha256()))) == NULL)&lt;br /&gt;
		handleErrors();&lt;br /&gt;
&lt;br /&gt;
	if(1 != EVP_DigestFinal_ex(mdctx, *digest, digest_len))&lt;br /&gt;
		handleErrors();&lt;br /&gt;
&lt;br /&gt;
	EVP_MD_CTX_free(mdctx);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need to support both OpenSSL 1.0.x and OpenSSL 1.1.x, then use a &amp;lt;tt&amp;gt;define&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;EVP_MD_CTX_new&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;EVP_MD_CTX_free&amp;lt;/tt&amp;gt; as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#if OPENSSL_VERSION_NUMBER &amp;lt; 0x10100000L&lt;br /&gt;
#  define EVP_MD_CTX_new   EVP_MD_CTX_create&lt;br /&gt;
#  define EVP_MD_CTX_free  EVP_MD_CTX_destroy&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refer to the OpenSSL manual page for further details [[Manual:EVP_DigestInit(3)]]&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[EVP]]&lt;br /&gt;
* [[Libcrypto API]]&lt;br /&gt;
* [[EVP Symmetric Encryption and Decryption]]&lt;br /&gt;
* [[EVP Authenticated Encryption and Decryption]]&lt;br /&gt;
* [[EVP Asymmetric Encryption and Decryption of an Envelope]]&lt;br /&gt;
* [[EVP Key Agreement]]&lt;br /&gt;
* [[EVP Key and Parameter Generation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Crypto API]]&lt;br /&gt;
[[Category:C level]]&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Diffie-Hellman_parameters&amp;diff=3178</id>
		<title>Diffie-Hellman parameters</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Diffie-Hellman_parameters&amp;diff=3178"/>
		<updated>2021-05-12T20:55:39Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Spelling.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;TLS key agreement algorithms use [[Diffie Hellman|Diffie-Hellman]] groups and provide [http://blog.ivanristic.com/2013/06/ssl-labs-deploying-forward-secrecy.html perfect forward secrecy] (PFS). To use Diffie-Hellman groups and cipher suites with perfect forward secrecy, you must set up Diffie-Hellman parameters [http://www.mail-archive.com/openssl-users@openssl.org/msg71878.html at the server] or the PFS cipher suites will be silently ignored.&lt;br /&gt;
&lt;br /&gt;
Your Diffie-Hellman group parameters should match the key size used in the server's certificate. If you use a 2048-bit RSA prime in the server's certificate, then use a 2048-bit Diffie-Hellman group for key agreement.&lt;br /&gt;
&lt;br /&gt;
Due to [https://weakdh.org/ Logjam vulnerabilities] you should use a group with 2048-bits or higher.&lt;br /&gt;
&lt;br /&gt;
== Diffie-Hellman ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SSL_CTX_set_tmp_dh&amp;lt;/code&amp;gt; is used to set the Diffie-Hellman parameters for a context.  One of the easiest ways to get Diffie-Hellman parameters to use with this function is to generate random Diffie-Hellman parameters with the [https://www.openssl.org/docs/apps/dhparam.html dhparam] command-line program with the &amp;lt;code&amp;gt;-C&amp;lt;/code&amp;gt; option, and embed the resulting code fragment in your program.  For example, &amp;lt;code&amp;gt;openssl dhparam -C 2236&amp;lt;/code&amp;gt; might result in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef HEADER_DH_H&lt;br /&gt;
#include &amp;lt;openssl/dh.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
DH *get_dh2236()&lt;br /&gt;
	{&lt;br /&gt;
	static unsigned char dh2236_p[]={&lt;br /&gt;
		0x0F,0x52,0xE5,0x24,0xF5,0xFA,0x9D,0xDC,0xC6,0xAB,0xE6,0x04,&lt;br /&gt;
		0xE4,0x20,0x89,0x8A,0xB4,0xBF,0x27,0xB5,0x4A,0x95,0x57,0xA1,&lt;br /&gt;
		0x06,0xE7,0x30,0x73,0x83,0x5E,0xC9,0x23,0x11,0xED,0x42,0x45,&lt;br /&gt;
		0xAC,0x49,0xD3,0xE3,0xF3,0x34,0x73,0xC5,0x7D,0x00,0x3C,0x86,&lt;br /&gt;
		0x63,0x74,0xE0,0x75,0x97,0x84,0x1D,0x0B,0x11,0xDA,0x04,0xD0,&lt;br /&gt;
		0xFE,0x4F,0xB0,0x37,0xDF,0x57,0x22,0x2E,0x96,0x42,0xE0,0x7C,&lt;br /&gt;
		0xD7,0x5E,0x46,0x29,0xAF,0xB1,0xF4,0x81,0xAF,0xFC,0x9A,0xEF,&lt;br /&gt;
		0xFA,0x89,0x9E,0x0A,0xFB,0x16,0xE3,0x8F,0x01,0xA2,0xC8,0xDD,&lt;br /&gt;
		0xB4,0x47,0x12,0xF8,0x29,0x09,0x13,0x6E,0x9D,0xA8,0xF9,0x5D,&lt;br /&gt;
		0x08,0x00,0x3A,0x8C,0xA7,0xFF,0x6C,0xCF,0xE3,0x7C,0x3B,0x6B,&lt;br /&gt;
		0xB4,0x26,0xCC,0xDA,0x89,0x93,0x01,0x73,0xA8,0x55,0x3E,0x5B,&lt;br /&gt;
		0x77,0x25,0x8F,0x27,0xA3,0xF1,0xBF,0x7A,0x73,0x1F,0x85,0x96,&lt;br /&gt;
		0x0C,0x45,0x14,0xC1,0x06,0xB7,0x1C,0x75,0xAA,0x10,0xBC,0x86,&lt;br /&gt;
		0x98,0x75,0x44,0x70,0xD1,0x0F,0x20,0xF4,0xAC,0x4C,0xB3,0x88,&lt;br /&gt;
		0x16,0x1C,0x7E,0xA3,0x27,0xE4,0xAD,0xE1,0xA1,0x85,0x4F,0x1A,&lt;br /&gt;
		0x22,0x0D,0x05,0x42,0x73,0x69,0x45,0xC9,0x2F,0xF7,0xC2,0x48,&lt;br /&gt;
		0xE3,0xCE,0x9D,0x74,0x58,0x53,0xE7,0xA7,0x82,0x18,0xD9,0x3D,&lt;br /&gt;
		0xAF,0xAB,0x40,0x9F,0xAA,0x4C,0x78,0x0A,0xC3,0x24,0x2D,0xDB,&lt;br /&gt;
		0x12,0xA9,0x54,0xE5,0x47,0x87,0xAC,0x52,0xFE,0xE8,0x3D,0x0B,&lt;br /&gt;
		0x56,0xED,0x9C,0x9F,0xFF,0x39,0xE5,0xE5,0xBF,0x62,0x32,0x42,&lt;br /&gt;
		0x08,0xAE,0x6A,0xED,0x88,0x0E,0xB3,0x1A,0x4C,0xD3,0x08,0xE4,&lt;br /&gt;
		0xC4,0xAA,0x2C,0xCC,0xB1,0x37,0xA5,0xC1,0xA9,0x64,0x7E,0xEB,&lt;br /&gt;
		0xF9,0xD3,0xF5,0x15,0x28,0xFE,0x2E,0xE2,0x7F,0xFE,0xD9,0xB9,&lt;br /&gt;
		0x38,0x42,0x57,0x03,&lt;br /&gt;
		};&lt;br /&gt;
	static unsigned char dh2236_g[]={&lt;br /&gt;
		0x02,&lt;br /&gt;
		};&lt;br /&gt;
	DH *dh;&lt;br /&gt;
&lt;br /&gt;
	if ((dh=DH_new()) == NULL) return(NULL);&lt;br /&gt;
	dh-&amp;gt;p=BN_bin2bn(dh2236_p,sizeof(dh2236_p),NULL);&lt;br /&gt;
	dh-&amp;gt;g=BN_bin2bn(dh2236_g,sizeof(dh2236_g),NULL);&lt;br /&gt;
	if ((dh-&amp;gt;p == NULL) || (dh-&amp;gt;g == NULL))&lt;br /&gt;
		{ DH_free(dh); return(NULL); }&lt;br /&gt;
	return(dh);&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which can then be used like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DH *dh = get_dh2236 ();&lt;br /&gt;
if (1 != SSL_CTX_set_tmp_dh (ctx, dh))&lt;br /&gt;
  error ();&lt;br /&gt;
DH_free (dh);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to choose a bit length [http://www.keylength.com/en/3/ appropriate to the security level you want to achieve], although keep in mind that Diffie-Hellman parameters longer than 2236 bits may be [https://bugzilla.mozilla.org/show_bug.cgi?id=636802 incompatible with older versions of NSS].  Even worse, it appears that [http://stackoverflow.com/questions/6851461/java-why-does-ssl-handshake-give-could-not-generate-dh-keypair-exception versions of Java prior to 1.7 don't support Diffie-Hellman parameters longer than 1024 bits]!&lt;br /&gt;
&lt;br /&gt;
== Validating Parameters ==&lt;br /&gt;
&lt;br /&gt;
The Diffie-Hellman parameters should be validated after loading. To perform paramter validation, you call &amp;lt;tt&amp;gt;DH_check&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;DH_check&amp;lt;/tt&amp;gt; returns 0 or a bitmask values of the following:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_CHECK_P_NOT_PRIME&amp;lt;/tt&amp;gt; (0x01)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_CHECK_P_NOT_SAFE_PRIME&amp;lt;/tt&amp;gt; (0x02)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_UNABLE_TO_CHECK_GENERATOR&amp;lt;/tt&amp;gt; (0x04)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_NOT_SUITABLE_GENERATOR&amp;lt;/tt&amp;gt; (0x08)&lt;br /&gt;
&lt;br /&gt;
The validation code might look as follows (error checking omitted for clarity):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;BIO* bio = ...;&lt;br /&gt;
DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);&lt;br /&gt;
&lt;br /&gt;
int rc, codes = 0;&lt;br /&gt;
rc = DH_check(dh, &amp;amp;codes);&lt;br /&gt;
assert(rc == 1);&lt;br /&gt;
&lt;br /&gt;
if(BN_is_word(dh-&amp;gt;g, DH_GENERATOR_2))&lt;br /&gt;
{&lt;br /&gt;
    long residue = BN_mod_word(dh-&amp;gt;p, 24);&lt;br /&gt;
    if(residue == 11 || residue == 23) {&lt;br /&gt;
        codes &amp;amp;= ~DH_NOT_SUITABLE_GENERATOR;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_UNABLE_TO_CHECK_GENERATOR)&lt;br /&gt;
    printf(&amp;quot;DH_check: failed to test generator\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_NOT_SUITABLE_GENERATOR)&lt;br /&gt;
    printf(&amp;quot;DH_check: g is not a suitable generator\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_CHECK_P_NOT_PRIME)&lt;br /&gt;
    printf(&amp;quot;DH_check: p is not prime\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_CHECK_P_NOT_SAFE_PRIME)&lt;br /&gt;
    printf(&amp;quot;DH_check: p is not a safe prime\n&amp;quot;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The additional call to &amp;lt;tt&amp;gt;BN_mod_word(dh-&amp;gt;p, 24)&amp;lt;/tt&amp;gt; (and unmasking of &amp;lt;tt&amp;gt;DH_NOT_SUITABLE_GENERATOR&amp;lt;/tt&amp;gt;) is performed to ensure your program accepts IETF group parameters. OpenSSL checks the prime is congruent to 11 when &amp;lt;tt&amp;gt;g = 2&amp;lt;/tt&amp;gt;; while the IETF's primes are congruent to 23 when &amp;lt;tt&amp;gt;g = 2&amp;lt;/tt&amp;gt;. Without the test, the IETF parameters would fail validation. For details, see [http://crypto.stackexchange.com/questions/12961/diffie-hellman-parameter-check-when-g-2-must-p-mod-24-11 Diffie-Hellman Parameter Check (when g = 2, must p mod 24 == 11?)].&lt;br /&gt;
&lt;br /&gt;
== Elliptic curve Diffie-Hellman ==&lt;br /&gt;
&lt;br /&gt;
For [[Elliptic Curve Diffie Hellman|elliptic curve Diffie-Hellman]], you can do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);&lt;br /&gt;
if (! ecdh)&lt;br /&gt;
  error ();&lt;br /&gt;
if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh))&lt;br /&gt;
  error ();&lt;br /&gt;
EC_KEY_free (ecdh);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, in OpenSSL 1.0.2 (not yet released, as of Feb 2013) and higher, you should be able to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SSL_CTX_set_ecdh_auto (ctx, 1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, see [[Elliptic Curve Diffie Hellman]] and [[Elliptic Curve Cryptography]].&lt;br /&gt;
&lt;br /&gt;
== Diffie-Hellman Groups ==&lt;br /&gt;
&lt;br /&gt;
Ephemeral Diffie-Hellman key agreement needs to happen over a group. The client and server will each pick a random value in the group and perform key agreement with the random parameters. For each run of the protocol, the random parameters will change but the group will remain the same. When you need a group you can either calculate one; or you can use a standard group published by a standards body like the IETF.&lt;br /&gt;
&lt;br /&gt;
Calculating a group is an expensive operation because the safe primes used for the group are harder to find. As the group size gets larger it takes more time to find them. A 3072-bit group can take minutes to find, and a 8192-bit group can take hours to find in the worst case.&lt;br /&gt;
&lt;br /&gt;
To avoid the runtime costs associated with finding a group, you typically you use a standard group, like those published in RFC 3526 or RFC 7919. The declarations for the IETF groups are provided below.&lt;br /&gt;
&lt;br /&gt;
=== RFC 3526 Groups ===&lt;br /&gt;
&lt;br /&gt;
Below are five Diffie-Hellman MODP groups specified in [http://tools.ietf.org/html/rfc3526 RFC 3526, More Modular Exponential (MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)] (the 1024-bit parameter is from RFC 2409). They can be used with &amp;lt;tt&amp;gt;PEM_read_bio_DHparams&amp;lt;/tt&amp;gt; and a memory &amp;lt;tt&amp;gt;BIO&amp;lt;/tt&amp;gt;. RFC 3526 also offers 1536-bit, 6144-bit and 8192-bit primes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;static const char g_dh1024_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n&amp;quot;&lt;br /&gt;
    &amp;quot;Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n&amp;quot;&lt;br /&gt;
    &amp;quot;/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh1536_sz[] = &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n&amp;quot;&lt;br /&gt;
    &amp;quot;Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n&amp;quot;&lt;br /&gt;
    &amp;quot;/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORbPcIAfLihY78FmNpINhxV05pp\n&amp;quot;&lt;br /&gt;
    &amp;quot;Fj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaWbWcMNU5KvJgE8XRsCMojcyf/\n&amp;quot;&lt;br /&gt;
    &amp;quot;/////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh2048_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh3072_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n&amp;quot;&lt;br /&gt;
    &amp;quot;fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n&amp;quot;&lt;br /&gt;
    &amp;quot;ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS\n&amp;quot;&lt;br /&gt;
    &amp;quot;yv//////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh4096_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n&amp;quot;&lt;br /&gt;
    &amp;quot;fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n&amp;quot;&lt;br /&gt;
    &amp;quot;ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI\n&amp;quot;&lt;br /&gt;
    &amp;quot;ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O\n&amp;quot;&lt;br /&gt;
    &amp;quot;+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI\n&amp;quot;&lt;br /&gt;
    &amp;quot;HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI=\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RFC 7919 Groups ===&lt;br /&gt;
&lt;br /&gt;
Below are three additional Diffie-Hellman groups specified in [http://tools.ietf.org/html/rfc3526 RFC 7919, Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for Transport Layer Security (TLS)]. They can be used with &amp;lt;tt&amp;gt;PEM_read_bio_DHparams&amp;lt;/tt&amp;gt; and a memory &amp;lt;tt&amp;gt;BIO&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;static const char g_ffdhe2048_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_ffdhe3072_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n&amp;quot;&lt;br /&gt;
    &amp;quot;7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n&amp;quot;&lt;br /&gt;
    &amp;quot;nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu\n&amp;quot;&lt;br /&gt;
    &amp;quot;N///////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_ffdhe4096_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n&amp;quot;&lt;br /&gt;
    &amp;quot;7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n&amp;quot;&lt;br /&gt;
    &amp;quot;nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e\n&amp;quot;&lt;br /&gt;
    &amp;quot;8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx\n&amp;quot;&lt;br /&gt;
    &amp;quot;iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K\n&amp;quot;&lt;br /&gt;
    &amp;quot;zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Diffie-Hellman_parameters&amp;diff=3177</id>
		<title>Diffie-Hellman parameters</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Diffie-Hellman_parameters&amp;diff=3177"/>
		<updated>2021-05-12T19:28:18Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Rework introduction.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;TLS key agreement algorithms use [[Diffie Hellman|Diffie-Hellman]] groups and provide [http://blog.ivanristic.com/2013/06/ssl-labs-deploying-forward-secrecy.html perfect forward secrecy] (PFS). To use Diffie-Hellman groups and cipher suites with perfect forward secrecy, you must set up Diffie-Hellman parameters [http://www.mail-archive.com/openssl-users@openssl.org/msg71878.html at the server] or the PFS cipher suites will be silently ignored.&lt;br /&gt;
&lt;br /&gt;
Your Diffie-Hellman group parameters should match the key size used in the server's certificate. If you use a 2048-bit RSA prime in the server's certificate, then use a 2048-bit Dhiifie-Hellman group for key agreement.&lt;br /&gt;
&lt;br /&gt;
Due to [https://weakdh.org/ Logjam vulnerabilities] you should use a group with 2048-bits or higher.&lt;br /&gt;
&lt;br /&gt;
== Diffie-Hellman ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SSL_CTX_set_tmp_dh&amp;lt;/code&amp;gt; is used to set the Diffie-Hellman parameters for a context.  One of the easiest ways to get Diffie-Hellman parameters to use with this function is to generate random Diffie-Hellman parameters with the [https://www.openssl.org/docs/apps/dhparam.html dhparam] command-line program with the &amp;lt;code&amp;gt;-C&amp;lt;/code&amp;gt; option, and embed the resulting code fragment in your program.  For example, &amp;lt;code&amp;gt;openssl dhparam -C 2236&amp;lt;/code&amp;gt; might result in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef HEADER_DH_H&lt;br /&gt;
#include &amp;lt;openssl/dh.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
DH *get_dh2236()&lt;br /&gt;
	{&lt;br /&gt;
	static unsigned char dh2236_p[]={&lt;br /&gt;
		0x0F,0x52,0xE5,0x24,0xF5,0xFA,0x9D,0xDC,0xC6,0xAB,0xE6,0x04,&lt;br /&gt;
		0xE4,0x20,0x89,0x8A,0xB4,0xBF,0x27,0xB5,0x4A,0x95,0x57,0xA1,&lt;br /&gt;
		0x06,0xE7,0x30,0x73,0x83,0x5E,0xC9,0x23,0x11,0xED,0x42,0x45,&lt;br /&gt;
		0xAC,0x49,0xD3,0xE3,0xF3,0x34,0x73,0xC5,0x7D,0x00,0x3C,0x86,&lt;br /&gt;
		0x63,0x74,0xE0,0x75,0x97,0x84,0x1D,0x0B,0x11,0xDA,0x04,0xD0,&lt;br /&gt;
		0xFE,0x4F,0xB0,0x37,0xDF,0x57,0x22,0x2E,0x96,0x42,0xE0,0x7C,&lt;br /&gt;
		0xD7,0x5E,0x46,0x29,0xAF,0xB1,0xF4,0x81,0xAF,0xFC,0x9A,0xEF,&lt;br /&gt;
		0xFA,0x89,0x9E,0x0A,0xFB,0x16,0xE3,0x8F,0x01,0xA2,0xC8,0xDD,&lt;br /&gt;
		0xB4,0x47,0x12,0xF8,0x29,0x09,0x13,0x6E,0x9D,0xA8,0xF9,0x5D,&lt;br /&gt;
		0x08,0x00,0x3A,0x8C,0xA7,0xFF,0x6C,0xCF,0xE3,0x7C,0x3B,0x6B,&lt;br /&gt;
		0xB4,0x26,0xCC,0xDA,0x89,0x93,0x01,0x73,0xA8,0x55,0x3E,0x5B,&lt;br /&gt;
		0x77,0x25,0x8F,0x27,0xA3,0xF1,0xBF,0x7A,0x73,0x1F,0x85,0x96,&lt;br /&gt;
		0x0C,0x45,0x14,0xC1,0x06,0xB7,0x1C,0x75,0xAA,0x10,0xBC,0x86,&lt;br /&gt;
		0x98,0x75,0x44,0x70,0xD1,0x0F,0x20,0xF4,0xAC,0x4C,0xB3,0x88,&lt;br /&gt;
		0x16,0x1C,0x7E,0xA3,0x27,0xE4,0xAD,0xE1,0xA1,0x85,0x4F,0x1A,&lt;br /&gt;
		0x22,0x0D,0x05,0x42,0x73,0x69,0x45,0xC9,0x2F,0xF7,0xC2,0x48,&lt;br /&gt;
		0xE3,0xCE,0x9D,0x74,0x58,0x53,0xE7,0xA7,0x82,0x18,0xD9,0x3D,&lt;br /&gt;
		0xAF,0xAB,0x40,0x9F,0xAA,0x4C,0x78,0x0A,0xC3,0x24,0x2D,0xDB,&lt;br /&gt;
		0x12,0xA9,0x54,0xE5,0x47,0x87,0xAC,0x52,0xFE,0xE8,0x3D,0x0B,&lt;br /&gt;
		0x56,0xED,0x9C,0x9F,0xFF,0x39,0xE5,0xE5,0xBF,0x62,0x32,0x42,&lt;br /&gt;
		0x08,0xAE,0x6A,0xED,0x88,0x0E,0xB3,0x1A,0x4C,0xD3,0x08,0xE4,&lt;br /&gt;
		0xC4,0xAA,0x2C,0xCC,0xB1,0x37,0xA5,0xC1,0xA9,0x64,0x7E,0xEB,&lt;br /&gt;
		0xF9,0xD3,0xF5,0x15,0x28,0xFE,0x2E,0xE2,0x7F,0xFE,0xD9,0xB9,&lt;br /&gt;
		0x38,0x42,0x57,0x03,&lt;br /&gt;
		};&lt;br /&gt;
	static unsigned char dh2236_g[]={&lt;br /&gt;
		0x02,&lt;br /&gt;
		};&lt;br /&gt;
	DH *dh;&lt;br /&gt;
&lt;br /&gt;
	if ((dh=DH_new()) == NULL) return(NULL);&lt;br /&gt;
	dh-&amp;gt;p=BN_bin2bn(dh2236_p,sizeof(dh2236_p),NULL);&lt;br /&gt;
	dh-&amp;gt;g=BN_bin2bn(dh2236_g,sizeof(dh2236_g),NULL);&lt;br /&gt;
	if ((dh-&amp;gt;p == NULL) || (dh-&amp;gt;g == NULL))&lt;br /&gt;
		{ DH_free(dh); return(NULL); }&lt;br /&gt;
	return(dh);&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which can then be used like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DH *dh = get_dh2236 ();&lt;br /&gt;
if (1 != SSL_CTX_set_tmp_dh (ctx, dh))&lt;br /&gt;
  error ();&lt;br /&gt;
DH_free (dh);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to choose a bit length [http://www.keylength.com/en/3/ appropriate to the security level you want to achieve], although keep in mind that Diffie-Hellman parameters longer than 2236 bits may be [https://bugzilla.mozilla.org/show_bug.cgi?id=636802 incompatible with older versions of NSS].  Even worse, it appears that [http://stackoverflow.com/questions/6851461/java-why-does-ssl-handshake-give-could-not-generate-dh-keypair-exception versions of Java prior to 1.7 don't support Diffie-Hellman parameters longer than 1024 bits]!&lt;br /&gt;
&lt;br /&gt;
== Validating Parameters ==&lt;br /&gt;
&lt;br /&gt;
The Diffie-Hellman parameters should be validated after loading. To perform paramter validation, you call &amp;lt;tt&amp;gt;DH_check&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;DH_check&amp;lt;/tt&amp;gt; returns 0 or a bitmask values of the following:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_CHECK_P_NOT_PRIME&amp;lt;/tt&amp;gt; (0x01)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_CHECK_P_NOT_SAFE_PRIME&amp;lt;/tt&amp;gt; (0x02)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_UNABLE_TO_CHECK_GENERATOR&amp;lt;/tt&amp;gt; (0x04)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_NOT_SUITABLE_GENERATOR&amp;lt;/tt&amp;gt; (0x08)&lt;br /&gt;
&lt;br /&gt;
The validation code might look as follows (error checking omitted for clarity):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;BIO* bio = ...;&lt;br /&gt;
DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);&lt;br /&gt;
&lt;br /&gt;
int rc, codes = 0;&lt;br /&gt;
rc = DH_check(dh, &amp;amp;codes);&lt;br /&gt;
assert(rc == 1);&lt;br /&gt;
&lt;br /&gt;
if(BN_is_word(dh-&amp;gt;g, DH_GENERATOR_2))&lt;br /&gt;
{&lt;br /&gt;
    long residue = BN_mod_word(dh-&amp;gt;p, 24);&lt;br /&gt;
    if(residue == 11 || residue == 23) {&lt;br /&gt;
        codes &amp;amp;= ~DH_NOT_SUITABLE_GENERATOR;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_UNABLE_TO_CHECK_GENERATOR)&lt;br /&gt;
    printf(&amp;quot;DH_check: failed to test generator\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_NOT_SUITABLE_GENERATOR)&lt;br /&gt;
    printf(&amp;quot;DH_check: g is not a suitable generator\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_CHECK_P_NOT_PRIME)&lt;br /&gt;
    printf(&amp;quot;DH_check: p is not prime\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_CHECK_P_NOT_SAFE_PRIME)&lt;br /&gt;
    printf(&amp;quot;DH_check: p is not a safe prime\n&amp;quot;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The additional call to &amp;lt;tt&amp;gt;BN_mod_word(dh-&amp;gt;p, 24)&amp;lt;/tt&amp;gt; (and unmasking of &amp;lt;tt&amp;gt;DH_NOT_SUITABLE_GENERATOR&amp;lt;/tt&amp;gt;) is performed to ensure your program accepts IETF group parameters. OpenSSL checks the prime is congruent to 11 when &amp;lt;tt&amp;gt;g = 2&amp;lt;/tt&amp;gt;; while the IETF's primes are congruent to 23 when &amp;lt;tt&amp;gt;g = 2&amp;lt;/tt&amp;gt;. Without the test, the IETF parameters would fail validation. For details, see [http://crypto.stackexchange.com/questions/12961/diffie-hellman-parameter-check-when-g-2-must-p-mod-24-11 Diffie-Hellman Parameter Check (when g = 2, must p mod 24 == 11?)].&lt;br /&gt;
&lt;br /&gt;
== Elliptic curve Diffie-Hellman ==&lt;br /&gt;
&lt;br /&gt;
For [[Elliptic Curve Diffie Hellman|elliptic curve Diffie-Hellman]], you can do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);&lt;br /&gt;
if (! ecdh)&lt;br /&gt;
  error ();&lt;br /&gt;
if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh))&lt;br /&gt;
  error ();&lt;br /&gt;
EC_KEY_free (ecdh);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, in OpenSSL 1.0.2 (not yet released, as of Feb 2013) and higher, you should be able to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SSL_CTX_set_ecdh_auto (ctx, 1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, see [[Elliptic Curve Diffie Hellman]] and [[Elliptic Curve Cryptography]].&lt;br /&gt;
&lt;br /&gt;
== Diffie-Hellman Groups ==&lt;br /&gt;
&lt;br /&gt;
Ephemeral Diffie-Hellman key agreement needs to happen over a group. The client and server will each pick a random value in the group and perform key agreement with the random parameters. For each run of the protocol, the random parameters will change but the group will remain the same. When you need a group you can either calculate one; or you can use a standard group published by a standards body like the IETF.&lt;br /&gt;
&lt;br /&gt;
Calculating a group is an expensive operation because the safe primes used for the group are harder to find. As the group size gets larger it takes more time to find them. A 3072-bit group can take minutes to find, and a 8192-bit group can take hours to find in the worst case.&lt;br /&gt;
&lt;br /&gt;
To avoid the runtime costs associated with finding a group, you typically you use a standard group, like those published in RFC 3526 or RFC 7919. The declarations for the IETF groups are provided below.&lt;br /&gt;
&lt;br /&gt;
=== RFC 3526 Groups ===&lt;br /&gt;
&lt;br /&gt;
Below are five Diffie-Hellman MODP groups specified in [http://tools.ietf.org/html/rfc3526 RFC 3526, More Modular Exponential (MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)] (the 1024-bit parameter is from RFC 2409). They can be used with &amp;lt;tt&amp;gt;PEM_read_bio_DHparams&amp;lt;/tt&amp;gt; and a memory &amp;lt;tt&amp;gt;BIO&amp;lt;/tt&amp;gt;. RFC 3526 also offers 1536-bit, 6144-bit and 8192-bit primes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;static const char g_dh1024_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n&amp;quot;&lt;br /&gt;
    &amp;quot;Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n&amp;quot;&lt;br /&gt;
    &amp;quot;/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh1536_sz[] = &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n&amp;quot;&lt;br /&gt;
    &amp;quot;Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n&amp;quot;&lt;br /&gt;
    &amp;quot;/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORbPcIAfLihY78FmNpINhxV05pp\n&amp;quot;&lt;br /&gt;
    &amp;quot;Fj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaWbWcMNU5KvJgE8XRsCMojcyf/\n&amp;quot;&lt;br /&gt;
    &amp;quot;/////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh2048_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh3072_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n&amp;quot;&lt;br /&gt;
    &amp;quot;fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n&amp;quot;&lt;br /&gt;
    &amp;quot;ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS\n&amp;quot;&lt;br /&gt;
    &amp;quot;yv//////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh4096_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n&amp;quot;&lt;br /&gt;
    &amp;quot;fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n&amp;quot;&lt;br /&gt;
    &amp;quot;ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI\n&amp;quot;&lt;br /&gt;
    &amp;quot;ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O\n&amp;quot;&lt;br /&gt;
    &amp;quot;+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI\n&amp;quot;&lt;br /&gt;
    &amp;quot;HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI=\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RFC 7919 Groups ===&lt;br /&gt;
&lt;br /&gt;
Below are three additional Diffie-Hellman groups specified in [http://tools.ietf.org/html/rfc3526 RFC 7919, Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for Transport Layer Security (TLS)]. They can be used with &amp;lt;tt&amp;gt;PEM_read_bio_DHparams&amp;lt;/tt&amp;gt; and a memory &amp;lt;tt&amp;gt;BIO&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;static const char g_ffdhe2048_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_ffdhe3072_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n&amp;quot;&lt;br /&gt;
    &amp;quot;7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n&amp;quot;&lt;br /&gt;
    &amp;quot;nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu\n&amp;quot;&lt;br /&gt;
    &amp;quot;N///////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_ffdhe4096_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n&amp;quot;&lt;br /&gt;
    &amp;quot;7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n&amp;quot;&lt;br /&gt;
    &amp;quot;nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e\n&amp;quot;&lt;br /&gt;
    &amp;quot;8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx\n&amp;quot;&lt;br /&gt;
    &amp;quot;iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K\n&amp;quot;&lt;br /&gt;
    &amp;quot;zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Diffie-Hellman_parameters&amp;diff=3176</id>
		<title>Diffie-Hellman parameters</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Diffie-Hellman_parameters&amp;diff=3176"/>
		<updated>2021-05-12T19:21:36Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Reorganize Diffie-Hellman Groups. Add RFC 7919 group parameters.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To use [http://blog.ivanristic.com/2013/06/ssl-labs-deploying-forward-secrecy.html perfect forward secrecy] cipher suites, you must set up [[Diffie Hellman|Diffie-Hellman]] parameters ([http://www.mail-archive.com/openssl-users@openssl.org/msg71878.html on the server side]), or the PFS cipher suites will be silently ignored.&lt;br /&gt;
&lt;br /&gt;
== Diffie-Hellman ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SSL_CTX_set_tmp_dh&amp;lt;/code&amp;gt; is used to set the Diffie-Hellman parameters for a context.  One of the easiest ways to get Diffie-Hellman parameters to use with this function is to generate random Diffie-Hellman parameters with the [https://www.openssl.org/docs/apps/dhparam.html dhparam] command-line program with the &amp;lt;code&amp;gt;-C&amp;lt;/code&amp;gt; option, and embed the resulting code fragment in your program.  For example, &amp;lt;code&amp;gt;openssl dhparam -C 2236&amp;lt;/code&amp;gt; might result in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef HEADER_DH_H&lt;br /&gt;
#include &amp;lt;openssl/dh.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
DH *get_dh2236()&lt;br /&gt;
	{&lt;br /&gt;
	static unsigned char dh2236_p[]={&lt;br /&gt;
		0x0F,0x52,0xE5,0x24,0xF5,0xFA,0x9D,0xDC,0xC6,0xAB,0xE6,0x04,&lt;br /&gt;
		0xE4,0x20,0x89,0x8A,0xB4,0xBF,0x27,0xB5,0x4A,0x95,0x57,0xA1,&lt;br /&gt;
		0x06,0xE7,0x30,0x73,0x83,0x5E,0xC9,0x23,0x11,0xED,0x42,0x45,&lt;br /&gt;
		0xAC,0x49,0xD3,0xE3,0xF3,0x34,0x73,0xC5,0x7D,0x00,0x3C,0x86,&lt;br /&gt;
		0x63,0x74,0xE0,0x75,0x97,0x84,0x1D,0x0B,0x11,0xDA,0x04,0xD0,&lt;br /&gt;
		0xFE,0x4F,0xB0,0x37,0xDF,0x57,0x22,0x2E,0x96,0x42,0xE0,0x7C,&lt;br /&gt;
		0xD7,0x5E,0x46,0x29,0xAF,0xB1,0xF4,0x81,0xAF,0xFC,0x9A,0xEF,&lt;br /&gt;
		0xFA,0x89,0x9E,0x0A,0xFB,0x16,0xE3,0x8F,0x01,0xA2,0xC8,0xDD,&lt;br /&gt;
		0xB4,0x47,0x12,0xF8,0x29,0x09,0x13,0x6E,0x9D,0xA8,0xF9,0x5D,&lt;br /&gt;
		0x08,0x00,0x3A,0x8C,0xA7,0xFF,0x6C,0xCF,0xE3,0x7C,0x3B,0x6B,&lt;br /&gt;
		0xB4,0x26,0xCC,0xDA,0x89,0x93,0x01,0x73,0xA8,0x55,0x3E,0x5B,&lt;br /&gt;
		0x77,0x25,0x8F,0x27,0xA3,0xF1,0xBF,0x7A,0x73,0x1F,0x85,0x96,&lt;br /&gt;
		0x0C,0x45,0x14,0xC1,0x06,0xB7,0x1C,0x75,0xAA,0x10,0xBC,0x86,&lt;br /&gt;
		0x98,0x75,0x44,0x70,0xD1,0x0F,0x20,0xF4,0xAC,0x4C,0xB3,0x88,&lt;br /&gt;
		0x16,0x1C,0x7E,0xA3,0x27,0xE4,0xAD,0xE1,0xA1,0x85,0x4F,0x1A,&lt;br /&gt;
		0x22,0x0D,0x05,0x42,0x73,0x69,0x45,0xC9,0x2F,0xF7,0xC2,0x48,&lt;br /&gt;
		0xE3,0xCE,0x9D,0x74,0x58,0x53,0xE7,0xA7,0x82,0x18,0xD9,0x3D,&lt;br /&gt;
		0xAF,0xAB,0x40,0x9F,0xAA,0x4C,0x78,0x0A,0xC3,0x24,0x2D,0xDB,&lt;br /&gt;
		0x12,0xA9,0x54,0xE5,0x47,0x87,0xAC,0x52,0xFE,0xE8,0x3D,0x0B,&lt;br /&gt;
		0x56,0xED,0x9C,0x9F,0xFF,0x39,0xE5,0xE5,0xBF,0x62,0x32,0x42,&lt;br /&gt;
		0x08,0xAE,0x6A,0xED,0x88,0x0E,0xB3,0x1A,0x4C,0xD3,0x08,0xE4,&lt;br /&gt;
		0xC4,0xAA,0x2C,0xCC,0xB1,0x37,0xA5,0xC1,0xA9,0x64,0x7E,0xEB,&lt;br /&gt;
		0xF9,0xD3,0xF5,0x15,0x28,0xFE,0x2E,0xE2,0x7F,0xFE,0xD9,0xB9,&lt;br /&gt;
		0x38,0x42,0x57,0x03,&lt;br /&gt;
		};&lt;br /&gt;
	static unsigned char dh2236_g[]={&lt;br /&gt;
		0x02,&lt;br /&gt;
		};&lt;br /&gt;
	DH *dh;&lt;br /&gt;
&lt;br /&gt;
	if ((dh=DH_new()) == NULL) return(NULL);&lt;br /&gt;
	dh-&amp;gt;p=BN_bin2bn(dh2236_p,sizeof(dh2236_p),NULL);&lt;br /&gt;
	dh-&amp;gt;g=BN_bin2bn(dh2236_g,sizeof(dh2236_g),NULL);&lt;br /&gt;
	if ((dh-&amp;gt;p == NULL) || (dh-&amp;gt;g == NULL))&lt;br /&gt;
		{ DH_free(dh); return(NULL); }&lt;br /&gt;
	return(dh);&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which can then be used like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DH *dh = get_dh2236 ();&lt;br /&gt;
if (1 != SSL_CTX_set_tmp_dh (ctx, dh))&lt;br /&gt;
  error ();&lt;br /&gt;
DH_free (dh);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to choose a bit length [http://www.keylength.com/en/3/ appropriate to the security level you want to achieve], although keep in mind that Diffie-Hellman parameters longer than 2236 bits may be [https://bugzilla.mozilla.org/show_bug.cgi?id=636802 incompatible with older versions of NSS].  Even worse, it appears that [http://stackoverflow.com/questions/6851461/java-why-does-ssl-handshake-give-could-not-generate-dh-keypair-exception versions of Java prior to 1.7 don't support Diffie-Hellman parameters longer than 1024 bits]!&lt;br /&gt;
&lt;br /&gt;
== Validating Parameters ==&lt;br /&gt;
&lt;br /&gt;
The Diffie-Hellman parameters should be validated after loading. To perform paramter validation, you call &amp;lt;tt&amp;gt;DH_check&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;DH_check&amp;lt;/tt&amp;gt; returns 0 or a bitmask values of the following:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_CHECK_P_NOT_PRIME&amp;lt;/tt&amp;gt; (0x01)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_CHECK_P_NOT_SAFE_PRIME&amp;lt;/tt&amp;gt; (0x02)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_UNABLE_TO_CHECK_GENERATOR&amp;lt;/tt&amp;gt; (0x04)&lt;br /&gt;
* &amp;lt;tt&amp;gt;DH_NOT_SUITABLE_GENERATOR&amp;lt;/tt&amp;gt; (0x08)&lt;br /&gt;
&lt;br /&gt;
The validation code might look as follows (error checking omitted for clarity):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;BIO* bio = ...;&lt;br /&gt;
DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);&lt;br /&gt;
&lt;br /&gt;
int rc, codes = 0;&lt;br /&gt;
rc = DH_check(dh, &amp;amp;codes);&lt;br /&gt;
assert(rc == 1);&lt;br /&gt;
&lt;br /&gt;
if(BN_is_word(dh-&amp;gt;g, DH_GENERATOR_2))&lt;br /&gt;
{&lt;br /&gt;
    long residue = BN_mod_word(dh-&amp;gt;p, 24);&lt;br /&gt;
    if(residue == 11 || residue == 23) {&lt;br /&gt;
        codes &amp;amp;= ~DH_NOT_SUITABLE_GENERATOR;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_UNABLE_TO_CHECK_GENERATOR)&lt;br /&gt;
    printf(&amp;quot;DH_check: failed to test generator\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_NOT_SUITABLE_GENERATOR)&lt;br /&gt;
    printf(&amp;quot;DH_check: g is not a suitable generator\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_CHECK_P_NOT_PRIME)&lt;br /&gt;
    printf(&amp;quot;DH_check: p is not prime\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (codes &amp;amp; DH_CHECK_P_NOT_SAFE_PRIME)&lt;br /&gt;
    printf(&amp;quot;DH_check: p is not a safe prime\n&amp;quot;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The additional call to &amp;lt;tt&amp;gt;BN_mod_word(dh-&amp;gt;p, 24)&amp;lt;/tt&amp;gt; (and unmasking of &amp;lt;tt&amp;gt;DH_NOT_SUITABLE_GENERATOR&amp;lt;/tt&amp;gt;) is performed to ensure your program accepts IETF group parameters. OpenSSL checks the prime is congruent to 11 when &amp;lt;tt&amp;gt;g = 2&amp;lt;/tt&amp;gt;; while the IETF's primes are congruent to 23 when &amp;lt;tt&amp;gt;g = 2&amp;lt;/tt&amp;gt;. Without the test, the IETF parameters would fail validation. For details, see [http://crypto.stackexchange.com/questions/12961/diffie-hellman-parameter-check-when-g-2-must-p-mod-24-11 Diffie-Hellman Parameter Check (when g = 2, must p mod 24 == 11?)].&lt;br /&gt;
&lt;br /&gt;
== Elliptic curve Diffie-Hellman ==&lt;br /&gt;
&lt;br /&gt;
For [[Elliptic Curve Diffie Hellman|elliptic curve Diffie-Hellman]], you can do something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);&lt;br /&gt;
if (! ecdh)&lt;br /&gt;
  error ();&lt;br /&gt;
if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh))&lt;br /&gt;
  error ();&lt;br /&gt;
EC_KEY_free (ecdh);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, in OpenSSL 1.0.2 (not yet released, as of Feb 2013) and higher, you should be able to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SSL_CTX_set_ecdh_auto (ctx, 1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information, see [[Elliptic Curve Diffie Hellman]] and [[Elliptic Curve Cryptography]].&lt;br /&gt;
&lt;br /&gt;
== Diffie-Hellman Groups ==&lt;br /&gt;
&lt;br /&gt;
Ephemeral Diffie-Hellman key agreement needs to happen over a group. The client and server will each pick a random value in the group and perform key agreement with the random parameters. For each run of the protocol, the random parameters will change but the group will remain the same. When you need a group you can either calculate one; or you can use a standard group published by a standards body like the IETF.&lt;br /&gt;
&lt;br /&gt;
Calculating a group is an expensive operation because the safe primes used for the group are harder to find. As the group size gets larger it takes more time to find them. A 3072-bit group can take minutes to find, and a 8192-bit group can take hours to find in the worst case.&lt;br /&gt;
&lt;br /&gt;
To avoid the runtime costs associated with finding a group, you typically you use a standard group, like those published in RFC 3526 or RFC 7919. The declarations for the IETF groups are provided below.&lt;br /&gt;
&lt;br /&gt;
Due to [https://weakdh.org/ Logjam vulnerabilities] you should use a group with 2048-bits or higher.&lt;br /&gt;
&lt;br /&gt;
== RFC 3526 Groups ==&lt;br /&gt;
&lt;br /&gt;
Below are five Diffie-Hellman MODP groups specified in [http://tools.ietf.org/html/rfc3526 RFC 3526, More Modular Exponential (MODP) Diffie-Hellman groups for Internet Key Exchange (IKE)] (the 1024-bit parameter is from RFC 2409). They can be used with &amp;lt;tt&amp;gt;PEM_read_bio_DHparams&amp;lt;/tt&amp;gt; and a memory &amp;lt;tt&amp;gt;BIO&amp;lt;/tt&amp;gt;. RFC 3526 also offers 1536-bit, 6144-bit and 8192-bit primes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;static const char g_dh1024_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n&amp;quot;&lt;br /&gt;
    &amp;quot;Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n&amp;quot;&lt;br /&gt;
    &amp;quot;/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh1536_sz[] = &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n&amp;quot;&lt;br /&gt;
    &amp;quot;Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n&amp;quot;&lt;br /&gt;
    &amp;quot;/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORbPcIAfLihY78FmNpINhxV05pp\n&amp;quot;&lt;br /&gt;
    &amp;quot;Fj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaWbWcMNU5KvJgE8XRsCMojcyf/\n&amp;quot;&lt;br /&gt;
    &amp;quot;/////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh2048_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh3072_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n&amp;quot;&lt;br /&gt;
    &amp;quot;fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n&amp;quot;&lt;br /&gt;
    &amp;quot;ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS\n&amp;quot;&lt;br /&gt;
    &amp;quot;yv//////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_dh4096_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n&amp;quot;&lt;br /&gt;
    &amp;quot;IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n&amp;quot;&lt;br /&gt;
    &amp;quot;awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n&amp;quot;&lt;br /&gt;
    &amp;quot;mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n&amp;quot;&lt;br /&gt;
    &amp;quot;fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n&amp;quot;&lt;br /&gt;
    &amp;quot;5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n&amp;quot;&lt;br /&gt;
    &amp;quot;fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n&amp;quot;&lt;br /&gt;
    &amp;quot;ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI\n&amp;quot;&lt;br /&gt;
    &amp;quot;ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O\n&amp;quot;&lt;br /&gt;
    &amp;quot;+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI\n&amp;quot;&lt;br /&gt;
    &amp;quot;HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI=\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RFC 7919 Groups ==&lt;br /&gt;
&lt;br /&gt;
Below are three additional Diffie-Hellman groups specified in [http://tools.ietf.org/html/rfc3526 RFC 7919, Negotiated Finite Field Diffie-Hellman Ephemeral Parameters for Transport Layer Security (TLS)]. They can be used with &amp;lt;tt&amp;gt;PEM_read_bio_DHparams&amp;lt;/tt&amp;gt; and a memory &amp;lt;tt&amp;gt;BIO&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;static const char g_ffdhe2048_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_ffdhe3072_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n&amp;quot;&lt;br /&gt;
    &amp;quot;7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n&amp;quot;&lt;br /&gt;
    &amp;quot;nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu\n&amp;quot;&lt;br /&gt;
    &amp;quot;N///////////AgEC\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
static const char g_ffdhe4096_sz[] =&lt;br /&gt;
    &amp;quot;-----BEGIN DH PARAMETERS-----\n&amp;quot;&lt;br /&gt;
    &amp;quot;MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n&amp;quot;&lt;br /&gt;
    &amp;quot;+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n&amp;quot;&lt;br /&gt;
    &amp;quot;87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n&amp;quot;&lt;br /&gt;
    &amp;quot;YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n&amp;quot;&lt;br /&gt;
    &amp;quot;7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n&amp;quot;&lt;br /&gt;
    &amp;quot;ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n&amp;quot;&lt;br /&gt;
    &amp;quot;7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n&amp;quot;&lt;br /&gt;
    &amp;quot;nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e\n&amp;quot;&lt;br /&gt;
    &amp;quot;8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx\n&amp;quot;&lt;br /&gt;
    &amp;quot;iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K\n&amp;quot;&lt;br /&gt;
    &amp;quot;zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=\n&amp;quot;&lt;br /&gt;
    &amp;quot;-----END DH PARAMETERS-----\n&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Compilation_and_Installation&amp;diff=3167</id>
		<title>Compilation and Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Compilation_and_Installation&amp;diff=3167"/>
		<updated>2021-03-29T19:19:05Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: /* Using RPATHs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following page is a combination of the &amp;lt;tt&amp;gt;INSTALL&amp;lt;/tt&amp;gt; file provided with the OpenSSL library and notes from the field. If you have questions about what you are doing or seeing, then you should consult &amp;lt;tt&amp;gt;INSTALL&amp;lt;/tt&amp;gt; since it contains the commands and specifies the behavior by the development team.&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses a custom build system to configure the library. Configuration will allow the library to set up the recursive makefiles from &amp;lt;tt&amp;gt;makefile.org&amp;lt;/tt&amp;gt;. Once configured, you use &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; to build the library. You should avoid custom build systems because they often miss details, like each architecture and platform has a unique &amp;lt;tt&amp;gt;opensslconf.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bn.h&amp;lt;/tt&amp;gt; generated by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You must use a C compiler to build the OpenSSL library. You cannot use a C++ compiler. Later, once the library is built, it is OK to create user programs with a C++ compiler. But the library proper must be built with a C compiler.&lt;br /&gt;
&lt;br /&gt;
There are two generations of build system. First is the build system used in OpenSSL 1.0.2 and below. The instructions below apply to it. Second is the build system for OpenSSL 1.1.0 and above. The instructions are similar, but not the same. For example, the second generation abandons the monolithic &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and places individual configurations in the &amp;lt;tt&amp;gt;Configurations&amp;lt;/tt&amp;gt; directory.  Also, the second generation is more platform agnostic and uses templates to produce a final, top level build file (&amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;descrip.mms&amp;lt;/tt&amp;gt;, what have you).&lt;br /&gt;
&lt;br /&gt;
After you configure and build the library, you should always perform a &amp;lt;tt&amp;gt;make test&amp;lt;/tt&amp;gt; to ensure the library performs as expected under its self tests. If you are building OpenSSL 1.1.0 and above, then you will also need PERL 5.10 or higher (see &amp;lt;tt&amp;gt;README.PERL&amp;lt;/tt&amp;gt; for details).&lt;br /&gt;
&lt;br /&gt;
OpenSSL's build system does not rely upon &amp;lt;tt&amp;gt;autotools&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;libtool&amp;lt;/tt&amp;gt;. Also see [http://www.openssl.org/support/faq.html#MISC5 Why aren't tools like 'autoconf' and 'libtool' used?] in the OpenSSL FAQ.&lt;br /&gt;
&lt;br /&gt;
== Retrieve source code ==&lt;br /&gt;
&lt;br /&gt;
The OpenSSL source code can be downloaded from [http://www.openssl.org/source/ OpenSSL Source Tarballs] or any suitable [http://www.openssl.org/source/mirror.html ftp mirror]. There are various versions including stable as well as unstable versions. &lt;br /&gt;
&lt;br /&gt;
The source code is managed via Git. Its referred to as Master. The repository is&lt;br /&gt;
&lt;br /&gt;
: git://git.openssl.org/openssl.git&lt;br /&gt;
&lt;br /&gt;
The source is also available via a [https://github.com/openssl/openssl GitHub] mirror. This repository is updated every 15 minutes.&lt;br /&gt;
&lt;br /&gt;
* [[Use_of_Git|Accessing OpenSSL source code via Git]]&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL is configured for a particular platform with protocol and behavior options using &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should avoid custom build systems because they often miss details, like each architecture and platform has a unique &amp;lt;tt&amp;gt;opensslconf.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bn.h&amp;lt;/tt&amp;gt; generated by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Supported Platforms ===&lt;br /&gt;
&lt;br /&gt;
You can run &amp;lt;tt&amp;gt;Configure LIST&amp;lt;/tt&amp;gt; to see a list of available platforms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure LIST&lt;br /&gt;
BC-32&lt;br /&gt;
BS2000-OSD&lt;br /&gt;
BSD-generic32&lt;br /&gt;
BSD-generic64&lt;br /&gt;
BSD-ia64&lt;br /&gt;
BSD-sparc64&lt;br /&gt;
BSD-sparcv8&lt;br /&gt;
BSD-x86&lt;br /&gt;
BSD-x86-elf&lt;br /&gt;
BSD-x86_64&lt;br /&gt;
Cygwin&lt;br /&gt;
Cygwin-x86_64&lt;br /&gt;
DJGPP&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your platform is not listed, then use a similar platform and tune the &amp;lt;tt&amp;gt;$cflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflags&amp;lt;/tt&amp;gt; by making a copy of the configure line and giving it its own name. &amp;lt;tt&amp;gt;$cflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflags&amp;lt;/tt&amp;gt; correspond to fields 2 and 6 in a configure line. An example of using a similar configure line is presented in [[Compilation_and_Installation#Using_RPATHs|Using RPATHs]].&lt;br /&gt;
&lt;br /&gt;
=== Configure &amp;amp; Config ===&lt;br /&gt;
&lt;br /&gt;
You use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; to tune the compile and installation process through options and switches. The difference between is &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; properly handles the host-arch-compiler triplet, and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; does not. &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; attempts to guess the triplet, so its a lot like autotool's &amp;lt;tt&amp;gt;config.guess&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can usually use &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; and it will do the right thing (from Ubuntu 13.04, x64):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config &lt;br /&gt;
Operating system: x86_64-whatever-linux2&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mac OS X can have issues (its often a neglected platform), and you will have to use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; ./Configure darwin64-x86_64-cc&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also configure on Darwin by exporting &amp;lt;tt&amp;gt;KERNEL_BITS&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export KERNEL_BITS=64&lt;br /&gt;
$ ./config shared no-ssl2 no-ssl3 enable-ec_nistp_64_gcc_128 --openssldir=/usr/local/ssl/macosx-x64/&lt;br /&gt;
Operating system: i686-apple-darwinDarwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you provide a option not known to configure or ask for help, then you get a brief help message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure --help&lt;br /&gt;
Usage: Configure [no-&amp;lt;cipher&amp;gt; ...] [enable-&amp;lt;cipher&amp;gt; ...] [experimental-&amp;lt;cipher&amp;gt; ...]&lt;br /&gt;
[-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared]&lt;br /&gt;
[[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR]&lt;br /&gt;
[--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And if you supply an unknown triplet: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure darwin64-x86_64-clang&lt;br /&gt;
Configuring for darwin64-x86_64-clang&lt;br /&gt;
Usage: Configure [no-&amp;lt;cipher&amp;gt; ...] [enable-&amp;lt;cipher&amp;gt; ...] [experimental-&amp;lt;cipher&amp;gt; ...]&lt;br /&gt;
[-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared]&lt;br /&gt;
[[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR]&lt;br /&gt;
[--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]&lt;br /&gt;
&lt;br /&gt;
pick os/compiler from:&lt;br /&gt;
BC-32 BS2000-OSD BSD-generic32 BSD-generic64 BSD-ia64 BSD-sparc64 BSD-sparcv8 &lt;br /&gt;
BSD-x86 BSD-x86-elf BSD-x86_64 Cygwin Cygwin-pre1.3 DJGPP MPE/iX-gcc OS2-EMX &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
NOTE: If in doubt, on Unix-ish systems use './config'.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
If you are prompted to run &amp;lt;tt&amp;gt;make depend&amp;lt;/tt&amp;gt;, then you must do so. For OpenSSL 1.0.2 and below, its required to update the standard distribution once configuration options change.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Since you've disabled or enabled at least one algorithm, you need to do&lt;br /&gt;
the following before building:&lt;br /&gt;
&lt;br /&gt;
	make depend&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 and above performs the dependency step for you, so you should not see the message. However, you should perform a &amp;lt;tt&amp;gt;make clean&amp;lt;/tt&amp;gt; to ensure the list of objects files is accurate after a reconfiguration.&lt;br /&gt;
&lt;br /&gt;
== Configure Options ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL has been around a long time, and it carries around a lot of cruft. For example, from above, SSLv2 is enabled by default. SSLv2 is completely broken, and you should disable it during configuration. You can disable protocols and provide other options through &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and the following lists some of them.&lt;br /&gt;
&lt;br /&gt;
'''Note''': if you specify a non-existent option, then the configure scripts will proceed without warning. For example, if you inadvertently specify '''no-sslv2''' rather than '''no-ssl2 no-ssl3''', the script will configure ''with'' SSLv2 and ''without'' warning for the unknown no-sslv2.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when building a shared object, both the static archive and shared objects are built. You do not need to do anything special to build both when '''shared''' is specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|+ OpenSSL Library Options&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;150px&amp;quot; | Option&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; class=&amp;quot;unsortable&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| --prefix=XXX || See [[#PREFIX_and_OPENSSLDIR|PREFIX and OPENSSLDIR]] in the next section (below).&lt;br /&gt;
|-&lt;br /&gt;
| --openssldir=XXX || See [[#PREFIX_and_OPENSSLDIR|PREFIX and OPENSSLDIR]] in the next section (below).&lt;br /&gt;
|-&lt;br /&gt;
| -d || Debug build of the library. Optimizations are disabled (no &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt; or similar) and &amp;lt;tt&amp;gt;libefence&amp;lt;/tt&amp;gt; is used (&amp;lt;tt&amp;gt;apt-get install electric-fence&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;yum install electric-fence&amp;lt;/tt&amp;gt;). TODO: Any other features?&lt;br /&gt;
|-&lt;br /&gt;
| shared || Build a shared object in addition to the static archive. You probably need a [[#Using_RPATHs|RPATH]] when enabling &amp;lt;tt&amp;gt;shared&amp;lt;/tt&amp;gt; to ensure &amp;lt;tt&amp;gt;openssl&amp;lt;/tt&amp;gt; uses the correct &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; after installation.&lt;br /&gt;
|-&lt;br /&gt;
| enable-ec_nistp_64_gcc_128 || Use on little endian platforms when GCC supports &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt;. ECDH is about 2 to 4 times faster. Not enabled by default because &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; can't determine it. Enable it if your compiler defines &amp;lt;tt&amp;gt;__SIZEOF_INT128__&amp;lt;/tt&amp;gt;, the CPU is little endian and it tolerates unaligned data access.&lt;br /&gt;
|-&lt;br /&gt;
| enable-capieng || Enables the Microsoft CAPI engine on Windows platforms. Used to access the Windows Certificate Store. Also see [http://openssl.6102.n7.nabble.com/Using-Windows-certificate-store-through-OpenSSL-td46788.html Using Windows certificate store through OpenSSL] on the OpenSSL developer list.&lt;br /&gt;
|-&lt;br /&gt;
| no-ssl2 || Disables SSLv2. &amp;lt;tt&amp;gt;OPENSSL_NO_SSL2&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-ssl3 || Disables SSLv3. &amp;lt;tt&amp;gt;OPENSSL_NO_SSL3&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-comp || Disables compression independent of &amp;lt;tt&amp;gt;zlib&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;OPENSSL_NO_COMP&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-idea || Disables IDEA algorithm. Unlike RC5 and MDC2, IDEA is enabled by default&lt;br /&gt;
|-&lt;br /&gt;
| no-asm || Disables assembly language routines (and uses C routines)&lt;br /&gt;
|-&lt;br /&gt;
| no-dtls || Disables DTLS in OpenSSL 1.1.0 and above&lt;br /&gt;
|-&lt;br /&gt;
| no-dtls1 || Disables DTLS in OpenSSL 1.0.2 and below&lt;br /&gt;
|-&lt;br /&gt;
| no-shared || Disables shared objects (only a static library is created)&lt;br /&gt;
|-&lt;br /&gt;
| no-hw || Disables hardware support (useful on mobile devices)&lt;br /&gt;
|-&lt;br /&gt;
| no-engine || Disables hardware support (useful on mobile devices)&lt;br /&gt;
|-&lt;br /&gt;
| no-threads || Disables threading support.&lt;br /&gt;
|-&lt;br /&gt;
| no-dso || Disables the OpenSSL DSO API (the library offers a shared object abstraction layer). If you disable DSO, then you must disable Engines also&lt;br /&gt;
|-&lt;br /&gt;
| no-err || Removes all error function names and error reason text to reduce footprint&lt;br /&gt;
|-&lt;br /&gt;
| no-npn/no-nextprotoneg || Disables Next Protocol Negotiation (NPN). Use &amp;lt;tt&amp;gt;no-nextprotoneg&amp;lt;/tt&amp;gt; for 1.1.0 and above; and &amp;lt;tt&amp;gt;no-npn&amp;lt;/tt&amp;gt; otherwise&lt;br /&gt;
|-&lt;br /&gt;
| no-psk || Disables Preshared Key (PSK). PSK provides mutual authentication independent of trusted authorities, but its rarely offered or used&lt;br /&gt;
|-&lt;br /&gt;
| no-srp || Disables Secure Remote Password (SRP). SRP provides mutual authentication independent of trusted authorities, but its rarely offered or used&lt;br /&gt;
|-&lt;br /&gt;
| no-ec2m || Used when configuring FIPS Capable Library with a FIPS Object Module that only includes prime curves. That is, use this switch if you use &amp;lt;tt&amp;gt;openssl-fips-ecp-2.0.5&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| no-weak-ssl-ciphers || Disables RC4. Available in OpenSSL 1.1.0 and above.&lt;br /&gt;
|-&lt;br /&gt;
| -DXXX || Defines XXX. For example, &amp;lt;tt&amp;gt;-DOPENSSL_NO_HEARTBEATS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| -DPEDANTIC || Defines PEDANTIC. The library will avoid some undefined behavior, like casting an unaligned byte array to a different pointer type. This define should be used if building OpenSSL with undefined behavior sanitizer (&amp;lt;tt&amp;gt;-fsanitize=undefined&amp;lt;/tt&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| -DOPENSSL_USE_IPV6=0 || Disables IPv6. Useful if OpenSSL encounters incorrect or inconsistent platform headers and mistakenly enables IPv6. Must be passed to &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; manually.&lt;br /&gt;
|-&lt;br /&gt;
| -DNO_FORK || Defines NO_FORK. Disables calls to &amp;lt;tt&amp;gt;fork&amp;lt;/tt&amp;gt;. Useful for operating systems like AppleTVOS, WatchOS, AppleTVSimulator and WatchSimulator.&lt;br /&gt;
|-&lt;br /&gt;
| -L''something'', -l''something'', -K''something'', -Wl,''something'' || Linker options, will become part of LDFLAGS.&lt;br /&gt;
|-&lt;br /&gt;
| -''anythingelse'', +''anythingelse'' || Compiler options, will become part of CFLAGS.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''''Note''''': on older OSes, like CentOS 5, BSD 5, and Windows XP or Vista, you will need to configure with &amp;lt;tt&amp;gt;no-async&amp;lt;/tt&amp;gt; when building OpenSSL 1.1.0 and above. The configuration system does not detect lack of the Posix feature on the platforms.&lt;br /&gt;
&lt;br /&gt;
'''''Note''''': you can verify compiler support for &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt; with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# gcc -dM -E - &amp;lt;/dev/null | grep __SIZEOF_INT128__  &lt;br /&gt;
#define __SIZEOF_INT128__ 16&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PREFIX and OPENSSLDIR ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; control the configuration of installed components. The behavior and interactions of &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; are slightly different between OpenSSL 1.0.2 and below, and OpenSSL 1.1.0 and above.&lt;br /&gt;
&lt;br /&gt;
The '''''rule of thumb''''' to use when you want something that &amp;quot;just works&amp;quot; for all recent versions of OpenSSL, including OpenSSL 1.0.2 and 1.1.0, is:&lt;br /&gt;
&lt;br /&gt;
* specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;&lt;br /&gt;
* set &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; to the same location&lt;br /&gt;
&lt;br /&gt;
One word of caution is ''avoid'' &amp;lt;tt&amp;gt;--prefix=/usr&amp;lt;/tt&amp;gt; when OpenSSL versions are '''''not''''' [[Binary_Compatibility|binary compatible]]. You will replace the distro's version of OpenSSL with your version of OpenSSL. It will most likely break everything, including the package management system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''OpenSSL 1.0.2 and below'''&lt;br /&gt;
&lt;br /&gt;
It is usually ''not'' necessary to specify &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; is ''not'' specified, then &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; is used. However, specifying ''only'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; may result in broken builds because the 1.0.2 build system attempts to build in a FIPS configuration.&lt;br /&gt;
&lt;br /&gt;
You can ''omit'' If &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and use &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. In this case, the paths for &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; will be used during configuration. If &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; is not specified, the the default &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used.&lt;br /&gt;
&lt;br /&gt;
The takeaway is &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used by default, and it can be overridden with &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. The rule of thumb applies for path overrides: specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''OpenSSL 1.1.0 and above'''&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 changed the behavior of install rules. You should specify both &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; to ensure &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt; works as expected.&lt;br /&gt;
&lt;br /&gt;
The takeaway is &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used by default, and it can be overridden with ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. The rule of thumb applies for path overrides: specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Debug Configuration ===&lt;br /&gt;
&lt;br /&gt;
From the list above, its possible to quickly configure a &amp;quot;debug&amp;quot; build with &amp;lt;tt&amp;gt;./config -d&amp;lt;/tt&amp;gt;. However, you can often get into a more amicable state ''without'' the [http://en.wikipedia.org/wiki/Electric_Fence Electric Fence] dependency by issuing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config no-asm -g3 -O0 -fno-omit-frame-pointer -fno-inline-functions&lt;br /&gt;
Operating system: x86_64-whatever-linux2&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
Configuring OpenSSL version 1.1.0-pre5-dev (0x0x10100005L)&lt;br /&gt;
    no-asm          [option]   OPENSSL_NO_ASM&lt;br /&gt;
    ...&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
IsMK1MF       =no&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-Wall -O3 -pthread -m64 -DL_ENDIAN  -g3 -O0 -fno-omit-frame-pointer&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Don't be alarmed about both &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;. The last setting ''&amp;quot;sticks&amp;quot;'', and that's the &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you are working in Visual Studio and you can't step into library calls, then see [http://stackoverflow.com/q/38249235 Step into not working, but can force stepping after some asm steps] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
=== Modifying Build Settings ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to work around OpenSSL's selections for building the library. For example, you might want to use &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt; for a mobile device (rather than &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt;), or you might want to use the &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt; compiler (rather than &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In case like these, its often easier to modify &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; rather than trying to add targets to the configure scripts. Below is a patch that modifies &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; for use under the iOS 7.0 SDK (which lacks &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;CFLAG&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;MAKEDEPPROG&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;$(CC) -M&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting and resetting of &amp;lt;tt&amp;gt;LANG&amp;lt;/tt&amp;gt; is required on Mac OSX to work around a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; bug or limitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;OLD_LANG=$LANG&lt;br /&gt;
unset LANG&lt;br /&gt;
&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's|\&amp;quot;iphoneos-cross\&amp;quot;\,\&amp;quot;llvm-gcc\:-O3|\&amp;quot;iphoneos-cross\&amp;quot;\,\&amp;quot;clang\:-Os|g' Configure&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/CC= cc/CC= clang/g' Makefile.org&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/CFLAG= -O/CFLAG= -Os/g' Makefile.org&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/MAKEDEPPROG=makedepend/MAKEDEPPROG=$(CC) -M/g' Makefile.org&lt;br /&gt;
&lt;br /&gt;
export LANG=$OLD_LANG&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After modification, be sure to dclean and configure again so the new settings are picked up:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;make dclean&lt;br /&gt;
&lt;br /&gt;
./config&lt;br /&gt;
make depend&lt;br /&gt;
make all&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using RPATHs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt;'s are supported by default on the BSD platforms, but not others. If you are working on Linux and compatibles, then you have to manually add an RPATH. One of the easiest ways to add a &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; is to configure with it as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config -Wl,-rpath=/usr/local/ssl/lib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For modern Linux you should also use &amp;lt;tt&amp;gt;-Wl,--enable-new-dtags&amp;lt;/tt&amp;gt;. The linker option sets a &amp;lt;tt&amp;gt;RUNPATH&amp;lt;/tt&amp;gt; as opposed to a &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt;. A &amp;lt;tt&amp;gt;RUNPATH&amp;lt;/tt&amp;gt; allows library path overrides at runtime, while a &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; does not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config -Wl,-rpath=/usr/local/ssl/lib -Wl,--enable-new-dtags&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Note well''''': you should use a &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;RUNPATH&amp;lt;/tt&amp;gt; when building both OpenSSL and your program. If you don't add a &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;RUNPATH&amp;lt;/tt&amp;gt; to both, then your program could runtime-link to the wrong version of OpenSSL. Linking against random versions of a security library is ''not'' a good idea.&lt;br /&gt;
&lt;br /&gt;
You can also add an &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;RUNPATH&amp;lt;/tt&amp;gt; by hard coding the &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; into a configure line. For example, on Debian x86_64 open the file &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; in an editor, copy &amp;lt;tt&amp;gt;linux-x86_64&amp;lt;/tt&amp;gt;, name it &amp;lt;tt&amp;gt;linux-x86_64-rpath&amp;lt;/tt&amp;gt;, and make the following change to add the &amp;lt;tt&amp;gt;-rpath&amp;lt;/tt&amp;gt; option. Notice the addition of &amp;lt;tt&amp;gt;-Wl,-rpath=...&amp;lt;/tt&amp;gt; in two places.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;linux-x86_64-rpath&amp;quot;, &amp;quot;gcc:-m64 -DL_ENDIAN -O3 -Wall -Wl,-rpath=/usr/local/ssl/lib::&lt;br /&gt;
  -D_REENTRANT::-Wl,-rpath=/usr/local/ssl/lib -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:&lt;br /&gt;
  ${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64&amp;quot;,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Above, fields 2 and 6 were changed. They correspond to &amp;lt;tt&amp;gt;$cflag&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflag&amp;lt;/tt&amp;gt; in OpenSSL's builds system.&lt;br /&gt;
&lt;br /&gt;
Then, Configure with the new configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure linux-x86_64-rpath shared no-ssl2 no-ssl3 no-comp \&lt;br /&gt;
    --openssldir=/usr/local/ssl enable-ec_nistp_64_gcc_128&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, after &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, verify the settings stuck:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ readelf -d ./libssl.so | grep -i -E 'rpath|runpath'&lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&lt;br /&gt;
$ readelf -d ./libcrypto.so | grep -i rpath&lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&lt;br /&gt;
$ readelf -d ./apps/openssl | grep -i rpath &lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you perform &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt;, then &amp;lt;tt&amp;gt;ldd&amp;lt;/tt&amp;gt; will produce expected results:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ldd /usr/local/ssl/lib/libssl.so&lt;br /&gt;
linux-vdso.so.1 =&amp;gt;  (0x00007ffceff6c000)&lt;br /&gt;
 ibcrypto.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007ff5eff96000)&lt;br /&gt;
...&lt;br /&gt;
    &lt;br /&gt;
$ ldd /usr/local/ssl/bin/openssl &lt;br /&gt;
linux-vdso.so.1 =&amp;gt;  (0x00007ffc30d3a000)&lt;br /&gt;
libssl.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libssl.so.1.0.0 (0x00007f9e8372e000)&lt;br /&gt;
libcrypto.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007f9e832c0000)&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== FIPS Capable Library ===&lt;br /&gt;
&lt;br /&gt;
If you want to use FIPS validated cryptography, you download, build and install the FIPS Object Module (&amp;lt;tt&amp;gt;openssl-fips-2.0.5.tar.gz&amp;lt;/tt&amp;gt;) according to the [https://www.openssl.org/docs/fips/UserGuide-2.0.pdf FIPS User Guide 2.0] and [https://www.openssl.org/docs/fips/SecurityPolicy-2.0.pdf FIPS 140-2 Security Policy]. You then download, build and install the FIPS Capable Library (&amp;lt;tt&amp;gt;openssl-1.0.1e.tar.gz&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
When configuring the FIPS Capable Library, you must use &amp;lt;tt&amp;gt;fips&amp;lt;/tt&amp;gt; as an option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config fips &amp;lt;other options ...&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are configuring the FIPS Capable Library with only prime curves (&amp;lt;tt&amp;gt;openssl-fips-ecp-2.0.5.tar.gz&amp;lt;/tt&amp;gt;), then you must configure with &amp;lt;tt&amp;gt;no-ec2m&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config fips no-ec2m &amp;lt;other options ...&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Compile Time Checking ===&lt;br /&gt;
&lt;br /&gt;
If you disable an option during configure, you can check if it's available through &amp;lt;tt&amp;gt;OPENSSL_NO_*&amp;lt;/tt&amp;gt; defines. OpenSSL writes the configure options to &amp;lt;tt&amp;gt;&amp;lt;openssl/opensslconf.h&amp;gt;&amp;lt;/tt&amp;gt;. For example, if you want to know if SSLv3 is available, then you would perform the following in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/opensslconf.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#if !defined(OPENSSL_NO_SSL3)&lt;br /&gt;
  /* SSLv3 is available */&lt;br /&gt;
#endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compilation ==&lt;br /&gt;
&lt;br /&gt;
After configuring the library, you should run &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;. If prompted, there's usually no need to &amp;lt;tt&amp;gt;make depend&amp;lt;/tt&amp;gt; since you are building from a clean download.&lt;br /&gt;
&lt;br /&gt;
==== Quick ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config &amp;lt;nowiki&amp;gt;&amp;lt;options ...&amp;gt; --openssldir=/usr/local/ssl&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
make&lt;br /&gt;
make test&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Various options can be found examining the &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; file (there is a well commented block at its top). OpenSSL ships with SSLv2, SSLv3 and Compression enabled by default (see &amp;lt;tt&amp;gt;my $disabled&amp;lt;/tt&amp;gt;), so you might want to use &amp;lt;tt&amp;gt;no-ssl2 no-ssl3&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;no-ssl3&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;no-comp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Platfom specific ==&lt;br /&gt;
&lt;br /&gt;
=== Linux ===&lt;br /&gt;
&lt;br /&gt;
==== Intel ====&lt;br /&gt;
&lt;br /&gt;
==== ARM ====&lt;br /&gt;
&lt;br /&gt;
==== X32 (ILP32) ====&lt;br /&gt;
&lt;br /&gt;
X32 uses the 32-bit data model (ILP32) on x86_64/amd64. To properly configure for X32 under current OpenSSL distributions, you must use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and use the x32 triplet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# ./Configure LIST | grep x32&lt;br /&gt;
linux-x32&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# ./Configure linux-x32      &lt;br /&gt;
Configuring OpenSSL version 1.1.0-pre6-dev (0x0x10100006L)&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN (skip dir)&lt;br /&gt;
    ...&lt;br /&gt;
Configuring for linux-x32&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-Wall -O3 -pthread -mx32 -DL_ENDIAN &lt;br /&gt;
SHARED_CFLAG  =-fPIC&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If using an amd64-compatible processor and GCC with that supports &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt;, then you usually add &amp;lt;tt&amp;gt;enable-ec_nistp_64_gcc_128 &amp;lt;/tt&amp;gt; in addition to your other flags.&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
3noch wrote a VERY good guide in 2012 [https://web.archive.org/web/20161123004257/http://developer.covenanteyes.com/building-openssl-for-visual-studio// here] (PLEASE NOTE: the guide was written in 2012 and is no longer available at the original location; the link now points to an archived version at the Internet Archive Wayback Machine).&lt;br /&gt;
&lt;br /&gt;
Like he said in his article, make absolutely sure to create separate directories for 32 and 64 bit versions.&lt;br /&gt;
&lt;br /&gt;
==== W32 / Windows NT - Windows 9x ====&lt;br /&gt;
&lt;br /&gt;
type INSTALL.W32&lt;br /&gt;
&lt;br /&gt;
* you need Perl for Win32.  Unless you will build on Cygwin, you will need ActiveState Perl, available from http://www.activestate.com/ActivePerl.&lt;br /&gt;
* one of the following C compilers:&lt;br /&gt;
** Visual C++&lt;br /&gt;
** Borland C&lt;br /&gt;
** GNU C (Cygwin or MinGW)&lt;br /&gt;
* Netwide Assembler, a.k.a. NASM, available from http://nasm.sourceforge.net/ is required if you intend to utilize assembler modules. Note that NASM is now the only supported assembler.&lt;br /&gt;
&lt;br /&gt;
==== W64 ====&lt;br /&gt;
&lt;br /&gt;
Read first the INSTALL.W64 documentation note containing some specific 64bits information.&lt;br /&gt;
See also INSTALL.W32 that still provides additonnal build information common to both the 64 and 32 bit versions.&lt;br /&gt;
&lt;br /&gt;
You may be surprised: the 64bit artefacts are indeed output in the out32* sub-directories and bear names ending *32.dll. Fact is the 64 bit compile target is so far an incremental change over the legacy 32bit windows target. Numerous compile flags are still labelled &amp;quot;32&amp;quot; although those do apply to both 32 and 64bit targets.&lt;br /&gt;
&lt;br /&gt;
The important pre-requisites are to have PERL available (for essential file processing so as to prepare sources and scripts for the target OS) and of course a C compiler like Microsoft Visual Studio for C/C++. Also note the procedure changed at OpenSSL 1.1.0 and is more streamlined. Also see [https://stackoverflow.com/q/39076244/608639 Why there is no ms\do_ms.bat after perl Configure VC-WIN64A] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.1.0 ===&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 and above perform these steps:&lt;br /&gt;
&lt;br /&gt;
# Ensure you have perl installed on your machine (e.g. ActiveState or Strawberry), and available on your %PATH%&lt;br /&gt;
# Ensure you have NASM installed on your machine, and available on your %PATH%&lt;br /&gt;
# Extract the source files to your folder, here &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# Launch Visual Studio tool x64 Cross Tools Command prompt&lt;br /&gt;
# Goto your defined folder &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure for the target OS with &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt; or other configurations to be found in the INSTALL file (e.g. UNIX targets). &lt;br /&gt;
## For instance: &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;.&lt;br /&gt;
# (''Optional'') In case you compiled before on 32 or 64-bits, make sure you run &amp;lt;code&amp;gt;nmake clean&amp;lt;/code&amp;gt; to prevent trouble across 32 and 64-bits which share output folder.&lt;br /&gt;
# Now build with: &amp;lt;code&amp;gt;nmake&amp;lt;/code&amp;gt;&lt;br /&gt;
# Output can be found in the '''root''' of your folder as '''libcrypto-1_1x64.dll''' and '''libssl-1_1-x64.dll''' (with all the build additionals such as .pdb .lik or static .lib). You may check this is true 64bit code using the Visual Studio tool 'dumpbin'. For instance &amp;lt;code&amp;gt;dumpbin  /headers libcrypto-1_1x64.dll | more&amp;lt;/code&amp;gt;, and look at the FILE HEADER section.&lt;br /&gt;
# Test the code using the 'test' make target, by running &amp;lt;code&amp;gt;nmake test&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Reminder, clean your code to prevent issues the next time you compile for a different target. See step 7.&lt;br /&gt;
&lt;br /&gt;
==== Windows CE ====&lt;br /&gt;
'' Not specified ''&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.0.2 ===&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.0.2 and earlier the procedure is as follows.&lt;br /&gt;
&lt;br /&gt;
# Ensure you have perl installed on your machine (e.g. ActiveState or Strawberry), and available on your %PATH%&lt;br /&gt;
# Ensure you have NASM installed on your machine, and available on your %PATH%&lt;br /&gt;
# launch a Visual Studio tool x64 Cross Tools Command prompt&lt;br /&gt;
# change to the directory where you have copied openssl sources &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# configure for the target OS with the command &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;. You may also be interested to set more configuration options as documented in the general INSTALL note (for UNIX targets). For instance: &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;.&lt;br /&gt;
# prepare the target environment with the command: &amp;lt;code&amp;gt;ms\do_win64a&amp;lt;/code&amp;gt;&lt;br /&gt;
# ensure you start afresh and notably without linkable products from a previous 32bit compile (as 32 and 64 bits compiling still share common directories) with the command: &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak clean&amp;lt;/code&amp;gt; for the DLL target and &amp;lt;code&amp;gt;nmake -f ms\nt.mak clean&amp;lt;/code&amp;gt; for static libraries.&lt;br /&gt;
# build the code with: &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak&amp;lt;/code&amp;gt; (respectively &amp;lt;code&amp;gt;nmake -f ms\nt.mak&amp;lt;/code&amp;gt; )&lt;br /&gt;
# the artefacts will be found in sub directories out32dll and out32dll.dbg (respectively out32 and out32.dbg for static libraries). The libcrypto and ssl libraries are still named libeay32.lib and ssleay32.lib, and associated includes in inc32 ! You may check this is true 64bit code using the Visual Studio tool 'dumpbin'. For instance &amp;lt;code&amp;gt;dumpbin  /headers out32dll/libeay32.lib | more&amp;lt;/code&amp;gt;, and look at the FILE HEADER section.&lt;br /&gt;
# test the code using the various *test.exe programs in out32dll. Use the 'test' make target to run all tests as in &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak test&amp;lt;/code&amp;gt;&lt;br /&gt;
# we recommend that you move/copy needed includes and libraries from the &amp;quot;32&amp;quot; directories under a new explicit directory tree for 64bit applications from where you will import and link your target applications, similar to that explained in INSTALL.W32.&lt;br /&gt;
&lt;br /&gt;
==== Windows CE ====&lt;br /&gt;
&lt;br /&gt;
=== OS X ===&lt;br /&gt;
&lt;br /&gt;
The earlier discussion presented a lot of information (and some of it had OS X information). Here are the TLDR versions to configure, build and install the library.&lt;br /&gt;
&lt;br /&gt;
If configuring for 64-bit OS X, then use a command similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./Configure darwin64-x86_64-cc shared enable-ec_nistp_64_gcc_128 no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl/macos-x86_64&lt;br /&gt;
make depend&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If configuring for 32-bit OS X, then use a command similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./Configure darwin-i386-cc shared no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl/macosx-i386&lt;br /&gt;
make depend&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to build a multiarch OpenSSL library, then see this answer on Stack Overflow: [http://stackoverflow.com/a/25531033/608639 Build Multiarch OpenSSL on OS X].&lt;br /&gt;
&lt;br /&gt;
=== iOS ===&lt;br /&gt;
&lt;br /&gt;
The following builds OpenSSL for iOS using the iPhoneOS SDK. The configuration avoids the dynamic library the DSO interface and engines.&lt;br /&gt;
&lt;br /&gt;
If you run &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt;, then the headers will be installed in &amp;lt;tt&amp;gt;/usr/local/openssl-ios/include&amp;lt;/tt&amp;gt; and libraries will be installed in &amp;lt;tt&amp;gt;/usr/local/openssl-ios/lib&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== 32-bit ====&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 and above, a 32-bit iOS cross-compiles uses the &amp;lt;tt&amp;gt;ios-cross&amp;lt;/tt&amp;gt; target, and options similar to &amp;lt;tt&amp;gt;--prefix=/usr/local/openssl-ios&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure ios-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios&lt;br /&gt;
&lt;br /&gt;
Configuring OpenSSL version 1.1.1-dev (0x10101000L)&lt;br /&gt;
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-dynamic-engine [forced]&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
Configuring for ios-cross&lt;br /&gt;
&lt;br /&gt;
PERL          =perl&lt;br /&gt;
PERLVERSION   =5.16.2 for darwin-thread-multi-2level&lt;br /&gt;
HASHBANGPERL  =/usr/bin/env perl&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-O3 -D_REENTRANT -arch armv7 -mios-version-min=6.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
CXX           =c++&lt;br /&gt;
CXXFLAG       =-O3 -D_REENTRANT -arch armv7 -mios-version-min=6.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
DEFINES       =NDEBUG OPENSSL_THREADS OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_PIC OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_GF2m SHA1_ASM SHA256_ASM SHA512_ASM AES_ASM BSAES_ASM GHASH_ASM ECP_NISTZ256_ASM POLY1305_ASM&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are working with OpenSSL 1.0.2 or below, then use the &amp;lt;tt&amp;gt;iphoneos-cross&amp;lt;/tt&amp;gt; target.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure iphoneos-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios&lt;br /&gt;
Configuring for iphoneos-cross&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-engine       [option]   OPENSSL_NO_ENGINE (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-hw           [option]   OPENSSL_NO_HW&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS (skip dir)&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
IsMK1MF=0&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-DOPENSSL_THREADS -D_REENTRANT -O3 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fomit-frame-pointer -fno-common&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 64-bit ====&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 , a 64-bit iOS cross-compiles uses the &amp;lt;tt&amp;gt;ios64-cross&amp;lt;/tt&amp;gt; target, and &amp;lt;tt&amp;gt;--prefix=/usr/local/openssl-ios64&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;ios64-cross&amp;lt;/tt&amp;gt;. There is no built-in 64-bit iOS support for OpenSSL 1.0.2 or below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure ios64-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios64&lt;br /&gt;
&lt;br /&gt;
Configuring OpenSSL version 1.1.1-dev (0x10101000L)&lt;br /&gt;
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-dynamic-engine [forced]&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
Configuring for ios64-cross&lt;br /&gt;
&lt;br /&gt;
PERL          =perl&lt;br /&gt;
PERLVERSION   =5.16.2 for darwin-thread-multi-2level&lt;br /&gt;
HASHBANGPERL  =/usr/bin/env perl&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
CXX           =c++&lt;br /&gt;
CXXFLAG       =-O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
DEFINES       =NDEBUG OPENSSL_THREADS OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_PIC OPENSSL_BN_ASM_MONT SHA1_ASM SHA256_ASM SHA512_ASM VPAES_ASM ECP_NISTZ256_ASM POLY1305_ASM&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Android ===&lt;br /&gt;
&lt;br /&gt;
Visit [[Android]] and [[FIPS Library and Android]].&lt;br /&gt;
&lt;br /&gt;
=== More ===&lt;br /&gt;
&lt;br /&gt;
==== VAX/VMS ====&lt;br /&gt;
&lt;br /&gt;
I you wonder what are files ending with .com like test/testca.com those are VAX/VMX scripts.&lt;br /&gt;
This code is still maintained.&lt;br /&gt;
&lt;br /&gt;
==== OS/2 ====&lt;br /&gt;
&lt;br /&gt;
==== NetWare ====&lt;br /&gt;
5.x 6.x&lt;br /&gt;
&lt;br /&gt;
==== HP-UX ====&lt;br /&gt;
[[HP-UX Itanium FIPS and OpenSSL build]]&lt;br /&gt;
&lt;br /&gt;
==Autoconf==&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses its own configuration system, and does not use Autoconf. However, a number of popular projects use both OpenSSL and Autoconf, and it would be useful to detect either &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. To craft a feature test for OpenSSL that recognizes both &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;, you can use the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if test &amp;quot;$with_openssl&amp;quot; = yes ; then&lt;br /&gt;
  dnl Order matters!&lt;br /&gt;
  if test &amp;quot;$PORTNAME&amp;quot; != &amp;quot;win32&amp;quot;; then&lt;br /&gt;
     AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_CHECK_LIB(ssl, OPENSSL_init_ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_CHECK_LIB(ssl, SSL_library_init, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])])&lt;br /&gt;
  else&lt;br /&gt;
     AC_SEARCH_LIBS(CRYPTO_new_ex_data, eay32 crypto, [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_SEARCH_LIBS(OPENSSL_init_ssl, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_SEARCH_LIBS(SSL_library_init, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])&lt;br /&gt;
  fi&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many thanks to the Postgres folks for donating part of their &amp;lt;tt&amp;gt;configure.in&amp;lt;/tt&amp;gt;. Also see [http://stackoverflow.com/q/39285733 How to tell Autoconf “require symbol A or B” from LIB?] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
[[Category:Shell level]]&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
[[Category:Compilation]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Compilation_and_Installation&amp;diff=3166</id>
		<title>Compilation and Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Compilation_and_Installation&amp;diff=3166"/>
		<updated>2021-03-29T19:14:04Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on RUNPATHs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following page is a combination of the &amp;lt;tt&amp;gt;INSTALL&amp;lt;/tt&amp;gt; file provided with the OpenSSL library and notes from the field. If you have questions about what you are doing or seeing, then you should consult &amp;lt;tt&amp;gt;INSTALL&amp;lt;/tt&amp;gt; since it contains the commands and specifies the behavior by the development team.&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses a custom build system to configure the library. Configuration will allow the library to set up the recursive makefiles from &amp;lt;tt&amp;gt;makefile.org&amp;lt;/tt&amp;gt;. Once configured, you use &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; to build the library. You should avoid custom build systems because they often miss details, like each architecture and platform has a unique &amp;lt;tt&amp;gt;opensslconf.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bn.h&amp;lt;/tt&amp;gt; generated by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You must use a C compiler to build the OpenSSL library. You cannot use a C++ compiler. Later, once the library is built, it is OK to create user programs with a C++ compiler. But the library proper must be built with a C compiler.&lt;br /&gt;
&lt;br /&gt;
There are two generations of build system. First is the build system used in OpenSSL 1.0.2 and below. The instructions below apply to it. Second is the build system for OpenSSL 1.1.0 and above. The instructions are similar, but not the same. For example, the second generation abandons the monolithic &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and places individual configurations in the &amp;lt;tt&amp;gt;Configurations&amp;lt;/tt&amp;gt; directory.  Also, the second generation is more platform agnostic and uses templates to produce a final, top level build file (&amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;descrip.mms&amp;lt;/tt&amp;gt;, what have you).&lt;br /&gt;
&lt;br /&gt;
After you configure and build the library, you should always perform a &amp;lt;tt&amp;gt;make test&amp;lt;/tt&amp;gt; to ensure the library performs as expected under its self tests. If you are building OpenSSL 1.1.0 and above, then you will also need PERL 5.10 or higher (see &amp;lt;tt&amp;gt;README.PERL&amp;lt;/tt&amp;gt; for details).&lt;br /&gt;
&lt;br /&gt;
OpenSSL's build system does not rely upon &amp;lt;tt&amp;gt;autotools&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;libtool&amp;lt;/tt&amp;gt;. Also see [http://www.openssl.org/support/faq.html#MISC5 Why aren't tools like 'autoconf' and 'libtool' used?] in the OpenSSL FAQ.&lt;br /&gt;
&lt;br /&gt;
== Retrieve source code ==&lt;br /&gt;
&lt;br /&gt;
The OpenSSL source code can be downloaded from [http://www.openssl.org/source/ OpenSSL Source Tarballs] or any suitable [http://www.openssl.org/source/mirror.html ftp mirror]. There are various versions including stable as well as unstable versions. &lt;br /&gt;
&lt;br /&gt;
The source code is managed via Git. Its referred to as Master. The repository is&lt;br /&gt;
&lt;br /&gt;
: git://git.openssl.org/openssl.git&lt;br /&gt;
&lt;br /&gt;
The source is also available via a [https://github.com/openssl/openssl GitHub] mirror. This repository is updated every 15 minutes.&lt;br /&gt;
&lt;br /&gt;
* [[Use_of_Git|Accessing OpenSSL source code via Git]]&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL is configured for a particular platform with protocol and behavior options using &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should avoid custom build systems because they often miss details, like each architecture and platform has a unique &amp;lt;tt&amp;gt;opensslconf.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bn.h&amp;lt;/tt&amp;gt; generated by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Supported Platforms ===&lt;br /&gt;
&lt;br /&gt;
You can run &amp;lt;tt&amp;gt;Configure LIST&amp;lt;/tt&amp;gt; to see a list of available platforms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure LIST&lt;br /&gt;
BC-32&lt;br /&gt;
BS2000-OSD&lt;br /&gt;
BSD-generic32&lt;br /&gt;
BSD-generic64&lt;br /&gt;
BSD-ia64&lt;br /&gt;
BSD-sparc64&lt;br /&gt;
BSD-sparcv8&lt;br /&gt;
BSD-x86&lt;br /&gt;
BSD-x86-elf&lt;br /&gt;
BSD-x86_64&lt;br /&gt;
Cygwin&lt;br /&gt;
Cygwin-x86_64&lt;br /&gt;
DJGPP&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your platform is not listed, then use a similar platform and tune the &amp;lt;tt&amp;gt;$cflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflags&amp;lt;/tt&amp;gt; by making a copy of the configure line and giving it its own name. &amp;lt;tt&amp;gt;$cflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflags&amp;lt;/tt&amp;gt; correspond to fields 2 and 6 in a configure line. An example of using a similar configure line is presented in [[Compilation_and_Installation#Using_RPATHs|Using RPATHs]].&lt;br /&gt;
&lt;br /&gt;
=== Configure &amp;amp; Config ===&lt;br /&gt;
&lt;br /&gt;
You use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; to tune the compile and installation process through options and switches. The difference between is &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; properly handles the host-arch-compiler triplet, and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; does not. &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; attempts to guess the triplet, so its a lot like autotool's &amp;lt;tt&amp;gt;config.guess&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can usually use &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; and it will do the right thing (from Ubuntu 13.04, x64):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config &lt;br /&gt;
Operating system: x86_64-whatever-linux2&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mac OS X can have issues (its often a neglected platform), and you will have to use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; ./Configure darwin64-x86_64-cc&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also configure on Darwin by exporting &amp;lt;tt&amp;gt;KERNEL_BITS&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export KERNEL_BITS=64&lt;br /&gt;
$ ./config shared no-ssl2 no-ssl3 enable-ec_nistp_64_gcc_128 --openssldir=/usr/local/ssl/macosx-x64/&lt;br /&gt;
Operating system: i686-apple-darwinDarwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you provide a option not known to configure or ask for help, then you get a brief help message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure --help&lt;br /&gt;
Usage: Configure [no-&amp;lt;cipher&amp;gt; ...] [enable-&amp;lt;cipher&amp;gt; ...] [experimental-&amp;lt;cipher&amp;gt; ...]&lt;br /&gt;
[-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared]&lt;br /&gt;
[[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR]&lt;br /&gt;
[--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And if you supply an unknown triplet: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure darwin64-x86_64-clang&lt;br /&gt;
Configuring for darwin64-x86_64-clang&lt;br /&gt;
Usage: Configure [no-&amp;lt;cipher&amp;gt; ...] [enable-&amp;lt;cipher&amp;gt; ...] [experimental-&amp;lt;cipher&amp;gt; ...]&lt;br /&gt;
[-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared]&lt;br /&gt;
[[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR]&lt;br /&gt;
[--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]&lt;br /&gt;
&lt;br /&gt;
pick os/compiler from:&lt;br /&gt;
BC-32 BS2000-OSD BSD-generic32 BSD-generic64 BSD-ia64 BSD-sparc64 BSD-sparcv8 &lt;br /&gt;
BSD-x86 BSD-x86-elf BSD-x86_64 Cygwin Cygwin-pre1.3 DJGPP MPE/iX-gcc OS2-EMX &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
NOTE: If in doubt, on Unix-ish systems use './config'.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
If you are prompted to run &amp;lt;tt&amp;gt;make depend&amp;lt;/tt&amp;gt;, then you must do so. For OpenSSL 1.0.2 and below, its required to update the standard distribution once configuration options change.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Since you've disabled or enabled at least one algorithm, you need to do&lt;br /&gt;
the following before building:&lt;br /&gt;
&lt;br /&gt;
	make depend&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 and above performs the dependency step for you, so you should not see the message. However, you should perform a &amp;lt;tt&amp;gt;make clean&amp;lt;/tt&amp;gt; to ensure the list of objects files is accurate after a reconfiguration.&lt;br /&gt;
&lt;br /&gt;
== Configure Options ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL has been around a long time, and it carries around a lot of cruft. For example, from above, SSLv2 is enabled by default. SSLv2 is completely broken, and you should disable it during configuration. You can disable protocols and provide other options through &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and the following lists some of them.&lt;br /&gt;
&lt;br /&gt;
'''Note''': if you specify a non-existent option, then the configure scripts will proceed without warning. For example, if you inadvertently specify '''no-sslv2''' rather than '''no-ssl2 no-ssl3''', the script will configure ''with'' SSLv2 and ''without'' warning for the unknown no-sslv2.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when building a shared object, both the static archive and shared objects are built. You do not need to do anything special to build both when '''shared''' is specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|+ OpenSSL Library Options&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;150px&amp;quot; | Option&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; class=&amp;quot;unsortable&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| --prefix=XXX || See [[#PREFIX_and_OPENSSLDIR|PREFIX and OPENSSLDIR]] in the next section (below).&lt;br /&gt;
|-&lt;br /&gt;
| --openssldir=XXX || See [[#PREFIX_and_OPENSSLDIR|PREFIX and OPENSSLDIR]] in the next section (below).&lt;br /&gt;
|-&lt;br /&gt;
| -d || Debug build of the library. Optimizations are disabled (no &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt; or similar) and &amp;lt;tt&amp;gt;libefence&amp;lt;/tt&amp;gt; is used (&amp;lt;tt&amp;gt;apt-get install electric-fence&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;yum install electric-fence&amp;lt;/tt&amp;gt;). TODO: Any other features?&lt;br /&gt;
|-&lt;br /&gt;
| shared || Build a shared object in addition to the static archive. You probably need a [[#Using_RPATHs|RPATH]] when enabling &amp;lt;tt&amp;gt;shared&amp;lt;/tt&amp;gt; to ensure &amp;lt;tt&amp;gt;openssl&amp;lt;/tt&amp;gt; uses the correct &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; after installation.&lt;br /&gt;
|-&lt;br /&gt;
| enable-ec_nistp_64_gcc_128 || Use on little endian platforms when GCC supports &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt;. ECDH is about 2 to 4 times faster. Not enabled by default because &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; can't determine it. Enable it if your compiler defines &amp;lt;tt&amp;gt;__SIZEOF_INT128__&amp;lt;/tt&amp;gt;, the CPU is little endian and it tolerates unaligned data access.&lt;br /&gt;
|-&lt;br /&gt;
| enable-capieng || Enables the Microsoft CAPI engine on Windows platforms. Used to access the Windows Certificate Store. Also see [http://openssl.6102.n7.nabble.com/Using-Windows-certificate-store-through-OpenSSL-td46788.html Using Windows certificate store through OpenSSL] on the OpenSSL developer list.&lt;br /&gt;
|-&lt;br /&gt;
| no-ssl2 || Disables SSLv2. &amp;lt;tt&amp;gt;OPENSSL_NO_SSL2&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-ssl3 || Disables SSLv3. &amp;lt;tt&amp;gt;OPENSSL_NO_SSL3&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-comp || Disables compression independent of &amp;lt;tt&amp;gt;zlib&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;OPENSSL_NO_COMP&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-idea || Disables IDEA algorithm. Unlike RC5 and MDC2, IDEA is enabled by default&lt;br /&gt;
|-&lt;br /&gt;
| no-asm || Disables assembly language routines (and uses C routines)&lt;br /&gt;
|-&lt;br /&gt;
| no-dtls || Disables DTLS in OpenSSL 1.1.0 and above&lt;br /&gt;
|-&lt;br /&gt;
| no-dtls1 || Disables DTLS in OpenSSL 1.0.2 and below&lt;br /&gt;
|-&lt;br /&gt;
| no-shared || Disables shared objects (only a static library is created)&lt;br /&gt;
|-&lt;br /&gt;
| no-hw || Disables hardware support (useful on mobile devices)&lt;br /&gt;
|-&lt;br /&gt;
| no-engine || Disables hardware support (useful on mobile devices)&lt;br /&gt;
|-&lt;br /&gt;
| no-threads || Disables threading support.&lt;br /&gt;
|-&lt;br /&gt;
| no-dso || Disables the OpenSSL DSO API (the library offers a shared object abstraction layer). If you disable DSO, then you must disable Engines also&lt;br /&gt;
|-&lt;br /&gt;
| no-err || Removes all error function names and error reason text to reduce footprint&lt;br /&gt;
|-&lt;br /&gt;
| no-npn/no-nextprotoneg || Disables Next Protocol Negotiation (NPN). Use &amp;lt;tt&amp;gt;no-nextprotoneg&amp;lt;/tt&amp;gt; for 1.1.0 and above; and &amp;lt;tt&amp;gt;no-npn&amp;lt;/tt&amp;gt; otherwise&lt;br /&gt;
|-&lt;br /&gt;
| no-psk || Disables Preshared Key (PSK). PSK provides mutual authentication independent of trusted authorities, but its rarely offered or used&lt;br /&gt;
|-&lt;br /&gt;
| no-srp || Disables Secure Remote Password (SRP). SRP provides mutual authentication independent of trusted authorities, but its rarely offered or used&lt;br /&gt;
|-&lt;br /&gt;
| no-ec2m || Used when configuring FIPS Capable Library with a FIPS Object Module that only includes prime curves. That is, use this switch if you use &amp;lt;tt&amp;gt;openssl-fips-ecp-2.0.5&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| no-weak-ssl-ciphers || Disables RC4. Available in OpenSSL 1.1.0 and above.&lt;br /&gt;
|-&lt;br /&gt;
| -DXXX || Defines XXX. For example, &amp;lt;tt&amp;gt;-DOPENSSL_NO_HEARTBEATS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| -DPEDANTIC || Defines PEDANTIC. The library will avoid some undefined behavior, like casting an unaligned byte array to a different pointer type. This define should be used if building OpenSSL with undefined behavior sanitizer (&amp;lt;tt&amp;gt;-fsanitize=undefined&amp;lt;/tt&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| -DOPENSSL_USE_IPV6=0 || Disables IPv6. Useful if OpenSSL encounters incorrect or inconsistent platform headers and mistakenly enables IPv6. Must be passed to &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; manually.&lt;br /&gt;
|-&lt;br /&gt;
| -DNO_FORK || Defines NO_FORK. Disables calls to &amp;lt;tt&amp;gt;fork&amp;lt;/tt&amp;gt;. Useful for operating systems like AppleTVOS, WatchOS, AppleTVSimulator and WatchSimulator.&lt;br /&gt;
|-&lt;br /&gt;
| -L''something'', -l''something'', -K''something'', -Wl,''something'' || Linker options, will become part of LDFLAGS.&lt;br /&gt;
|-&lt;br /&gt;
| -''anythingelse'', +''anythingelse'' || Compiler options, will become part of CFLAGS.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''''Note''''': on older OSes, like CentOS 5, BSD 5, and Windows XP or Vista, you will need to configure with &amp;lt;tt&amp;gt;no-async&amp;lt;/tt&amp;gt; when building OpenSSL 1.1.0 and above. The configuration system does not detect lack of the Posix feature on the platforms.&lt;br /&gt;
&lt;br /&gt;
'''''Note''''': you can verify compiler support for &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt; with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# gcc -dM -E - &amp;lt;/dev/null | grep __SIZEOF_INT128__  &lt;br /&gt;
#define __SIZEOF_INT128__ 16&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PREFIX and OPENSSLDIR ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; control the configuration of installed components. The behavior and interactions of &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; are slightly different between OpenSSL 1.0.2 and below, and OpenSSL 1.1.0 and above.&lt;br /&gt;
&lt;br /&gt;
The '''''rule of thumb''''' to use when you want something that &amp;quot;just works&amp;quot; for all recent versions of OpenSSL, including OpenSSL 1.0.2 and 1.1.0, is:&lt;br /&gt;
&lt;br /&gt;
* specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;&lt;br /&gt;
* set &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; to the same location&lt;br /&gt;
&lt;br /&gt;
One word of caution is ''avoid'' &amp;lt;tt&amp;gt;--prefix=/usr&amp;lt;/tt&amp;gt; when OpenSSL versions are '''''not''''' [[Binary_Compatibility|binary compatible]]. You will replace the distro's version of OpenSSL with your version of OpenSSL. It will most likely break everything, including the package management system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''OpenSSL 1.0.2 and below'''&lt;br /&gt;
&lt;br /&gt;
It is usually ''not'' necessary to specify &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; is ''not'' specified, then &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; is used. However, specifying ''only'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; may result in broken builds because the 1.0.2 build system attempts to build in a FIPS configuration.&lt;br /&gt;
&lt;br /&gt;
You can ''omit'' If &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and use &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. In this case, the paths for &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; will be used during configuration. If &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; is not specified, the the default &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used.&lt;br /&gt;
&lt;br /&gt;
The takeaway is &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used by default, and it can be overridden with &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. The rule of thumb applies for path overrides: specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''OpenSSL 1.1.0 and above'''&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 changed the behavior of install rules. You should specify both &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; to ensure &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt; works as expected.&lt;br /&gt;
&lt;br /&gt;
The takeaway is &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used by default, and it can be overridden with ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. The rule of thumb applies for path overrides: specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Debug Configuration ===&lt;br /&gt;
&lt;br /&gt;
From the list above, its possible to quickly configure a &amp;quot;debug&amp;quot; build with &amp;lt;tt&amp;gt;./config -d&amp;lt;/tt&amp;gt;. However, you can often get into a more amicable state ''without'' the [http://en.wikipedia.org/wiki/Electric_Fence Electric Fence] dependency by issuing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config no-asm -g3 -O0 -fno-omit-frame-pointer -fno-inline-functions&lt;br /&gt;
Operating system: x86_64-whatever-linux2&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
Configuring OpenSSL version 1.1.0-pre5-dev (0x0x10100005L)&lt;br /&gt;
    no-asm          [option]   OPENSSL_NO_ASM&lt;br /&gt;
    ...&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
IsMK1MF       =no&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-Wall -O3 -pthread -m64 -DL_ENDIAN  -g3 -O0 -fno-omit-frame-pointer&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Don't be alarmed about both &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;. The last setting ''&amp;quot;sticks&amp;quot;'', and that's the &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you are working in Visual Studio and you can't step into library calls, then see [http://stackoverflow.com/q/38249235 Step into not working, but can force stepping after some asm steps] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
=== Modifying Build Settings ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to work around OpenSSL's selections for building the library. For example, you might want to use &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt; for a mobile device (rather than &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt;), or you might want to use the &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt; compiler (rather than &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In case like these, its often easier to modify &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; rather than trying to add targets to the configure scripts. Below is a patch that modifies &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; for use under the iOS 7.0 SDK (which lacks &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;CFLAG&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;MAKEDEPPROG&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;$(CC) -M&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting and resetting of &amp;lt;tt&amp;gt;LANG&amp;lt;/tt&amp;gt; is required on Mac OSX to work around a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; bug or limitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;OLD_LANG=$LANG&lt;br /&gt;
unset LANG&lt;br /&gt;
&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's|\&amp;quot;iphoneos-cross\&amp;quot;\,\&amp;quot;llvm-gcc\:-O3|\&amp;quot;iphoneos-cross\&amp;quot;\,\&amp;quot;clang\:-Os|g' Configure&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/CC= cc/CC= clang/g' Makefile.org&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/CFLAG= -O/CFLAG= -Os/g' Makefile.org&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/MAKEDEPPROG=makedepend/MAKEDEPPROG=$(CC) -M/g' Makefile.org&lt;br /&gt;
&lt;br /&gt;
export LANG=$OLD_LANG&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After modification, be sure to dclean and configure again so the new settings are picked up:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;make dclean&lt;br /&gt;
&lt;br /&gt;
./config&lt;br /&gt;
make depend&lt;br /&gt;
make all&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using RPATHs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt;'s are supported by default on the BSD platforms, but not others. If you are working on Linux and compatibles, then you have to manually add an RPATH. One of the easiest ways to add a &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; is to configure with it as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config -Wl,-rpath=/usr/local/ssl/lib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For modern Linux you should also use &amp;lt;tt&amp;gt;-Wl,--enable-new-dtags&amp;lt;/tt&amp;gt;. The linker option sets a RUNPATH as opposed to a RPATH. A RUNPATH allows runtime path overrides, while a RPATH does not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config -Wl,-rpath=/usr/local/ssl/lib -Wl,--enable-new-dtags&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Note well''''': you should use a RPATH or RUNPATH when building both OpenSSL and your program. If you don't add a RPATH or RUNPATH to both, then your program could runtime-link to the wrong version of OpenSSL. Linking against random versions of a security library is ''not'' a good idea.&lt;br /&gt;
&lt;br /&gt;
You can also add an &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;RUNPATH&amp;lt;/tt&amp;gt; by hard coding the &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; into a configure line. For example, on Debian x86_64 open the file &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; in an editor, copy &amp;lt;tt&amp;gt;linux-x86_64&amp;lt;/tt&amp;gt;, name it &amp;lt;tt&amp;gt;linux-x86_64-rpath&amp;lt;/tt&amp;gt;, and make the following change to add the &amp;lt;tt&amp;gt;-rpath&amp;lt;/tt&amp;gt; option. Notice the addition of &amp;lt;tt&amp;gt;-Wl,-rpath=...&amp;lt;/tt&amp;gt; in two places.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;linux-x86_64-rpath&amp;quot;, &amp;quot;gcc:-m64 -DL_ENDIAN -O3 -Wall -Wl,-rpath=/usr/local/ssl/lib::&lt;br /&gt;
  -D_REENTRANT::-Wl,-rpath=/usr/local/ssl/lib -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:&lt;br /&gt;
  ${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64&amp;quot;,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Above, fields 2 and 6 were changed. They correspond to &amp;lt;tt&amp;gt;$cflag&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflag&amp;lt;/tt&amp;gt; in OpenSSL's builds system.&lt;br /&gt;
&lt;br /&gt;
Then, Configure with the new configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure linux-x86_64-rpath shared no-ssl2 no-ssl3 no-comp \&lt;br /&gt;
    --openssldir=/usr/local/ssl enable-ec_nistp_64_gcc_128&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, after &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, verify the settings stuck:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ readelf -d ./libssl.so | grep -i -E 'rpath|runpath'&lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&lt;br /&gt;
$ readelf -d ./libcrypto.so | grep -i rpath&lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&lt;br /&gt;
$ readelf -d ./apps/openssl | grep -i rpath &lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you perform &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt;, then &amp;lt;tt&amp;gt;ldd&amp;lt;/tt&amp;gt; will produce expected results:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ldd /usr/local/ssl/lib/libssl.so&lt;br /&gt;
linux-vdso.so.1 =&amp;gt;  (0x00007ffceff6c000)&lt;br /&gt;
 ibcrypto.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007ff5eff96000)&lt;br /&gt;
...&lt;br /&gt;
    &lt;br /&gt;
$ ldd /usr/local/ssl/bin/openssl &lt;br /&gt;
linux-vdso.so.1 =&amp;gt;  (0x00007ffc30d3a000)&lt;br /&gt;
libssl.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libssl.so.1.0.0 (0x00007f9e8372e000)&lt;br /&gt;
libcrypto.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007f9e832c0000)&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== FIPS Capable Library ===&lt;br /&gt;
&lt;br /&gt;
If you want to use FIPS validated cryptography, you download, build and install the FIPS Object Module (&amp;lt;tt&amp;gt;openssl-fips-2.0.5.tar.gz&amp;lt;/tt&amp;gt;) according to the [https://www.openssl.org/docs/fips/UserGuide-2.0.pdf FIPS User Guide 2.0] and [https://www.openssl.org/docs/fips/SecurityPolicy-2.0.pdf FIPS 140-2 Security Policy]. You then download, build and install the FIPS Capable Library (&amp;lt;tt&amp;gt;openssl-1.0.1e.tar.gz&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
When configuring the FIPS Capable Library, you must use &amp;lt;tt&amp;gt;fips&amp;lt;/tt&amp;gt; as an option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config fips &amp;lt;other options ...&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are configuring the FIPS Capable Library with only prime curves (&amp;lt;tt&amp;gt;openssl-fips-ecp-2.0.5.tar.gz&amp;lt;/tt&amp;gt;), then you must configure with &amp;lt;tt&amp;gt;no-ec2m&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config fips no-ec2m &amp;lt;other options ...&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Compile Time Checking ===&lt;br /&gt;
&lt;br /&gt;
If you disable an option during configure, you can check if it's available through &amp;lt;tt&amp;gt;OPENSSL_NO_*&amp;lt;/tt&amp;gt; defines. OpenSSL writes the configure options to &amp;lt;tt&amp;gt;&amp;lt;openssl/opensslconf.h&amp;gt;&amp;lt;/tt&amp;gt;. For example, if you want to know if SSLv3 is available, then you would perform the following in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/opensslconf.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#if !defined(OPENSSL_NO_SSL3)&lt;br /&gt;
  /* SSLv3 is available */&lt;br /&gt;
#endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compilation ==&lt;br /&gt;
&lt;br /&gt;
After configuring the library, you should run &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;. If prompted, there's usually no need to &amp;lt;tt&amp;gt;make depend&amp;lt;/tt&amp;gt; since you are building from a clean download.&lt;br /&gt;
&lt;br /&gt;
==== Quick ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config &amp;lt;nowiki&amp;gt;&amp;lt;options ...&amp;gt; --openssldir=/usr/local/ssl&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
make&lt;br /&gt;
make test&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Various options can be found examining the &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; file (there is a well commented block at its top). OpenSSL ships with SSLv2, SSLv3 and Compression enabled by default (see &amp;lt;tt&amp;gt;my $disabled&amp;lt;/tt&amp;gt;), so you might want to use &amp;lt;tt&amp;gt;no-ssl2 no-ssl3&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;no-ssl3&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;no-comp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Platfom specific ==&lt;br /&gt;
&lt;br /&gt;
=== Linux ===&lt;br /&gt;
&lt;br /&gt;
==== Intel ====&lt;br /&gt;
&lt;br /&gt;
==== ARM ====&lt;br /&gt;
&lt;br /&gt;
==== X32 (ILP32) ====&lt;br /&gt;
&lt;br /&gt;
X32 uses the 32-bit data model (ILP32) on x86_64/amd64. To properly configure for X32 under current OpenSSL distributions, you must use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and use the x32 triplet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# ./Configure LIST | grep x32&lt;br /&gt;
linux-x32&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# ./Configure linux-x32      &lt;br /&gt;
Configuring OpenSSL version 1.1.0-pre6-dev (0x0x10100006L)&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN (skip dir)&lt;br /&gt;
    ...&lt;br /&gt;
Configuring for linux-x32&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-Wall -O3 -pthread -mx32 -DL_ENDIAN &lt;br /&gt;
SHARED_CFLAG  =-fPIC&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If using an amd64-compatible processor and GCC with that supports &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt;, then you usually add &amp;lt;tt&amp;gt;enable-ec_nistp_64_gcc_128 &amp;lt;/tt&amp;gt; in addition to your other flags.&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
3noch wrote a VERY good guide in 2012 [https://web.archive.org/web/20161123004257/http://developer.covenanteyes.com/building-openssl-for-visual-studio// here] (PLEASE NOTE: the guide was written in 2012 and is no longer available at the original location; the link now points to an archived version at the Internet Archive Wayback Machine).&lt;br /&gt;
&lt;br /&gt;
Like he said in his article, make absolutely sure to create separate directories for 32 and 64 bit versions.&lt;br /&gt;
&lt;br /&gt;
==== W32 / Windows NT - Windows 9x ====&lt;br /&gt;
&lt;br /&gt;
type INSTALL.W32&lt;br /&gt;
&lt;br /&gt;
* you need Perl for Win32.  Unless you will build on Cygwin, you will need ActiveState Perl, available from http://www.activestate.com/ActivePerl.&lt;br /&gt;
* one of the following C compilers:&lt;br /&gt;
** Visual C++&lt;br /&gt;
** Borland C&lt;br /&gt;
** GNU C (Cygwin or MinGW)&lt;br /&gt;
* Netwide Assembler, a.k.a. NASM, available from http://nasm.sourceforge.net/ is required if you intend to utilize assembler modules. Note that NASM is now the only supported assembler.&lt;br /&gt;
&lt;br /&gt;
==== W64 ====&lt;br /&gt;
&lt;br /&gt;
Read first the INSTALL.W64 documentation note containing some specific 64bits information.&lt;br /&gt;
See also INSTALL.W32 that still provides additonnal build information common to both the 64 and 32 bit versions.&lt;br /&gt;
&lt;br /&gt;
You may be surprised: the 64bit artefacts are indeed output in the out32* sub-directories and bear names ending *32.dll. Fact is the 64 bit compile target is so far an incremental change over the legacy 32bit windows target. Numerous compile flags are still labelled &amp;quot;32&amp;quot; although those do apply to both 32 and 64bit targets.&lt;br /&gt;
&lt;br /&gt;
The important pre-requisites are to have PERL available (for essential file processing so as to prepare sources and scripts for the target OS) and of course a C compiler like Microsoft Visual Studio for C/C++. Also note the procedure changed at OpenSSL 1.1.0 and is more streamlined. Also see [https://stackoverflow.com/q/39076244/608639 Why there is no ms\do_ms.bat after perl Configure VC-WIN64A] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.1.0 ===&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 and above perform these steps:&lt;br /&gt;
&lt;br /&gt;
# Ensure you have perl installed on your machine (e.g. ActiveState or Strawberry), and available on your %PATH%&lt;br /&gt;
# Ensure you have NASM installed on your machine, and available on your %PATH%&lt;br /&gt;
# Extract the source files to your folder, here &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# Launch Visual Studio tool x64 Cross Tools Command prompt&lt;br /&gt;
# Goto your defined folder &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure for the target OS with &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt; or other configurations to be found in the INSTALL file (e.g. UNIX targets). &lt;br /&gt;
## For instance: &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;.&lt;br /&gt;
# (''Optional'') In case you compiled before on 32 or 64-bits, make sure you run &amp;lt;code&amp;gt;nmake clean&amp;lt;/code&amp;gt; to prevent trouble across 32 and 64-bits which share output folder.&lt;br /&gt;
# Now build with: &amp;lt;code&amp;gt;nmake&amp;lt;/code&amp;gt;&lt;br /&gt;
# Output can be found in the '''root''' of your folder as '''libcrypto-1_1x64.dll''' and '''libssl-1_1-x64.dll''' (with all the build additionals such as .pdb .lik or static .lib). You may check this is true 64bit code using the Visual Studio tool 'dumpbin'. For instance &amp;lt;code&amp;gt;dumpbin  /headers libcrypto-1_1x64.dll | more&amp;lt;/code&amp;gt;, and look at the FILE HEADER section.&lt;br /&gt;
# Test the code using the 'test' make target, by running &amp;lt;code&amp;gt;nmake test&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Reminder, clean your code to prevent issues the next time you compile for a different target. See step 7.&lt;br /&gt;
&lt;br /&gt;
==== Windows CE ====&lt;br /&gt;
'' Not specified ''&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.0.2 ===&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.0.2 and earlier the procedure is as follows.&lt;br /&gt;
&lt;br /&gt;
# Ensure you have perl installed on your machine (e.g. ActiveState or Strawberry), and available on your %PATH%&lt;br /&gt;
# Ensure you have NASM installed on your machine, and available on your %PATH%&lt;br /&gt;
# launch a Visual Studio tool x64 Cross Tools Command prompt&lt;br /&gt;
# change to the directory where you have copied openssl sources &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# configure for the target OS with the command &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;. You may also be interested to set more configuration options as documented in the general INSTALL note (for UNIX targets). For instance: &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;.&lt;br /&gt;
# prepare the target environment with the command: &amp;lt;code&amp;gt;ms\do_win64a&amp;lt;/code&amp;gt;&lt;br /&gt;
# ensure you start afresh and notably without linkable products from a previous 32bit compile (as 32 and 64 bits compiling still share common directories) with the command: &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak clean&amp;lt;/code&amp;gt; for the DLL target and &amp;lt;code&amp;gt;nmake -f ms\nt.mak clean&amp;lt;/code&amp;gt; for static libraries.&lt;br /&gt;
# build the code with: &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak&amp;lt;/code&amp;gt; (respectively &amp;lt;code&amp;gt;nmake -f ms\nt.mak&amp;lt;/code&amp;gt; )&lt;br /&gt;
# the artefacts will be found in sub directories out32dll and out32dll.dbg (respectively out32 and out32.dbg for static libraries). The libcrypto and ssl libraries are still named libeay32.lib and ssleay32.lib, and associated includes in inc32 ! You may check this is true 64bit code using the Visual Studio tool 'dumpbin'. For instance &amp;lt;code&amp;gt;dumpbin  /headers out32dll/libeay32.lib | more&amp;lt;/code&amp;gt;, and look at the FILE HEADER section.&lt;br /&gt;
# test the code using the various *test.exe programs in out32dll. Use the 'test' make target to run all tests as in &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak test&amp;lt;/code&amp;gt;&lt;br /&gt;
# we recommend that you move/copy needed includes and libraries from the &amp;quot;32&amp;quot; directories under a new explicit directory tree for 64bit applications from where you will import and link your target applications, similar to that explained in INSTALL.W32.&lt;br /&gt;
&lt;br /&gt;
==== Windows CE ====&lt;br /&gt;
&lt;br /&gt;
=== OS X ===&lt;br /&gt;
&lt;br /&gt;
The earlier discussion presented a lot of information (and some of it had OS X information). Here are the TLDR versions to configure, build and install the library.&lt;br /&gt;
&lt;br /&gt;
If configuring for 64-bit OS X, then use a command similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./Configure darwin64-x86_64-cc shared enable-ec_nistp_64_gcc_128 no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl/macos-x86_64&lt;br /&gt;
make depend&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If configuring for 32-bit OS X, then use a command similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./Configure darwin-i386-cc shared no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl/macosx-i386&lt;br /&gt;
make depend&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to build a multiarch OpenSSL library, then see this answer on Stack Overflow: [http://stackoverflow.com/a/25531033/608639 Build Multiarch OpenSSL on OS X].&lt;br /&gt;
&lt;br /&gt;
=== iOS ===&lt;br /&gt;
&lt;br /&gt;
The following builds OpenSSL for iOS using the iPhoneOS SDK. The configuration avoids the dynamic library the DSO interface and engines.&lt;br /&gt;
&lt;br /&gt;
If you run &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt;, then the headers will be installed in &amp;lt;tt&amp;gt;/usr/local/openssl-ios/include&amp;lt;/tt&amp;gt; and libraries will be installed in &amp;lt;tt&amp;gt;/usr/local/openssl-ios/lib&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== 32-bit ====&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 and above, a 32-bit iOS cross-compiles uses the &amp;lt;tt&amp;gt;ios-cross&amp;lt;/tt&amp;gt; target, and options similar to &amp;lt;tt&amp;gt;--prefix=/usr/local/openssl-ios&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure ios-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios&lt;br /&gt;
&lt;br /&gt;
Configuring OpenSSL version 1.1.1-dev (0x10101000L)&lt;br /&gt;
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-dynamic-engine [forced]&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
Configuring for ios-cross&lt;br /&gt;
&lt;br /&gt;
PERL          =perl&lt;br /&gt;
PERLVERSION   =5.16.2 for darwin-thread-multi-2level&lt;br /&gt;
HASHBANGPERL  =/usr/bin/env perl&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-O3 -D_REENTRANT -arch armv7 -mios-version-min=6.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
CXX           =c++&lt;br /&gt;
CXXFLAG       =-O3 -D_REENTRANT -arch armv7 -mios-version-min=6.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
DEFINES       =NDEBUG OPENSSL_THREADS OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_PIC OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_GF2m SHA1_ASM SHA256_ASM SHA512_ASM AES_ASM BSAES_ASM GHASH_ASM ECP_NISTZ256_ASM POLY1305_ASM&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are working with OpenSSL 1.0.2 or below, then use the &amp;lt;tt&amp;gt;iphoneos-cross&amp;lt;/tt&amp;gt; target.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure iphoneos-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios&lt;br /&gt;
Configuring for iphoneos-cross&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-engine       [option]   OPENSSL_NO_ENGINE (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-hw           [option]   OPENSSL_NO_HW&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS (skip dir)&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
IsMK1MF=0&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-DOPENSSL_THREADS -D_REENTRANT -O3 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fomit-frame-pointer -fno-common&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 64-bit ====&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 , a 64-bit iOS cross-compiles uses the &amp;lt;tt&amp;gt;ios64-cross&amp;lt;/tt&amp;gt; target, and &amp;lt;tt&amp;gt;--prefix=/usr/local/openssl-ios64&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;ios64-cross&amp;lt;/tt&amp;gt;. There is no built-in 64-bit iOS support for OpenSSL 1.0.2 or below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure ios64-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios64&lt;br /&gt;
&lt;br /&gt;
Configuring OpenSSL version 1.1.1-dev (0x10101000L)&lt;br /&gt;
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-dynamic-engine [forced]&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
Configuring for ios64-cross&lt;br /&gt;
&lt;br /&gt;
PERL          =perl&lt;br /&gt;
PERLVERSION   =5.16.2 for darwin-thread-multi-2level&lt;br /&gt;
HASHBANGPERL  =/usr/bin/env perl&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
CXX           =c++&lt;br /&gt;
CXXFLAG       =-O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
DEFINES       =NDEBUG OPENSSL_THREADS OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_PIC OPENSSL_BN_ASM_MONT SHA1_ASM SHA256_ASM SHA512_ASM VPAES_ASM ECP_NISTZ256_ASM POLY1305_ASM&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Android ===&lt;br /&gt;
&lt;br /&gt;
Visit [[Android]] and [[FIPS Library and Android]].&lt;br /&gt;
&lt;br /&gt;
=== More ===&lt;br /&gt;
&lt;br /&gt;
==== VAX/VMS ====&lt;br /&gt;
&lt;br /&gt;
I you wonder what are files ending with .com like test/testca.com those are VAX/VMX scripts.&lt;br /&gt;
This code is still maintained.&lt;br /&gt;
&lt;br /&gt;
==== OS/2 ====&lt;br /&gt;
&lt;br /&gt;
==== NetWare ====&lt;br /&gt;
5.x 6.x&lt;br /&gt;
&lt;br /&gt;
==== HP-UX ====&lt;br /&gt;
[[HP-UX Itanium FIPS and OpenSSL build]]&lt;br /&gt;
&lt;br /&gt;
==Autoconf==&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses its own configuration system, and does not use Autoconf. However, a number of popular projects use both OpenSSL and Autoconf, and it would be useful to detect either &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. To craft a feature test for OpenSSL that recognizes both &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;, you can use the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if test &amp;quot;$with_openssl&amp;quot; = yes ; then&lt;br /&gt;
  dnl Order matters!&lt;br /&gt;
  if test &amp;quot;$PORTNAME&amp;quot; != &amp;quot;win32&amp;quot;; then&lt;br /&gt;
     AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_CHECK_LIB(ssl, OPENSSL_init_ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_CHECK_LIB(ssl, SSL_library_init, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])])&lt;br /&gt;
  else&lt;br /&gt;
     AC_SEARCH_LIBS(CRYPTO_new_ex_data, eay32 crypto, [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_SEARCH_LIBS(OPENSSL_init_ssl, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_SEARCH_LIBS(SSL_library_init, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])&lt;br /&gt;
  fi&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many thanks to the Postgres folks for donating part of their &amp;lt;tt&amp;gt;configure.in&amp;lt;/tt&amp;gt;. Also see [http://stackoverflow.com/q/39285733 How to tell Autoconf “require symbol A or B” from LIB?] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
[[Category:Shell level]]&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
[[Category:Compilation]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_SHA&amp;diff=3152</id>
		<title>Cryptogams SHA</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_SHA&amp;diff=3152"/>
		<updated>2021-03-14T06:10:26Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on Apple M1 builds.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 SHA-1 implementation. According to the head notes the ARMv4 implementation runs around 6.5 cycles per byte (cpb). Typical C/C++ implementations run around 10 to 20 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;sha1-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' sha1-armv4.h sha1-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation hashes full SHA blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
If you experience ''&amp;quot;unexpected reloc type 0x03&amp;quot;'' when building a shared object then see [https://sourceware.org/ml/binutils/2019-05/msg00287.html What does unexpected reloc type 0x03 mean?] on the Binutils mailing list.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams SHA. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/sha/asm/sha1-armv4-large.pl &amp;lt;tt&amp;gt;sha1-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/sha/asm/sha1-armv4-large.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;sha1-armv4-large.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;sha1-armv4-large.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl sha1-armv4-large.pl linux32 sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;sha1-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat sha1-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' sha1-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c sha1-armv4.S&lt;br /&gt;
$ nm sha1-armv4.o&lt;br /&gt;
00000000 T sha1_block_data_order&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble sha1-armv4.o&lt;br /&gt;
sha1-armv4.o:     file format elf32-littlearm&lt;br /&gt;
&lt;br /&gt;
Disassembly of section .text:&lt;br /&gt;
&lt;br /&gt;
00000000 &amp;lt;sha1_block_data_order&amp;gt;:&lt;br /&gt;
   0:   e92d5ff0        push    {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}&lt;br /&gt;
   4:   e0812302        add     r2, r1, r2, lsl #6&lt;br /&gt;
   8:   e89000f8        ldm     r0, {r3, r4, r5, r6, r7}&lt;br /&gt;
   c:   e59f858c        ldr     r8, [pc, #1420] ; 5a0 &amp;lt;sha1_block_data_order+0x5a0&amp;gt;&lt;br /&gt;
  10:   e1a0e00d        mov     lr, sp&lt;br /&gt;
  14:   e24dd03c        sub     sp, sp, #60     ; 0x3c&lt;br /&gt;
  18:   e1a05f65        ror     r5, r5, #30&lt;br /&gt;
  1c:   e1a06f66        ror     r6, r6, #30&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. Fortunately there is one function of interest called &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR sha1_block_data_order | grep '\.c'&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:95:    void sha1_block_data_order(void *c, const void *p, size_t len);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:115:        sha1_block_data_order(c, ptr, len / SHA_CBLOCK);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:615:        sha1_block_data_order(&amp;amp;key-&amp;gt;md, data, 1);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:631:        sha1_block_data_order(&amp;amp;key-&amp;gt;md, data, 1);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We need several more symbols, and and they are &amp;lt;tt&amp;gt;OPENSSL_armcap_P&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ARMV7_NEON&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ARMV8_SHA1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ grep -nIR OPENSSL_armcap_P&lt;br /&gt;
...&lt;br /&gt;
crypto/armcap.c:20:unsigned int OPENSSL_armcap_P = 0;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse, repeat for &amp;lt;tt&amp;gt;ARMV7_NEON&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ARMV8_SHA1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use. While it is not obvious, the &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; parameter from [[#Determine_API|Determine API]] is a block count, not a byte count.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 SHA1.    */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_SHA.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_SHA1_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_SHA1_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
extern unsigned int OPENSSL_armcap_P;&lt;br /&gt;
void sha1_block_data_order(void *state, const void *data, size_t blocks);&lt;br /&gt;
&lt;br /&gt;
/* Auxval caps */&lt;br /&gt;
#ifndef HWCAP_NEON&lt;br /&gt;
# define HWCAP_NEON (1 &amp;lt;&amp;lt; 12)&lt;br /&gt;
#endif&lt;br /&gt;
#ifndef HWCAP_SHA1&lt;br /&gt;
# define HWCAP_SHA1 (1 &amp;lt;&amp;lt; 5)&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/* OpenSSL caps */&lt;br /&gt;
#define ARMV7_NEON (1&amp;lt;&amp;lt;0)&lt;br /&gt;
#define ARMV8_SHA1 (1&amp;lt;&amp;lt;3)&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_SHA1_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's SHA with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 sha1-armv4-test.c ./sha1-armv4.o -o sha1-armv4-test.exe&lt;br /&gt;
$ ./sha1-armv4-test.exe&lt;br /&gt;
SHA1 hash of empty message: DA39A3EE5E6B4B0D...&lt;br /&gt;
Success!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/auxv.h&amp;gt;&lt;br /&gt;
#include &amp;quot;sha1-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* processor caps */&lt;br /&gt;
unsigned int OPENSSL_armcap_P = 0;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* processor caps */&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_NEON)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV7_NEON;&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_SHA1)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV8_SHA1;&lt;br /&gt;
&lt;br /&gt;
    /* empty message with padding */&lt;br /&gt;
    uint8_t message[64];&lt;br /&gt;
    memset(message, 0x00, sizeof(message));&lt;br /&gt;
    message[0] = 0x80;&lt;br /&gt;
&lt;br /&gt;
    /* initial state */&lt;br /&gt;
    uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};&lt;br /&gt;
&lt;br /&gt;
    sha1_block_data_order(state, message, 1);&lt;br /&gt;
&lt;br /&gt;
    const uint8_t b1 = (uint8_t)(state[0] &amp;gt;&amp;gt; 24);&lt;br /&gt;
    const uint8_t b2 = (uint8_t)(state[0] &amp;gt;&amp;gt; 16);&lt;br /&gt;
    const uint8_t b3 = (uint8_t)(state[0] &amp;gt;&amp;gt;  8);&lt;br /&gt;
    const uint8_t b4 = (uint8_t)(state[0] &amp;gt;&amp;gt;  0);&lt;br /&gt;
    const uint8_t b5 = (uint8_t)(state[1] &amp;gt;&amp;gt; 24);&lt;br /&gt;
    const uint8_t b6 = (uint8_t)(state[1] &amp;gt;&amp;gt; 16);&lt;br /&gt;
    const uint8_t b7 = (uint8_t)(state[1] &amp;gt;&amp;gt;  8);&lt;br /&gt;
    const uint8_t b8 = (uint8_t)(state[1] &amp;gt;&amp;gt;  0);&lt;br /&gt;
&lt;br /&gt;
    /* DA39A3EE5E6B4B0D... */&lt;br /&gt;
    printf(&amp;quot;SHA1 hash of empty message: &amp;quot;);&lt;br /&gt;
    printf(&amp;quot;%02X%02X%02X%02X%02X%02X%02X%02X...\n&amp;quot;,&lt;br /&gt;
        b1, b2, b3, b4, b5, b6, b7, b8);&lt;br /&gt;
&lt;br /&gt;
    int success = ((b1 == 0xDA) &amp;amp;&amp;amp; (b2 == 0x39) &amp;amp;&amp;amp; (b3 == 0xA3) &amp;amp;&amp;amp; (b4 == 0xEE) &amp;amp;&amp;amp;&lt;br /&gt;
                    (b5 == 0x5E) &amp;amp;&amp;amp; (b6 == 0x6B) &amp;amp;&amp;amp; (b7 == 0x4B) &amp;amp;&amp;amp; (b8 == 0x0D));&lt;br /&gt;
&lt;br /&gt;
    if (success)&lt;br /&gt;
        printf(&amp;quot;Success!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failure!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    return (success != 0 ? 0 : 1);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt; is the names of function in the source code, and they will show up in the object file and when compiled and in the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for SHA-1 you should rename &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OPENSSL_armcap_P&amp;lt;/tt&amp;gt;. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' sha1_armv4.h sha1_armv4.S&lt;br /&gt;
sed -i 's/sha1_block_data_order/MYLIB_sha1_block_data_order/g' sha1_armv4.h sha1_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/auxv.h&amp;gt;&lt;br /&gt;
#include &amp;quot;sha1-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* processor caps */&lt;br /&gt;
unsigned int OPENSSL_armcap_P = 0;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* set processor caps */&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_NEON)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV7_NEON;&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_SHA1)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV8_SHA1;&lt;br /&gt;
&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    uint8_t* buf = (uint8_t*)malloc(STEPS*64+64);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            sha1_block_data_order(state, buf, idx+1);&lt;br /&gt;
        total += 64*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 1 GHz */&lt;br /&gt;
    const double cpuFreq = 1000.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a [https://www.amazon.com/gp/product/B07D4L7GXZ Libre Computer Tritium H3] with a Cortex-A7 Sun7i SoC running at 1 GHz. A C/C++ SHA implementation runs about 22 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 -march=armv7 -c sha1-armv4.S -o sha1-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 sha1-armv7-test.c sha1-armv7.o -o sha1-armv7-test.exe&lt;br /&gt;
$ ./sha1-armv7-test.exe&lt;br /&gt;
180994048 bytes&lt;br /&gt;
57.59 mbs&lt;br /&gt;
16.56 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== iOS Builds ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sha1-armv4&amp;lt;/tt&amp;gt; can be configured for iOS. Simply use &amp;lt;tt&amp;gt;ios32&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ios64&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ perl sha1-armv4-large.pl ios32 sha1-armv4.S&lt;br /&gt;
$ clang -arch armv7 sha1-armv4.S -c&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ nm sha1-armv4.o&lt;br /&gt;
000012d0 s OPENSSL_armcap_P&lt;br /&gt;
00000004 C _OPENSSL_armcap_P&lt;br /&gt;
00000000 T _sha1_block_data_order&lt;br /&gt;
00001100 t sha1_block_data_order_armv8&lt;br /&gt;
00000560 t sha1_block_data_order_neon&lt;br /&gt;
&lt;br /&gt;
$ otool -tV sha1-armv4.o&lt;br /&gt;
sha1-armv4.o:&lt;br /&gt;
(__TEXT,__text) section&lt;br /&gt;
_sha1_block_data_order:&lt;br /&gt;
00000000        f8dfc4ec        ldr.w   r12, [pc, #0x4ec]&lt;br /&gt;
00000004        f2af0308        subw    r3, pc, #0x8&lt;br /&gt;
00000008        f853c00c        ldr.w   r12, [r3, r12]&lt;br /&gt;
0000000c        f8dcc000        ldr.w   r12, [r12]&lt;br /&gt;
00000010        f01c0f08        tst.w   r12, #0x8&lt;br /&gt;
00000014        f0418074        bne.w   sha1_block_data_order_armv8&lt;br /&gt;
00000018        f01c0f01        tst.w   r12, #0x1&lt;br /&gt;
0000001c        f04082a0        bne.w   sha1_block_data_order_neon&lt;br /&gt;
00000020        e92d5ff0        push.w  {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ARMv8 Builds ==&lt;br /&gt;
&lt;br /&gt;
If you need SHA for ARMv8 devices, which includes aarch64 and aarch32, then use &amp;lt;tt&amp;gt;sha1-armv8.pl&amp;lt;/tt&amp;gt;. You would use something like this in your scripts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ! perl sha1-armv8.pl linux64 sha1-armv8.S; then&lt;br /&gt;
    echo &amp;quot;Failed to translate SHA source file&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sha1-armv8.pl&amp;lt;/tt&amp;gt; provides the following function:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;sha1_block_armv8&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are building for an Apple M1 you may need to use flavor &amp;lt;tt&amp;gt;ios64&amp;lt;/tt&amp;gt;. The translate script does not handle &amp;lt;tt&amp;gt;osx64&amp;lt;/tt&amp;gt; properly.&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=3151</id>
		<title>Cryptogams AES</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=3151"/>
		<updated>2021-03-14T06:09:53Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on Apple M1 builds.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 AES implementation. According to the head notes the ARMv4 implementation runs around 22 to 40 cycles per byte (cpb). Typical C/C++ implementations run around 50 to 80 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;aes-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' aes-armv4.h aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation operates in ECB mode and encrypts or decrypts full AES blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
At the moment Clang is miscompiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Also see [https://bugs.llvm.org/show_bug.cgi?id=38133 LLVM Issue 38133]. You can work around the problem by compiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;-mthumb&amp;lt;/tt&amp;gt;, but all data must be aligned. If you don't use aligned buffers then a &amp;lt;tt&amp;gt;SIGBUS&amp;lt;/tt&amp;gt; could occur.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams AES. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/aes/asm/aes-armv4.pl &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/aes/asm/aes-armv4.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl aes-armv4.pl linux32 aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;aes-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat aes-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' aes-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&lt;br /&gt;
$ nm aes-armv4.o&lt;br /&gt;
000011c0 T AES_decrypt&lt;br /&gt;
00000540 T AES_encrypt&lt;br /&gt;
00000b60 T AES_set_decrypt_key&lt;br /&gt;
00000b80 T AES_set_enc2dec_key&lt;br /&gt;
00000820 T AES_set_encrypt_key&lt;br /&gt;
00000cc0 t AES_Td&lt;br /&gt;
00000000 t AES_Te&lt;br /&gt;
000012c0 t _armv4_AES_decrypt&lt;br /&gt;
00000640 t _armv4_AES_encrypt&lt;br /&gt;
00000b80 t _armv4_AES_set_enc2dec_key&lt;br /&gt;
00000820 t _armv4_AES_set_encrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble aes-armv4.o&lt;br /&gt;
aes-armv4.o:     file format elf32-littlearm&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
00000b60 &amp;lt;AES_set_decrypt_key&amp;gt;:&lt;br /&gt;
     b60:       e52de004        push    {lr}            ; (str lr, [sp, #-4]!)&lt;br /&gt;
     b64:       ebffff2d        bl      820 &amp;lt;AES_set_encrypt_key&amp;gt;&lt;br /&gt;
     b68:       e3300000        teq     r0, #0&lt;br /&gt;
     b6c:       e49de004        pop     {lr}            ; (ldr lr, [sp], #4)&lt;br /&gt;
     b70:       1afffff9        bne     b5c &amp;lt;AES_set_encrypt_key+0x33c&amp;gt;&lt;br /&gt;
     b74:       e1a00002        mov     r0, r2&lt;br /&gt;
     b78:       e1a01002        mov     r1, r2&lt;br /&gt;
     b7c:       eaffffff        b       b80 &amp;lt;AES_set_enc2dec_key&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And trace it back to the source code in &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;.globl  AES_set_decrypt_key&lt;br /&gt;
.type   AES_set_decrypt_key,%function&lt;br /&gt;
.align  5&lt;br /&gt;
AES_set_decrypt_key:&lt;br /&gt;
        str     lr,[sp,#-4]!            @ push lr&lt;br /&gt;
        bl      _armv4_AES_set_encrypt_key&lt;br /&gt;
        teq     r0,#0&lt;br /&gt;
        ldr     lr,[sp],#4              @ pop lr&lt;br /&gt;
        bne     .Labrt&lt;br /&gt;
&lt;br /&gt;
        mov     r0,r2                   @ AES_set_encrypt_key preserves r2,&lt;br /&gt;
        mov     r1,r2                   @ which is AES_KEY *key&lt;br /&gt;
        b       _armv4_AES_set_enc2dec_key&lt;br /&gt;
.size   AES_set_decrypt_key,.-AES_set_decrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. The functions of interest are &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_set_encrypt_key | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:632:int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examining &amp;lt;tt&amp;gt;aes_core.c:632&amp;lt;/tt&amp;gt; reveals the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   632  int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&lt;br /&gt;
   633                          AES_KEY *key)&lt;br /&gt;
   634  {&lt;br /&gt;
            ...&lt;br /&gt;
   728      return 0;&lt;br /&gt;
   729  }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next piece of information to discover is &amp;lt;tt&amp;gt;AES_KEY&amp;lt;/tt&amp;gt;. Again a quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; leads you to &amp;lt;tt&amp;gt;aes_key_st&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_KEY | grep typedef&lt;br /&gt;
include/openssl/aes.h:39:typedef struct aes_key_st AES_KEY;&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n include/openssl/aes.h&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    31  struct aes_key_st {&lt;br /&gt;
    32  # ifdef AES_LONG&lt;br /&gt;
    33      unsigned long rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    34  # else&lt;br /&gt;
    35      unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    36  # endif&lt;br /&gt;
    37      int rounds;&lt;br /&gt;
    38  };&lt;br /&gt;
    39  typedef struct aes_key_st AES_KEY;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, you need &amp;lt;tt&amp;gt;AES_MAXNR&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;aes.h&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -IR AES_MAXNR | grep define&lt;br /&gt;
include/openssl/aes.h:# define AES_MAXNR 14&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse repeat for &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;crypto/aes/aes_core.c:787&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_encrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:787:void AES_encrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   783  /*&lt;br /&gt;
   784   * Encrypt a single block&lt;br /&gt;
   785   * in and out can overlap&lt;br /&gt;
   786   */&lt;br /&gt;
   787  void AES_encrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   788                   const AES_KEY *key) {&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;aes_core.c:978&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_decrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:978:void AES_decrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
&lt;br /&gt;
   974  /*&lt;br /&gt;
   975   * Decrypt a single block&lt;br /&gt;
   976   * in and out can overlap&lt;br /&gt;
   977   */&lt;br /&gt;
   978  void AES_decrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   979                   const AES_KEY *key)&lt;br /&gt;
   980  {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 AES.     */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_AES.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define AES_MAXNR 14&lt;br /&gt;
&lt;br /&gt;
typedef struct AES_KEY_st {&lt;br /&gt;
    unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    int rounds;&lt;br /&gt;
} AES_KEY;&lt;br /&gt;
&lt;br /&gt;
int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
void AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
void AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_AES_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's AES with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 aes-armv4-test.c ./aes-armv4.o -o aes-armv4-test.exe&lt;br /&gt;
$ ./aes-armv4-test.exe&lt;br /&gt;
Encrypted plaintext!&lt;br /&gt;
Decrypted ciphertext!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* Test key from FIPS 197 */&lt;br /&gt;
    const uint8_t kb[] = {&lt;br /&gt;
        0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,&lt;br /&gt;
        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t pb[] = {&lt;br /&gt;
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,&lt;br /&gt;
        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t cb[] = {&lt;br /&gt;
        0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, &lt;br /&gt;
        0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /* Scratch */&lt;br /&gt;
    uint8_t buf[16];&lt;br /&gt;
    int result;&lt;br /&gt;
    &lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    result = AES_set_encrypt_key(kb, sizeof(kb)*8, &amp;amp; ekey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_encrypt(pb, buf, &amp;amp;ekey);&lt;br /&gt;
    if (memcmp(cb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Encrypted plaintext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to encrypt plaintext!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY dkey;&lt;br /&gt;
    result = AES_set_decrypt_key(kb, sizeof(kb)*8, &amp;amp; dkey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_decrypt(cb, buf, &amp;amp;dkey);&lt;br /&gt;
    if (memcmp(pb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Decrypted ciphertext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to decrypt ciphertext!\n&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt; are the names of two functions in the source code, and they will show up in the object file and when compiled and the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for AES you should rename all &amp;lt;tt&amp;gt;AES_*&amp;lt;/tt&amp;gt; names. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_decrypt/MYLIB_AES_decrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_encrypt/MYLIB_AES_encrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_decrypt_key/MYLIB_AES_set_decrypt_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_enc2dec_key/MYLIB_AES_set_enc2dec_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_encrypt_key/MYLIB_AES_set_encrypt_key/g' aes_armv4.h aes_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
typedef unsigned char byte;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    byte* buf = (byte*)malloc(STEPS*16+16);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    (void)AES_set_encrypt_key(buf, 16*8, &amp;amp;ekey);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            AES_encrypt(&amp;amp;buf[idx+i], &amp;amp;buf[idx+i+1], &amp;amp;ekey);&lt;br /&gt;
        total += 16*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 950 MHz */&lt;br /&gt;
    const double cpuFreq = 950.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a BananaPi with a Cortex-A7 Sun7i SoC running at 950 MHz. A C/C++ AES implementation runs about 65 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv7 -c aes-armv4.S -o aes-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 aes-armv7-test.c aes-armv7.o -o aes-armv7-test.exe&lt;br /&gt;
$ ./aes-armv7-test.exe&lt;br /&gt;
78426112 bytes&lt;br /&gt;
24.93 mbs&lt;br /&gt;
36.34 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the following is from a Wandboard Dual with a NXP i.MX6 Cortex-A9 running at 1 GHz.  A C/C++ implementation runs around 40 cpb.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./aes-armv7-test.exe&lt;br /&gt;
106029056 bytes&lt;br /&gt;
33.80 mbs&lt;br /&gt;
26.80 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Autotools ==&lt;br /&gt;
&lt;br /&gt;
If you are using Autotools you can add the following to &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; to conditionally compile &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; for A-32 platforms. You will need to detect ARM A-32 and set &amp;lt;tt&amp;gt;IS_ARM32&amp;lt;/tt&amp;gt; to non-0. Also see [https://www.gnu.org/software/automake/manual/html_node/Assembly-Support.html Automake Assembly Support] in section 8.13 of the manual.&lt;br /&gt;
&lt;br /&gt;
First, the &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Set ASM tools&lt;br /&gt;
AC_SUBST([CCAS], [$CC])&lt;br /&gt;
AC_SUBST([CCASFLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
# Used by Makefile.am to compile aes-armv4.S&lt;br /&gt;
if test &amp;quot;$IS_ARM32&amp;quot; != &amp;quot;0&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
   ## Save CFLAGS&lt;br /&gt;
   SAVED_CFLAGS=&amp;quot;$CFLAGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   CFLAGS=&amp;quot;-march=armv7-a -Wa,--noexecstack&amp;quot;&lt;br /&gt;
   AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
   AC_COMPILE_IFELSE(&lt;br /&gt;
      [AC_LANG_PROGRAM([])],&lt;br /&gt;
      [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
      [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
   )&lt;br /&gt;
&lt;br /&gt;
   if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
      AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
      AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
   else&lt;br /&gt;
&lt;br /&gt;
      CFLAGS=&amp;quot;-march=armv7-a&amp;quot;&lt;br /&gt;
      AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
      AC_COMPILE_IFELSE(&lt;br /&gt;
         [AC_LANG_PROGRAM([])],&lt;br /&gt;
         [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
         [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
      )&lt;br /&gt;
&lt;br /&gt;
      if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
         AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
      else&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
      fi&lt;br /&gt;
   fi&lt;br /&gt;
&lt;br /&gt;
   ## Restore CFLAGS&lt;br /&gt;
   CFLAGS=&amp;quot;$SAVED_CFLAGS&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
   # Required for other platforms&lt;br /&gt;
   AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second, the &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if CRYPTOGAMS_AES&lt;br /&gt;
&lt;br /&gt;
  aes_armv4_la_SOURCES = aes-armv4.S&lt;br /&gt;
  aes_armv4_la_CCASFLAGS = $(AM_CFLAGS) $(CRYPTOGAMS_AES)&lt;br /&gt;
&lt;br /&gt;
  pkginclude_HEADERS += aes-armv4.h&lt;br /&gt;
&lt;br /&gt;
endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ARMv8 Builds ==&lt;br /&gt;
&lt;br /&gt;
If you need AES for ARMv8 devices, which includes aarch64 and aarch32, then use &amp;lt;tt&amp;gt;aesv8-armx.pl&amp;lt;/tt&amp;gt;. You would use something like this in your scripts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ! perl aesv8-armx.pl linux64 armx_aes.S; then&lt;br /&gt;
    echo &amp;quot;Failed to translate AES source file&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;aesv8-armx.pl&amp;lt;/tt&amp;gt; provides the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_set_encrypt_key&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_set_decrypt_key&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_encrypt&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_decrypt&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are building for an Apple M1 you may need to use flavor &amp;lt;tt&amp;gt;ios64&amp;lt;/tt&amp;gt;. The translate script does not handle &amp;lt;tt&amp;gt;osx64&amp;lt;/tt&amp;gt; properly.&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_SHA&amp;diff=3149</id>
		<title>Cryptogams SHA</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_SHA&amp;diff=3149"/>
		<updated>2021-03-12T15:23:17Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Whitespace check-in.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 SHA-1 implementation. According to the head notes the ARMv4 implementation runs around 6.5 cycles per byte (cpb). Typical C/C++ implementations run around 10 to 20 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;sha1-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' sha1-armv4.h sha1-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation hashes full SHA blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
If you experience ''&amp;quot;unexpected reloc type 0x03&amp;quot;'' when building a shared object then see [https://sourceware.org/ml/binutils/2019-05/msg00287.html What does unexpected reloc type 0x03 mean?] on the Binutils mailing list.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams SHA. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/sha/asm/sha1-armv4-large.pl &amp;lt;tt&amp;gt;sha1-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/sha/asm/sha1-armv4-large.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;sha1-armv4-large.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;sha1-armv4-large.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl sha1-armv4-large.pl linux32 sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;sha1-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat sha1-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' sha1-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c sha1-armv4.S&lt;br /&gt;
$ nm sha1-armv4.o&lt;br /&gt;
00000000 T sha1_block_data_order&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble sha1-armv4.o&lt;br /&gt;
sha1-armv4.o:     file format elf32-littlearm&lt;br /&gt;
&lt;br /&gt;
Disassembly of section .text:&lt;br /&gt;
&lt;br /&gt;
00000000 &amp;lt;sha1_block_data_order&amp;gt;:&lt;br /&gt;
   0:   e92d5ff0        push    {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}&lt;br /&gt;
   4:   e0812302        add     r2, r1, r2, lsl #6&lt;br /&gt;
   8:   e89000f8        ldm     r0, {r3, r4, r5, r6, r7}&lt;br /&gt;
   c:   e59f858c        ldr     r8, [pc, #1420] ; 5a0 &amp;lt;sha1_block_data_order+0x5a0&amp;gt;&lt;br /&gt;
  10:   e1a0e00d        mov     lr, sp&lt;br /&gt;
  14:   e24dd03c        sub     sp, sp, #60     ; 0x3c&lt;br /&gt;
  18:   e1a05f65        ror     r5, r5, #30&lt;br /&gt;
  1c:   e1a06f66        ror     r6, r6, #30&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. Fortunately there is one function of interest called &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR sha1_block_data_order | grep '\.c'&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:95:    void sha1_block_data_order(void *c, const void *p, size_t len);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:115:        sha1_block_data_order(c, ptr, len / SHA_CBLOCK);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:615:        sha1_block_data_order(&amp;amp;key-&amp;gt;md, data, 1);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:631:        sha1_block_data_order(&amp;amp;key-&amp;gt;md, data, 1);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We need several more symbols, and and they are &amp;lt;tt&amp;gt;OPENSSL_armcap_P&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ARMV7_NEON&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ARMV8_SHA1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ grep -nIR OPENSSL_armcap_P&lt;br /&gt;
...&lt;br /&gt;
crypto/armcap.c:20:unsigned int OPENSSL_armcap_P = 0;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse, repeat for &amp;lt;tt&amp;gt;ARMV7_NEON&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ARMV8_SHA1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use. While it is not obvious, the &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; parameter from [[#Determine_API|Determine API]] is a block count, not a byte count.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 SHA1.    */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_SHA.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_SHA1_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_SHA1_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
extern unsigned int OPENSSL_armcap_P;&lt;br /&gt;
void sha1_block_data_order(void *state, const void *data, size_t blocks);&lt;br /&gt;
&lt;br /&gt;
/* Auxval caps */&lt;br /&gt;
#ifndef HWCAP_NEON&lt;br /&gt;
# define HWCAP_NEON (1 &amp;lt;&amp;lt; 12)&lt;br /&gt;
#endif&lt;br /&gt;
#ifndef HWCAP_SHA1&lt;br /&gt;
# define HWCAP_SHA1 (1 &amp;lt;&amp;lt; 5)&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/* OpenSSL caps */&lt;br /&gt;
#define ARMV7_NEON (1&amp;lt;&amp;lt;0)&lt;br /&gt;
#define ARMV8_SHA1 (1&amp;lt;&amp;lt;3)&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_SHA1_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's SHA with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 sha1-armv4-test.c ./sha1-armv4.o -o sha1-armv4-test.exe&lt;br /&gt;
$ ./sha1-armv4-test.exe&lt;br /&gt;
SHA1 hash of empty message: DA39A3EE5E6B4B0D...&lt;br /&gt;
Success!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/auxv.h&amp;gt;&lt;br /&gt;
#include &amp;quot;sha1-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* processor caps */&lt;br /&gt;
unsigned int OPENSSL_armcap_P = 0;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* processor caps */&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_NEON)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV7_NEON;&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_SHA1)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV8_SHA1;&lt;br /&gt;
&lt;br /&gt;
    /* empty message with padding */&lt;br /&gt;
    uint8_t message[64];&lt;br /&gt;
    memset(message, 0x00, sizeof(message));&lt;br /&gt;
    message[0] = 0x80;&lt;br /&gt;
&lt;br /&gt;
    /* initial state */&lt;br /&gt;
    uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};&lt;br /&gt;
&lt;br /&gt;
    sha1_block_data_order(state, message, 1);&lt;br /&gt;
&lt;br /&gt;
    const uint8_t b1 = (uint8_t)(state[0] &amp;gt;&amp;gt; 24);&lt;br /&gt;
    const uint8_t b2 = (uint8_t)(state[0] &amp;gt;&amp;gt; 16);&lt;br /&gt;
    const uint8_t b3 = (uint8_t)(state[0] &amp;gt;&amp;gt;  8);&lt;br /&gt;
    const uint8_t b4 = (uint8_t)(state[0] &amp;gt;&amp;gt;  0);&lt;br /&gt;
    const uint8_t b5 = (uint8_t)(state[1] &amp;gt;&amp;gt; 24);&lt;br /&gt;
    const uint8_t b6 = (uint8_t)(state[1] &amp;gt;&amp;gt; 16);&lt;br /&gt;
    const uint8_t b7 = (uint8_t)(state[1] &amp;gt;&amp;gt;  8);&lt;br /&gt;
    const uint8_t b8 = (uint8_t)(state[1] &amp;gt;&amp;gt;  0);&lt;br /&gt;
&lt;br /&gt;
    /* DA39A3EE5E6B4B0D... */&lt;br /&gt;
    printf(&amp;quot;SHA1 hash of empty message: &amp;quot;);&lt;br /&gt;
    printf(&amp;quot;%02X%02X%02X%02X%02X%02X%02X%02X...\n&amp;quot;,&lt;br /&gt;
        b1, b2, b3, b4, b5, b6, b7, b8);&lt;br /&gt;
&lt;br /&gt;
    int success = ((b1 == 0xDA) &amp;amp;&amp;amp; (b2 == 0x39) &amp;amp;&amp;amp; (b3 == 0xA3) &amp;amp;&amp;amp; (b4 == 0xEE) &amp;amp;&amp;amp;&lt;br /&gt;
                    (b5 == 0x5E) &amp;amp;&amp;amp; (b6 == 0x6B) &amp;amp;&amp;amp; (b7 == 0x4B) &amp;amp;&amp;amp; (b8 == 0x0D));&lt;br /&gt;
&lt;br /&gt;
    if (success)&lt;br /&gt;
        printf(&amp;quot;Success!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failure!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    return (success != 0 ? 0 : 1);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt; is the names of function in the source code, and they will show up in the object file and when compiled and in the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for SHA-1 you should rename &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OPENSSL_armcap_P&amp;lt;/tt&amp;gt;. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' sha1_armv4.h sha1_armv4.S&lt;br /&gt;
sed -i 's/sha1_block_data_order/MYLIB_sha1_block_data_order/g' sha1_armv4.h sha1_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/auxv.h&amp;gt;&lt;br /&gt;
#include &amp;quot;sha1-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* processor caps */&lt;br /&gt;
unsigned int OPENSSL_armcap_P = 0;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* set processor caps */&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_NEON)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV7_NEON;&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_SHA1)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV8_SHA1;&lt;br /&gt;
&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    uint8_t* buf = (uint8_t*)malloc(STEPS*64+64);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            sha1_block_data_order(state, buf, idx+1);&lt;br /&gt;
        total += 64*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 1 GHz */&lt;br /&gt;
    const double cpuFreq = 1000.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a [https://www.amazon.com/gp/product/B07D4L7GXZ Libre Computer Tritium H3] with a Cortex-A7 Sun7i SoC running at 1 GHz. A C/C++ SHA implementation runs about 22 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 -march=armv7 -c sha1-armv4.S -o sha1-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 sha1-armv7-test.c sha1-armv7.o -o sha1-armv7-test.exe&lt;br /&gt;
$ ./sha1-armv7-test.exe&lt;br /&gt;
180994048 bytes&lt;br /&gt;
57.59 mbs&lt;br /&gt;
16.56 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== iOS Builds ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sha1-armv4&amp;lt;/tt&amp;gt; can be configured for iOS. Simply use &amp;lt;tt&amp;gt;ios32&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ios64&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ perl sha1-armv4-large.pl ios32 sha1-armv4.S&lt;br /&gt;
$ clang -arch armv7 sha1-armv4.S -c&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ nm sha1-armv4.o&lt;br /&gt;
000012d0 s OPENSSL_armcap_P&lt;br /&gt;
00000004 C _OPENSSL_armcap_P&lt;br /&gt;
00000000 T _sha1_block_data_order&lt;br /&gt;
00001100 t sha1_block_data_order_armv8&lt;br /&gt;
00000560 t sha1_block_data_order_neon&lt;br /&gt;
&lt;br /&gt;
$ otool -tV sha1-armv4.o&lt;br /&gt;
sha1-armv4.o:&lt;br /&gt;
(__TEXT,__text) section&lt;br /&gt;
_sha1_block_data_order:&lt;br /&gt;
00000000        f8dfc4ec        ldr.w   r12, [pc, #0x4ec]&lt;br /&gt;
00000004        f2af0308        subw    r3, pc, #0x8&lt;br /&gt;
00000008        f853c00c        ldr.w   r12, [r3, r12]&lt;br /&gt;
0000000c        f8dcc000        ldr.w   r12, [r12]&lt;br /&gt;
00000010        f01c0f08        tst.w   r12, #0x8&lt;br /&gt;
00000014        f0418074        bne.w   sha1_block_data_order_armv8&lt;br /&gt;
00000018        f01c0f01        tst.w   r12, #0x1&lt;br /&gt;
0000001c        f04082a0        bne.w   sha1_block_data_order_neon&lt;br /&gt;
00000020        e92d5ff0        push.w  {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ARMv8 Builds ==&lt;br /&gt;
&lt;br /&gt;
If you need SHA for ARMv8 devices, which includes aarch64 and aarch32, then use &amp;lt;tt&amp;gt;sha1-armv8.pl&amp;lt;/tt&amp;gt;. You would use something like this in your scripts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ! perl sha1-armv8.pl linux64 sha1-armv8.S; then&lt;br /&gt;
    echo &amp;quot;Failed to translate SHA source file&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sha1-armv8.pl&amp;lt;/tt&amp;gt; provides the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;sha1_block_armv8&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_SHA&amp;diff=3148</id>
		<title>Cryptogams SHA</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_SHA&amp;diff=3148"/>
		<updated>2021-03-12T15:00:41Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Use linux64, not linux32, for ARMv8 builds.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 SHA-1 implementation. According to the head notes the ARMv4 implementation runs around 6.5 cycles per byte (cpb). Typical C/C++ implementations run around 10 to 20 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;sha1-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' sha1-armv4.h sha1-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation hashes full SHA blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
If you experience ''&amp;quot;unexpected reloc type 0x03&amp;quot;'' when building a shared object then see [https://sourceware.org/ml/binutils/2019-05/msg00287.html What does unexpected reloc type 0x03 mean?] on the Binutils mailing list.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams SHA. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/sha/asm/sha1-armv4-large.pl &amp;lt;tt&amp;gt;sha1-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/sha/asm/sha1-armv4-large.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;sha1-armv4-large.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;sha1-armv4-large.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl sha1-armv4-large.pl linux32 sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;sha1-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat sha1-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' sha1-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c sha1-armv4.S&lt;br /&gt;
$ nm sha1-armv4.o&lt;br /&gt;
00000000 T sha1_block_data_order&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble sha1-armv4.o&lt;br /&gt;
sha1-armv4.o:     file format elf32-littlearm&lt;br /&gt;
&lt;br /&gt;
Disassembly of section .text:&lt;br /&gt;
&lt;br /&gt;
00000000 &amp;lt;sha1_block_data_order&amp;gt;:&lt;br /&gt;
   0:   e92d5ff0        push    {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}&lt;br /&gt;
   4:   e0812302        add     r2, r1, r2, lsl #6&lt;br /&gt;
   8:   e89000f8        ldm     r0, {r3, r4, r5, r6, r7}&lt;br /&gt;
   c:   e59f858c        ldr     r8, [pc, #1420] ; 5a0 &amp;lt;sha1_block_data_order+0x5a0&amp;gt;&lt;br /&gt;
  10:   e1a0e00d        mov     lr, sp&lt;br /&gt;
  14:   e24dd03c        sub     sp, sp, #60     ; 0x3c&lt;br /&gt;
  18:   e1a05f65        ror     r5, r5, #30&lt;br /&gt;
  1c:   e1a06f66        ror     r6, r6, #30&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. Fortunately there is one function of interest called &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR sha1_block_data_order | grep '\.c'&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:95:    void sha1_block_data_order(void *c, const void *p, size_t len);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:115:        sha1_block_data_order(c, ptr, len / SHA_CBLOCK);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:615:        sha1_block_data_order(&amp;amp;key-&amp;gt;md, data, 1);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:631:        sha1_block_data_order(&amp;amp;key-&amp;gt;md, data, 1);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We need several more symbols, and and they are &amp;lt;tt&amp;gt;OPENSSL_armcap_P&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ARMV7_NEON&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ARMV8_SHA1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ grep -nIR OPENSSL_armcap_P&lt;br /&gt;
...&lt;br /&gt;
crypto/armcap.c:20:unsigned int OPENSSL_armcap_P = 0;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse, repeat for &amp;lt;tt&amp;gt;ARMV7_NEON&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ARMV8_SHA1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use. While it is not obvious, the &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; parameter from [[#Determine_API|Determine API]] is a block count, not a byte count.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 SHA1.    */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_SHA.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_SHA1_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_SHA1_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
extern unsigned int OPENSSL_armcap_P;&lt;br /&gt;
void sha1_block_data_order(void *state, const void *data, size_t blocks);&lt;br /&gt;
&lt;br /&gt;
/* Auxval caps */&lt;br /&gt;
#ifndef HWCAP_NEON&lt;br /&gt;
# define HWCAP_NEON (1 &amp;lt;&amp;lt; 12)&lt;br /&gt;
#endif&lt;br /&gt;
#ifndef HWCAP_SHA1&lt;br /&gt;
# define HWCAP_SHA1 (1 &amp;lt;&amp;lt; 5)&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/* OpenSSL caps */&lt;br /&gt;
#define ARMV7_NEON (1&amp;lt;&amp;lt;0)&lt;br /&gt;
#define ARMV8_SHA1 (1&amp;lt;&amp;lt;3)&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_SHA1_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's SHA with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 sha1-armv4-test.c ./sha1-armv4.o -o sha1-armv4-test.exe&lt;br /&gt;
$ ./sha1-armv4-test.exe&lt;br /&gt;
SHA1 hash of empty message: DA39A3EE5E6B4B0D...&lt;br /&gt;
Success!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/auxv.h&amp;gt;&lt;br /&gt;
#include &amp;quot;sha1-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* processor caps */&lt;br /&gt;
unsigned int OPENSSL_armcap_P = 0;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* processor caps */&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_NEON)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV7_NEON;&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_SHA1)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV8_SHA1;&lt;br /&gt;
&lt;br /&gt;
    /* empty message with padding */&lt;br /&gt;
    uint8_t message[64];&lt;br /&gt;
    memset(message, 0x00, sizeof(message));&lt;br /&gt;
    message[0] = 0x80;&lt;br /&gt;
&lt;br /&gt;
    /* initial state */&lt;br /&gt;
    uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};&lt;br /&gt;
&lt;br /&gt;
    sha1_block_data_order(state, message, 1);&lt;br /&gt;
&lt;br /&gt;
    const uint8_t b1 = (uint8_t)(state[0] &amp;gt;&amp;gt; 24);&lt;br /&gt;
    const uint8_t b2 = (uint8_t)(state[0] &amp;gt;&amp;gt; 16);&lt;br /&gt;
    const uint8_t b3 = (uint8_t)(state[0] &amp;gt;&amp;gt;  8);&lt;br /&gt;
    const uint8_t b4 = (uint8_t)(state[0] &amp;gt;&amp;gt;  0);&lt;br /&gt;
    const uint8_t b5 = (uint8_t)(state[1] &amp;gt;&amp;gt; 24);&lt;br /&gt;
    const uint8_t b6 = (uint8_t)(state[1] &amp;gt;&amp;gt; 16);&lt;br /&gt;
    const uint8_t b7 = (uint8_t)(state[1] &amp;gt;&amp;gt;  8);&lt;br /&gt;
    const uint8_t b8 = (uint8_t)(state[1] &amp;gt;&amp;gt;  0);&lt;br /&gt;
&lt;br /&gt;
    /* DA39A3EE5E6B4B0D... */&lt;br /&gt;
    printf(&amp;quot;SHA1 hash of empty message: &amp;quot;);&lt;br /&gt;
    printf(&amp;quot;%02X%02X%02X%02X%02X%02X%02X%02X...\n&amp;quot;,&lt;br /&gt;
        b1, b2, b3, b4, b5, b6, b7, b8);&lt;br /&gt;
&lt;br /&gt;
    int success = ((b1 == 0xDA) &amp;amp;&amp;amp; (b2 == 0x39) &amp;amp;&amp;amp; (b3 == 0xA3) &amp;amp;&amp;amp; (b4 == 0xEE) &amp;amp;&amp;amp;&lt;br /&gt;
                    (b5 == 0x5E) &amp;amp;&amp;amp; (b6 == 0x6B) &amp;amp;&amp;amp; (b7 == 0x4B) &amp;amp;&amp;amp; (b8 == 0x0D));&lt;br /&gt;
&lt;br /&gt;
    if (success)&lt;br /&gt;
        printf(&amp;quot;Success!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failure!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    return (success != 0 ? 0 : 1);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt; is the names of function in the source code, and they will show up in the object file and when compiled and in the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for SHA-1 you should rename &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OPENSSL_armcap_P&amp;lt;/tt&amp;gt;. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' sha1_armv4.h sha1_armv4.S&lt;br /&gt;
sed -i 's/sha1_block_data_order/MYLIB_sha1_block_data_order/g' sha1_armv4.h sha1_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/auxv.h&amp;gt;&lt;br /&gt;
#include &amp;quot;sha1-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* processor caps */&lt;br /&gt;
unsigned int OPENSSL_armcap_P = 0;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* set processor caps */&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_NEON)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV7_NEON;&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_SHA1)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV8_SHA1;&lt;br /&gt;
&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    uint8_t* buf = (uint8_t*)malloc(STEPS*64+64);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            sha1_block_data_order(state, buf, idx+1);&lt;br /&gt;
        total += 64*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 1 GHz */&lt;br /&gt;
    const double cpuFreq = 1000.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a [https://www.amazon.com/gp/product/B07D4L7GXZ Libre Computer Tritium H3] with a Cortex-A7 Sun7i SoC running at 1 GHz. A C/C++ SHA implementation runs about 22 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 -march=armv7 -c sha1-armv4.S -o sha1-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 sha1-armv7-test.c sha1-armv7.o -o sha1-armv7-test.exe&lt;br /&gt;
$ ./sha1-armv7-test.exe&lt;br /&gt;
180994048 bytes&lt;br /&gt;
57.59 mbs&lt;br /&gt;
16.56 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== iOS Builds ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sha1-armv4&amp;lt;/tt&amp;gt; can be configured for iOS. Simply use &amp;lt;tt&amp;gt;ios32&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ios64&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ perl sha1-armv4-large.pl ios32 sha1-armv4.S&lt;br /&gt;
$ clang -arch armv7 sha1-armv4.S -c&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ nm sha1-armv4.o&lt;br /&gt;
000012d0 s OPENSSL_armcap_P&lt;br /&gt;
00000004 C _OPENSSL_armcap_P&lt;br /&gt;
00000000 T _sha1_block_data_order&lt;br /&gt;
00001100 t sha1_block_data_order_armv8&lt;br /&gt;
00000560 t sha1_block_data_order_neon&lt;br /&gt;
&lt;br /&gt;
$ otool -tV sha1-armv4.o&lt;br /&gt;
sha1-armv4.o:&lt;br /&gt;
(__TEXT,__text) section&lt;br /&gt;
_sha1_block_data_order:&lt;br /&gt;
00000000        f8dfc4ec        ldr.w   r12, [pc, #0x4ec]&lt;br /&gt;
00000004        f2af0308        subw    r3, pc, #0x8&lt;br /&gt;
00000008        f853c00c        ldr.w   r12, [r3, r12]&lt;br /&gt;
0000000c        f8dcc000        ldr.w   r12, [r12]&lt;br /&gt;
00000010        f01c0f08        tst.w   r12, #0x8&lt;br /&gt;
00000014        f0418074        bne.w   sha1_block_data_order_armv8&lt;br /&gt;
00000018        f01c0f01        tst.w   r12, #0x1&lt;br /&gt;
0000001c        f04082a0        bne.w   sha1_block_data_order_neon&lt;br /&gt;
00000020        e92d5ff0        push.w  {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ARMv8 Builds ==&lt;br /&gt;
&lt;br /&gt;
If you need SHA for ARMv8 devices, which includes aarch64 and aarch32, then use &amp;lt;tt&amp;gt;sha1-armv8.pl&amp;lt;/tt&amp;gt;. You would use something like this in your scripts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ! perl sha1-armv8.pl linux64 sha1-armv8.S; then&lt;br /&gt;
    echo &amp;quot;Failed to translate SHA source file&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sha1-armv8.pl&amp;lt;/tt&amp;gt; provides the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;sha1_block_armv8&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=3147</id>
		<title>Cryptogams AES</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=3147"/>
		<updated>2021-03-12T15:00:18Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Use linux64, not linux32, for ARMv8 builds.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 AES implementation. According to the head notes the ARMv4 implementation runs around 22 to 40 cycles per byte (cpb). Typical C/C++ implementations run around 50 to 80 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;aes-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' aes-armv4.h aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation operates in ECB mode and encrypts or decrypts full AES blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
At the moment Clang is miscompiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Also see [https://bugs.llvm.org/show_bug.cgi?id=38133 LLVM Issue 38133]. You can work around the problem by compiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;-mthumb&amp;lt;/tt&amp;gt;, but all data must be aligned. If you don't use aligned buffers then a &amp;lt;tt&amp;gt;SIGBUS&amp;lt;/tt&amp;gt; could occur.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams AES. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/aes/asm/aes-armv4.pl &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/aes/asm/aes-armv4.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl aes-armv4.pl linux32 aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;aes-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat aes-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' aes-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&lt;br /&gt;
$ nm aes-armv4.o&lt;br /&gt;
000011c0 T AES_decrypt&lt;br /&gt;
00000540 T AES_encrypt&lt;br /&gt;
00000b60 T AES_set_decrypt_key&lt;br /&gt;
00000b80 T AES_set_enc2dec_key&lt;br /&gt;
00000820 T AES_set_encrypt_key&lt;br /&gt;
00000cc0 t AES_Td&lt;br /&gt;
00000000 t AES_Te&lt;br /&gt;
000012c0 t _armv4_AES_decrypt&lt;br /&gt;
00000640 t _armv4_AES_encrypt&lt;br /&gt;
00000b80 t _armv4_AES_set_enc2dec_key&lt;br /&gt;
00000820 t _armv4_AES_set_encrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble aes-armv4.o&lt;br /&gt;
aes-armv4.o:     file format elf32-littlearm&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
00000b60 &amp;lt;AES_set_decrypt_key&amp;gt;:&lt;br /&gt;
     b60:       e52de004        push    {lr}            ; (str lr, [sp, #-4]!)&lt;br /&gt;
     b64:       ebffff2d        bl      820 &amp;lt;AES_set_encrypt_key&amp;gt;&lt;br /&gt;
     b68:       e3300000        teq     r0, #0&lt;br /&gt;
     b6c:       e49de004        pop     {lr}            ; (ldr lr, [sp], #4)&lt;br /&gt;
     b70:       1afffff9        bne     b5c &amp;lt;AES_set_encrypt_key+0x33c&amp;gt;&lt;br /&gt;
     b74:       e1a00002        mov     r0, r2&lt;br /&gt;
     b78:       e1a01002        mov     r1, r2&lt;br /&gt;
     b7c:       eaffffff        b       b80 &amp;lt;AES_set_enc2dec_key&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And trace it back to the source code in &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;.globl  AES_set_decrypt_key&lt;br /&gt;
.type   AES_set_decrypt_key,%function&lt;br /&gt;
.align  5&lt;br /&gt;
AES_set_decrypt_key:&lt;br /&gt;
        str     lr,[sp,#-4]!            @ push lr&lt;br /&gt;
        bl      _armv4_AES_set_encrypt_key&lt;br /&gt;
        teq     r0,#0&lt;br /&gt;
        ldr     lr,[sp],#4              @ pop lr&lt;br /&gt;
        bne     .Labrt&lt;br /&gt;
&lt;br /&gt;
        mov     r0,r2                   @ AES_set_encrypt_key preserves r2,&lt;br /&gt;
        mov     r1,r2                   @ which is AES_KEY *key&lt;br /&gt;
        b       _armv4_AES_set_enc2dec_key&lt;br /&gt;
.size   AES_set_decrypt_key,.-AES_set_decrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. The functions of interest are &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_set_encrypt_key | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:632:int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examining &amp;lt;tt&amp;gt;aes_core.c:632&amp;lt;/tt&amp;gt; reveals the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   632  int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&lt;br /&gt;
   633                          AES_KEY *key)&lt;br /&gt;
   634  {&lt;br /&gt;
            ...&lt;br /&gt;
   728      return 0;&lt;br /&gt;
   729  }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next piece of information to discover is &amp;lt;tt&amp;gt;AES_KEY&amp;lt;/tt&amp;gt;. Again a quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; leads you to &amp;lt;tt&amp;gt;aes_key_st&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_KEY | grep typedef&lt;br /&gt;
include/openssl/aes.h:39:typedef struct aes_key_st AES_KEY;&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n include/openssl/aes.h&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    31  struct aes_key_st {&lt;br /&gt;
    32  # ifdef AES_LONG&lt;br /&gt;
    33      unsigned long rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    34  # else&lt;br /&gt;
    35      unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    36  # endif&lt;br /&gt;
    37      int rounds;&lt;br /&gt;
    38  };&lt;br /&gt;
    39  typedef struct aes_key_st AES_KEY;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, you need &amp;lt;tt&amp;gt;AES_MAXNR&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;aes.h&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -IR AES_MAXNR | grep define&lt;br /&gt;
include/openssl/aes.h:# define AES_MAXNR 14&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse repeat for &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;crypto/aes/aes_core.c:787&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_encrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:787:void AES_encrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   783  /*&lt;br /&gt;
   784   * Encrypt a single block&lt;br /&gt;
   785   * in and out can overlap&lt;br /&gt;
   786   */&lt;br /&gt;
   787  void AES_encrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   788                   const AES_KEY *key) {&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;aes_core.c:978&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_decrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:978:void AES_decrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
&lt;br /&gt;
   974  /*&lt;br /&gt;
   975   * Decrypt a single block&lt;br /&gt;
   976   * in and out can overlap&lt;br /&gt;
   977   */&lt;br /&gt;
   978  void AES_decrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   979                   const AES_KEY *key)&lt;br /&gt;
   980  {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 AES.     */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_AES.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define AES_MAXNR 14&lt;br /&gt;
&lt;br /&gt;
typedef struct AES_KEY_st {&lt;br /&gt;
    unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    int rounds;&lt;br /&gt;
} AES_KEY;&lt;br /&gt;
&lt;br /&gt;
int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
void AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
void AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_AES_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's AES with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 aes-armv4-test.c ./aes-armv4.o -o aes-armv4-test.exe&lt;br /&gt;
$ ./aes-armv4-test.exe&lt;br /&gt;
Encrypted plaintext!&lt;br /&gt;
Decrypted ciphertext!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* Test key from FIPS 197 */&lt;br /&gt;
    const uint8_t kb[] = {&lt;br /&gt;
        0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,&lt;br /&gt;
        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t pb[] = {&lt;br /&gt;
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,&lt;br /&gt;
        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t cb[] = {&lt;br /&gt;
        0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, &lt;br /&gt;
        0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /* Scratch */&lt;br /&gt;
    uint8_t buf[16];&lt;br /&gt;
    int result;&lt;br /&gt;
    &lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    result = AES_set_encrypt_key(kb, sizeof(kb)*8, &amp;amp; ekey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_encrypt(pb, buf, &amp;amp;ekey);&lt;br /&gt;
    if (memcmp(cb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Encrypted plaintext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to encrypt plaintext!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY dkey;&lt;br /&gt;
    result = AES_set_decrypt_key(kb, sizeof(kb)*8, &amp;amp; dkey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_decrypt(cb, buf, &amp;amp;dkey);&lt;br /&gt;
    if (memcmp(pb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Decrypted ciphertext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to decrypt ciphertext!\n&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt; are the names of two functions in the source code, and they will show up in the object file and when compiled and the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for AES you should rename all &amp;lt;tt&amp;gt;AES_*&amp;lt;/tt&amp;gt; names. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_decrypt/MYLIB_AES_decrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_encrypt/MYLIB_AES_encrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_decrypt_key/MYLIB_AES_set_decrypt_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_enc2dec_key/MYLIB_AES_set_enc2dec_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_encrypt_key/MYLIB_AES_set_encrypt_key/g' aes_armv4.h aes_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
typedef unsigned char byte;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    byte* buf = (byte*)malloc(STEPS*16+16);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    (void)AES_set_encrypt_key(buf, 16*8, &amp;amp;ekey);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            AES_encrypt(&amp;amp;buf[idx+i], &amp;amp;buf[idx+i+1], &amp;amp;ekey);&lt;br /&gt;
        total += 16*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 950 MHz */&lt;br /&gt;
    const double cpuFreq = 950.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a BananaPi with a Cortex-A7 Sun7i SoC running at 950 MHz. A C/C++ AES implementation runs about 65 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv7 -c aes-armv4.S -o aes-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 aes-armv7-test.c aes-armv7.o -o aes-armv7-test.exe&lt;br /&gt;
$ ./aes-armv7-test.exe&lt;br /&gt;
78426112 bytes&lt;br /&gt;
24.93 mbs&lt;br /&gt;
36.34 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the following is from a Wandboard Dual with a NXP i.MX6 Cortex-A9 running at 1 GHz.  A C/C++ implementation runs around 40 cpb.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./aes-armv7-test.exe&lt;br /&gt;
106029056 bytes&lt;br /&gt;
33.80 mbs&lt;br /&gt;
26.80 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Autotools ==&lt;br /&gt;
&lt;br /&gt;
If you are using Autotools you can add the following to &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; to conditionally compile &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; for A-32 platforms. You will need to detect ARM A-32 and set &amp;lt;tt&amp;gt;IS_ARM32&amp;lt;/tt&amp;gt; to non-0. Also see [https://www.gnu.org/software/automake/manual/html_node/Assembly-Support.html Automake Assembly Support] in section 8.13 of the manual.&lt;br /&gt;
&lt;br /&gt;
First, the &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Set ASM tools&lt;br /&gt;
AC_SUBST([CCAS], [$CC])&lt;br /&gt;
AC_SUBST([CCASFLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
# Used by Makefile.am to compile aes-armv4.S&lt;br /&gt;
if test &amp;quot;$IS_ARM32&amp;quot; != &amp;quot;0&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
   ## Save CFLAGS&lt;br /&gt;
   SAVED_CFLAGS=&amp;quot;$CFLAGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   CFLAGS=&amp;quot;-march=armv7-a -Wa,--noexecstack&amp;quot;&lt;br /&gt;
   AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
   AC_COMPILE_IFELSE(&lt;br /&gt;
      [AC_LANG_PROGRAM([])],&lt;br /&gt;
      [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
      [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
   )&lt;br /&gt;
&lt;br /&gt;
   if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
      AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
      AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
   else&lt;br /&gt;
&lt;br /&gt;
      CFLAGS=&amp;quot;-march=armv7-a&amp;quot;&lt;br /&gt;
      AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
      AC_COMPILE_IFELSE(&lt;br /&gt;
         [AC_LANG_PROGRAM([])],&lt;br /&gt;
         [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
         [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
      )&lt;br /&gt;
&lt;br /&gt;
      if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
         AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
      else&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
      fi&lt;br /&gt;
   fi&lt;br /&gt;
&lt;br /&gt;
   ## Restore CFLAGS&lt;br /&gt;
   CFLAGS=&amp;quot;$SAVED_CFLAGS&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
   # Required for other platforms&lt;br /&gt;
   AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second, the &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if CRYPTOGAMS_AES&lt;br /&gt;
&lt;br /&gt;
  aes_armv4_la_SOURCES = aes-armv4.S&lt;br /&gt;
  aes_armv4_la_CCASFLAGS = $(AM_CFLAGS) $(CRYPTOGAMS_AES)&lt;br /&gt;
&lt;br /&gt;
  pkginclude_HEADERS += aes-armv4.h&lt;br /&gt;
&lt;br /&gt;
endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ARMv8 Builds ==&lt;br /&gt;
&lt;br /&gt;
If you need AES for ARMv8 devices, which includes aarch64 and aarch32, then use &amp;lt;tt&amp;gt;aesv8-armx.pl&amp;lt;/tt&amp;gt;. You would use something like this in your scripts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ! perl aesv8-armx.pl linux64 armx_aes.S; then&lt;br /&gt;
    echo &amp;quot;Failed to translate AES source file&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;aesv8-armx.pl&amp;lt;/tt&amp;gt; provides the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_set_encrypt_key&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_set_decrypt_key&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_encrypt&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_decrypt&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=3146</id>
		<title>Cryptogams AES</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=3146"/>
		<updated>2021-03-12T14:53:11Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Update title for ARMv8 AES builds.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 AES implementation. According to the head notes the ARMv4 implementation runs around 22 to 40 cycles per byte (cpb). Typical C/C++ implementations run around 50 to 80 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;aes-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' aes-armv4.h aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation operates in ECB mode and encrypts or decrypts full AES blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
At the moment Clang is miscompiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Also see [https://bugs.llvm.org/show_bug.cgi?id=38133 LLVM Issue 38133]. You can work around the problem by compiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;-mthumb&amp;lt;/tt&amp;gt;, but all data must be aligned. If you don't use aligned buffers then a &amp;lt;tt&amp;gt;SIGBUS&amp;lt;/tt&amp;gt; could occur.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams AES. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/aes/asm/aes-armv4.pl &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/aes/asm/aes-armv4.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl aes-armv4.pl linux32 aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;aes-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat aes-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' aes-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&lt;br /&gt;
$ nm aes-armv4.o&lt;br /&gt;
000011c0 T AES_decrypt&lt;br /&gt;
00000540 T AES_encrypt&lt;br /&gt;
00000b60 T AES_set_decrypt_key&lt;br /&gt;
00000b80 T AES_set_enc2dec_key&lt;br /&gt;
00000820 T AES_set_encrypt_key&lt;br /&gt;
00000cc0 t AES_Td&lt;br /&gt;
00000000 t AES_Te&lt;br /&gt;
000012c0 t _armv4_AES_decrypt&lt;br /&gt;
00000640 t _armv4_AES_encrypt&lt;br /&gt;
00000b80 t _armv4_AES_set_enc2dec_key&lt;br /&gt;
00000820 t _armv4_AES_set_encrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble aes-armv4.o&lt;br /&gt;
aes-armv4.o:     file format elf32-littlearm&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
00000b60 &amp;lt;AES_set_decrypt_key&amp;gt;:&lt;br /&gt;
     b60:       e52de004        push    {lr}            ; (str lr, [sp, #-4]!)&lt;br /&gt;
     b64:       ebffff2d        bl      820 &amp;lt;AES_set_encrypt_key&amp;gt;&lt;br /&gt;
     b68:       e3300000        teq     r0, #0&lt;br /&gt;
     b6c:       e49de004        pop     {lr}            ; (ldr lr, [sp], #4)&lt;br /&gt;
     b70:       1afffff9        bne     b5c &amp;lt;AES_set_encrypt_key+0x33c&amp;gt;&lt;br /&gt;
     b74:       e1a00002        mov     r0, r2&lt;br /&gt;
     b78:       e1a01002        mov     r1, r2&lt;br /&gt;
     b7c:       eaffffff        b       b80 &amp;lt;AES_set_enc2dec_key&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And trace it back to the source code in &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;.globl  AES_set_decrypt_key&lt;br /&gt;
.type   AES_set_decrypt_key,%function&lt;br /&gt;
.align  5&lt;br /&gt;
AES_set_decrypt_key:&lt;br /&gt;
        str     lr,[sp,#-4]!            @ push lr&lt;br /&gt;
        bl      _armv4_AES_set_encrypt_key&lt;br /&gt;
        teq     r0,#0&lt;br /&gt;
        ldr     lr,[sp],#4              @ pop lr&lt;br /&gt;
        bne     .Labrt&lt;br /&gt;
&lt;br /&gt;
        mov     r0,r2                   @ AES_set_encrypt_key preserves r2,&lt;br /&gt;
        mov     r1,r2                   @ which is AES_KEY *key&lt;br /&gt;
        b       _armv4_AES_set_enc2dec_key&lt;br /&gt;
.size   AES_set_decrypt_key,.-AES_set_decrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. The functions of interest are &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_set_encrypt_key | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:632:int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examining &amp;lt;tt&amp;gt;aes_core.c:632&amp;lt;/tt&amp;gt; reveals the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   632  int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&lt;br /&gt;
   633                          AES_KEY *key)&lt;br /&gt;
   634  {&lt;br /&gt;
            ...&lt;br /&gt;
   728      return 0;&lt;br /&gt;
   729  }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next piece of information to discover is &amp;lt;tt&amp;gt;AES_KEY&amp;lt;/tt&amp;gt;. Again a quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; leads you to &amp;lt;tt&amp;gt;aes_key_st&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_KEY | grep typedef&lt;br /&gt;
include/openssl/aes.h:39:typedef struct aes_key_st AES_KEY;&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n include/openssl/aes.h&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    31  struct aes_key_st {&lt;br /&gt;
    32  # ifdef AES_LONG&lt;br /&gt;
    33      unsigned long rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    34  # else&lt;br /&gt;
    35      unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    36  # endif&lt;br /&gt;
    37      int rounds;&lt;br /&gt;
    38  };&lt;br /&gt;
    39  typedef struct aes_key_st AES_KEY;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, you need &amp;lt;tt&amp;gt;AES_MAXNR&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;aes.h&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -IR AES_MAXNR | grep define&lt;br /&gt;
include/openssl/aes.h:# define AES_MAXNR 14&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse repeat for &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;crypto/aes/aes_core.c:787&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_encrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:787:void AES_encrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   783  /*&lt;br /&gt;
   784   * Encrypt a single block&lt;br /&gt;
   785   * in and out can overlap&lt;br /&gt;
   786   */&lt;br /&gt;
   787  void AES_encrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   788                   const AES_KEY *key) {&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;aes_core.c:978&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_decrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:978:void AES_decrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
&lt;br /&gt;
   974  /*&lt;br /&gt;
   975   * Decrypt a single block&lt;br /&gt;
   976   * in and out can overlap&lt;br /&gt;
   977   */&lt;br /&gt;
   978  void AES_decrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   979                   const AES_KEY *key)&lt;br /&gt;
   980  {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 AES.     */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_AES.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define AES_MAXNR 14&lt;br /&gt;
&lt;br /&gt;
typedef struct AES_KEY_st {&lt;br /&gt;
    unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    int rounds;&lt;br /&gt;
} AES_KEY;&lt;br /&gt;
&lt;br /&gt;
int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
void AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
void AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_AES_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's AES with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 aes-armv4-test.c ./aes-armv4.o -o aes-armv4-test.exe&lt;br /&gt;
$ ./aes-armv4-test.exe&lt;br /&gt;
Encrypted plaintext!&lt;br /&gt;
Decrypted ciphertext!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* Test key from FIPS 197 */&lt;br /&gt;
    const uint8_t kb[] = {&lt;br /&gt;
        0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,&lt;br /&gt;
        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t pb[] = {&lt;br /&gt;
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,&lt;br /&gt;
        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t cb[] = {&lt;br /&gt;
        0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, &lt;br /&gt;
        0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /* Scratch */&lt;br /&gt;
    uint8_t buf[16];&lt;br /&gt;
    int result;&lt;br /&gt;
    &lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    result = AES_set_encrypt_key(kb, sizeof(kb)*8, &amp;amp; ekey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_encrypt(pb, buf, &amp;amp;ekey);&lt;br /&gt;
    if (memcmp(cb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Encrypted plaintext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to encrypt plaintext!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY dkey;&lt;br /&gt;
    result = AES_set_decrypt_key(kb, sizeof(kb)*8, &amp;amp; dkey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_decrypt(cb, buf, &amp;amp;dkey);&lt;br /&gt;
    if (memcmp(pb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Decrypted ciphertext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to decrypt ciphertext!\n&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt; are the names of two functions in the source code, and they will show up in the object file and when compiled and the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for AES you should rename all &amp;lt;tt&amp;gt;AES_*&amp;lt;/tt&amp;gt; names. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_decrypt/MYLIB_AES_decrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_encrypt/MYLIB_AES_encrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_decrypt_key/MYLIB_AES_set_decrypt_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_enc2dec_key/MYLIB_AES_set_enc2dec_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_encrypt_key/MYLIB_AES_set_encrypt_key/g' aes_armv4.h aes_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
typedef unsigned char byte;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    byte* buf = (byte*)malloc(STEPS*16+16);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    (void)AES_set_encrypt_key(buf, 16*8, &amp;amp;ekey);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            AES_encrypt(&amp;amp;buf[idx+i], &amp;amp;buf[idx+i+1], &amp;amp;ekey);&lt;br /&gt;
        total += 16*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 950 MHz */&lt;br /&gt;
    const double cpuFreq = 950.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a BananaPi with a Cortex-A7 Sun7i SoC running at 950 MHz. A C/C++ AES implementation runs about 65 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv7 -c aes-armv4.S -o aes-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 aes-armv7-test.c aes-armv7.o -o aes-armv7-test.exe&lt;br /&gt;
$ ./aes-armv7-test.exe&lt;br /&gt;
78426112 bytes&lt;br /&gt;
24.93 mbs&lt;br /&gt;
36.34 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the following is from a Wandboard Dual with a NXP i.MX6 Cortex-A9 running at 1 GHz.  A C/C++ implementation runs around 40 cpb.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./aes-armv7-test.exe&lt;br /&gt;
106029056 bytes&lt;br /&gt;
33.80 mbs&lt;br /&gt;
26.80 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Autotools ==&lt;br /&gt;
&lt;br /&gt;
If you are using Autotools you can add the following to &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; to conditionally compile &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; for A-32 platforms. You will need to detect ARM A-32 and set &amp;lt;tt&amp;gt;IS_ARM32&amp;lt;/tt&amp;gt; to non-0. Also see [https://www.gnu.org/software/automake/manual/html_node/Assembly-Support.html Automake Assembly Support] in section 8.13 of the manual.&lt;br /&gt;
&lt;br /&gt;
First, the &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Set ASM tools&lt;br /&gt;
AC_SUBST([CCAS], [$CC])&lt;br /&gt;
AC_SUBST([CCASFLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
# Used by Makefile.am to compile aes-armv4.S&lt;br /&gt;
if test &amp;quot;$IS_ARM32&amp;quot; != &amp;quot;0&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
   ## Save CFLAGS&lt;br /&gt;
   SAVED_CFLAGS=&amp;quot;$CFLAGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   CFLAGS=&amp;quot;-march=armv7-a -Wa,--noexecstack&amp;quot;&lt;br /&gt;
   AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
   AC_COMPILE_IFELSE(&lt;br /&gt;
      [AC_LANG_PROGRAM([])],&lt;br /&gt;
      [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
      [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
   )&lt;br /&gt;
&lt;br /&gt;
   if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
      AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
      AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
   else&lt;br /&gt;
&lt;br /&gt;
      CFLAGS=&amp;quot;-march=armv7-a&amp;quot;&lt;br /&gt;
      AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
      AC_COMPILE_IFELSE(&lt;br /&gt;
         [AC_LANG_PROGRAM([])],&lt;br /&gt;
         [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
         [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
      )&lt;br /&gt;
&lt;br /&gt;
      if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
         AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
      else&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
      fi&lt;br /&gt;
   fi&lt;br /&gt;
&lt;br /&gt;
   ## Restore CFLAGS&lt;br /&gt;
   CFLAGS=&amp;quot;$SAVED_CFLAGS&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
   # Required for other platforms&lt;br /&gt;
   AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second, the &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if CRYPTOGAMS_AES&lt;br /&gt;
&lt;br /&gt;
  aes_armv4_la_SOURCES = aes-armv4.S&lt;br /&gt;
  aes_armv4_la_CCASFLAGS = $(AM_CFLAGS) $(CRYPTOGAMS_AES)&lt;br /&gt;
&lt;br /&gt;
  pkginclude_HEADERS += aes-armv4.h&lt;br /&gt;
&lt;br /&gt;
endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ARMv8 Builds ==&lt;br /&gt;
&lt;br /&gt;
If you need AES for ARMv8 devices, which includes aarch64 and aarch32, then use &amp;lt;tt&amp;gt;aesv8-armx.pl&amp;lt;/tt&amp;gt;. You would use something like this in your scripts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ! perl aesv8-armx.pl linux32 armx_aes.S; then&lt;br /&gt;
    echo &amp;quot;Failed to translate AES source file&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;aesv8-armx.pl&amp;lt;/tt&amp;gt; provides the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_set_encrypt_key&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_set_decrypt_key&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_encrypt&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_decrypt&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_SHA&amp;diff=3145</id>
		<title>Cryptogams SHA</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_SHA&amp;diff=3145"/>
		<updated>2021-03-12T14:52:23Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on ARMv8 programs.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 SHA-1 implementation. According to the head notes the ARMv4 implementation runs around 6.5 cycles per byte (cpb). Typical C/C++ implementations run around 10 to 20 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;sha1-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' sha1-armv4.h sha1-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation hashes full SHA blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
If you experience ''&amp;quot;unexpected reloc type 0x03&amp;quot;'' when building a shared object then see [https://sourceware.org/ml/binutils/2019-05/msg00287.html What does unexpected reloc type 0x03 mean?] on the Binutils mailing list.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams SHA. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/sha/asm/sha1-armv4-large.pl &amp;lt;tt&amp;gt;sha1-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/sha/asm/sha1-armv4-large.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;sha1-armv4-large.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;sha1-armv4-large.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl sha1-armv4-large.pl linux32 sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;sha1-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat sha1-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' sha1-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c sha1-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c sha1-armv4.S&lt;br /&gt;
$ nm sha1-armv4.o&lt;br /&gt;
00000000 T sha1_block_data_order&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble sha1-armv4.o&lt;br /&gt;
sha1-armv4.o:     file format elf32-littlearm&lt;br /&gt;
&lt;br /&gt;
Disassembly of section .text:&lt;br /&gt;
&lt;br /&gt;
00000000 &amp;lt;sha1_block_data_order&amp;gt;:&lt;br /&gt;
   0:   e92d5ff0        push    {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}&lt;br /&gt;
   4:   e0812302        add     r2, r1, r2, lsl #6&lt;br /&gt;
   8:   e89000f8        ldm     r0, {r3, r4, r5, r6, r7}&lt;br /&gt;
   c:   e59f858c        ldr     r8, [pc, #1420] ; 5a0 &amp;lt;sha1_block_data_order+0x5a0&amp;gt;&lt;br /&gt;
  10:   e1a0e00d        mov     lr, sp&lt;br /&gt;
  14:   e24dd03c        sub     sp, sp, #60     ; 0x3c&lt;br /&gt;
  18:   e1a05f65        ror     r5, r5, #30&lt;br /&gt;
  1c:   e1a06f66        ror     r6, r6, #30&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. Fortunately there is one function of interest called &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR sha1_block_data_order | grep '\.c'&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:95:    void sha1_block_data_order(void *c, const void *p, size_t len);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:115:        sha1_block_data_order(c, ptr, len / SHA_CBLOCK);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:615:        sha1_block_data_order(&amp;amp;key-&amp;gt;md, data, 1);&lt;br /&gt;
crypto/evp/e_sha_cbc_hmac_sha1.c:631:        sha1_block_data_order(&amp;amp;key-&amp;gt;md, data, 1);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We need several more symbols, and and they are &amp;lt;tt&amp;gt;OPENSSL_armcap_P&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ARMV7_NEON&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ARMV8_SHA1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ grep -nIR OPENSSL_armcap_P&lt;br /&gt;
...&lt;br /&gt;
crypto/armcap.c:20:unsigned int OPENSSL_armcap_P = 0;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse, repeat for &amp;lt;tt&amp;gt;ARMV7_NEON&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ARMV8_SHA1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use. While it is not obvious, the &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; parameter from [[#Determine_API|Determine API]] is a block count, not a byte count.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 SHA1.    */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_SHA.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_SHA1_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_SHA1_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
extern unsigned int OPENSSL_armcap_P;&lt;br /&gt;
void sha1_block_data_order(void *state, const void *data, size_t blocks);&lt;br /&gt;
&lt;br /&gt;
/* Auxval caps */&lt;br /&gt;
#ifndef HWCAP_NEON&lt;br /&gt;
# define HWCAP_NEON (1 &amp;lt;&amp;lt; 12)&lt;br /&gt;
#endif&lt;br /&gt;
#ifndef HWCAP_SHA1&lt;br /&gt;
# define HWCAP_SHA1 (1 &amp;lt;&amp;lt; 5)&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
/* OpenSSL caps */&lt;br /&gt;
#define ARMV7_NEON (1&amp;lt;&amp;lt;0)&lt;br /&gt;
#define ARMV8_SHA1 (1&amp;lt;&amp;lt;3)&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_SHA1_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's SHA with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 sha1-armv4-test.c ./sha1-armv4.o -o sha1-armv4-test.exe&lt;br /&gt;
$ ./sha1-armv4-test.exe&lt;br /&gt;
SHA1 hash of empty message: DA39A3EE5E6B4B0D...&lt;br /&gt;
Success!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/auxv.h&amp;gt;&lt;br /&gt;
#include &amp;quot;sha1-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* processor caps */&lt;br /&gt;
unsigned int OPENSSL_armcap_P = 0;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* processor caps */&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_NEON)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV7_NEON;&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_SHA1)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV8_SHA1;&lt;br /&gt;
&lt;br /&gt;
    /* empty message with padding */&lt;br /&gt;
    uint8_t message[64];&lt;br /&gt;
    memset(message, 0x00, sizeof(message));&lt;br /&gt;
    message[0] = 0x80;&lt;br /&gt;
&lt;br /&gt;
    /* initial state */&lt;br /&gt;
    uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};&lt;br /&gt;
&lt;br /&gt;
    sha1_block_data_order(state, message, 1);&lt;br /&gt;
&lt;br /&gt;
    const uint8_t b1 = (uint8_t)(state[0] &amp;gt;&amp;gt; 24);&lt;br /&gt;
    const uint8_t b2 = (uint8_t)(state[0] &amp;gt;&amp;gt; 16);&lt;br /&gt;
    const uint8_t b3 = (uint8_t)(state[0] &amp;gt;&amp;gt;  8);&lt;br /&gt;
    const uint8_t b4 = (uint8_t)(state[0] &amp;gt;&amp;gt;  0);&lt;br /&gt;
    const uint8_t b5 = (uint8_t)(state[1] &amp;gt;&amp;gt; 24);&lt;br /&gt;
    const uint8_t b6 = (uint8_t)(state[1] &amp;gt;&amp;gt; 16);&lt;br /&gt;
    const uint8_t b7 = (uint8_t)(state[1] &amp;gt;&amp;gt;  8);&lt;br /&gt;
    const uint8_t b8 = (uint8_t)(state[1] &amp;gt;&amp;gt;  0);&lt;br /&gt;
&lt;br /&gt;
    /* DA39A3EE5E6B4B0D... */&lt;br /&gt;
    printf(&amp;quot;SHA1 hash of empty message: &amp;quot;);&lt;br /&gt;
    printf(&amp;quot;%02X%02X%02X%02X%02X%02X%02X%02X...\n&amp;quot;,&lt;br /&gt;
        b1, b2, b3, b4, b5, b6, b7, b8);&lt;br /&gt;
&lt;br /&gt;
    int success = ((b1 == 0xDA) &amp;amp;&amp;amp; (b2 == 0x39) &amp;amp;&amp;amp; (b3 == 0xA3) &amp;amp;&amp;amp; (b4 == 0xEE) &amp;amp;&amp;amp;&lt;br /&gt;
                    (b5 == 0x5E) &amp;amp;&amp;amp; (b6 == 0x6B) &amp;amp;&amp;amp; (b7 == 0x4B) &amp;amp;&amp;amp; (b8 == 0x0D));&lt;br /&gt;
&lt;br /&gt;
    if (success)&lt;br /&gt;
        printf(&amp;quot;Success!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failure!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    return (success != 0 ? 0 : 1);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt; is the names of function in the source code, and they will show up in the object file and when compiled and in the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for SHA-1 you should rename &amp;lt;tt&amp;gt;sha1_block_data_order&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OPENSSL_armcap_P&amp;lt;/tt&amp;gt;. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' sha1_armv4.h sha1_armv4.S&lt;br /&gt;
sed -i 's/sha1_block_data_order/MYLIB_sha1_block_data_order/g' sha1_armv4.h sha1_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/auxv.h&amp;gt;&lt;br /&gt;
#include &amp;quot;sha1-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* processor caps */&lt;br /&gt;
unsigned int OPENSSL_armcap_P = 0;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* set processor caps */&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_NEON)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV7_NEON;&lt;br /&gt;
    if (getauxval(AT_HWCAP) &amp;amp; HWCAP_SHA1)&lt;br /&gt;
        OPENSSL_armcap_P |= ARMV8_SHA1;&lt;br /&gt;
&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    uint8_t* buf = (uint8_t*)malloc(STEPS*64+64);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    uint32_t state[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            sha1_block_data_order(state, buf, idx+1);&lt;br /&gt;
        total += 64*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 1 GHz */&lt;br /&gt;
    const double cpuFreq = 1000.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a [https://www.amazon.com/gp/product/B07D4L7GXZ Libre Computer Tritium H3] with a Cortex-A7 Sun7i SoC running at 1 GHz. A C/C++ SHA implementation runs about 22 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;sha1-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 -march=armv7 -c sha1-armv4.S -o sha1-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 sha1-armv7-test.c sha1-armv7.o -o sha1-armv7-test.exe&lt;br /&gt;
$ ./sha1-armv7-test.exe&lt;br /&gt;
180994048 bytes&lt;br /&gt;
57.59 mbs&lt;br /&gt;
16.56 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== iOS Builds ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sha1-armv4&amp;lt;/tt&amp;gt; can be configured for iOS. Simply use &amp;lt;tt&amp;gt;ios32&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ios64&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ perl sha1-armv4-large.pl ios32 sha1-armv4.S&lt;br /&gt;
$ clang -arch armv7 sha1-armv4.S -c&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ nm sha1-armv4.o&lt;br /&gt;
000012d0 s OPENSSL_armcap_P&lt;br /&gt;
00000004 C _OPENSSL_armcap_P&lt;br /&gt;
00000000 T _sha1_block_data_order&lt;br /&gt;
00001100 t sha1_block_data_order_armv8&lt;br /&gt;
00000560 t sha1_block_data_order_neon&lt;br /&gt;
&lt;br /&gt;
$ otool -tV sha1-armv4.o&lt;br /&gt;
sha1-armv4.o:&lt;br /&gt;
(__TEXT,__text) section&lt;br /&gt;
_sha1_block_data_order:&lt;br /&gt;
00000000        f8dfc4ec        ldr.w   r12, [pc, #0x4ec]&lt;br /&gt;
00000004        f2af0308        subw    r3, pc, #0x8&lt;br /&gt;
00000008        f853c00c        ldr.w   r12, [r3, r12]&lt;br /&gt;
0000000c        f8dcc000        ldr.w   r12, [r12]&lt;br /&gt;
00000010        f01c0f08        tst.w   r12, #0x8&lt;br /&gt;
00000014        f0418074        bne.w   sha1_block_data_order_armv8&lt;br /&gt;
00000018        f01c0f01        tst.w   r12, #0x1&lt;br /&gt;
0000001c        f04082a0        bne.w   sha1_block_data_order_neon&lt;br /&gt;
00000020        e92d5ff0        push.w  {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ARMv8 Builds ==&lt;br /&gt;
&lt;br /&gt;
If you need SHA for ARMv8 devices, which includes aarch64 and aarch32, then use &amp;lt;tt&amp;gt;sha1-armv8.pl&amp;lt;/tt&amp;gt;. You would use something like this in your scripts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ! perl sha1-armv8.pl linux32 sha1-armv8.S; then&lt;br /&gt;
    echo &amp;quot;Failed to translate SHA source file&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sha1-armv8.pl&amp;lt;/tt&amp;gt; provides the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;sha1_block_armv8&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=3144</id>
		<title>Cryptogams AES</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=3144"/>
		<updated>2021-03-12T14:48:31Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on ARMv8 programs.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 AES implementation. According to the head notes the ARMv4 implementation runs around 22 to 40 cycles per byte (cpb). Typical C/C++ implementations run around 50 to 80 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;aes-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' aes-armv4.h aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation operates in ECB mode and encrypts or decrypts full AES blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
At the moment Clang is miscompiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Also see [https://bugs.llvm.org/show_bug.cgi?id=38133 LLVM Issue 38133]. You can work around the problem by compiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;-mthumb&amp;lt;/tt&amp;gt;, but all data must be aligned. If you don't use aligned buffers then a &amp;lt;tt&amp;gt;SIGBUS&amp;lt;/tt&amp;gt; could occur.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams AES. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/aes/asm/aes-armv4.pl &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/aes/asm/aes-armv4.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl aes-armv4.pl linux32 aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;aes-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat aes-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' aes-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&lt;br /&gt;
$ nm aes-armv4.o&lt;br /&gt;
000011c0 T AES_decrypt&lt;br /&gt;
00000540 T AES_encrypt&lt;br /&gt;
00000b60 T AES_set_decrypt_key&lt;br /&gt;
00000b80 T AES_set_enc2dec_key&lt;br /&gt;
00000820 T AES_set_encrypt_key&lt;br /&gt;
00000cc0 t AES_Td&lt;br /&gt;
00000000 t AES_Te&lt;br /&gt;
000012c0 t _armv4_AES_decrypt&lt;br /&gt;
00000640 t _armv4_AES_encrypt&lt;br /&gt;
00000b80 t _armv4_AES_set_enc2dec_key&lt;br /&gt;
00000820 t _armv4_AES_set_encrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble aes-armv4.o&lt;br /&gt;
aes-armv4.o:     file format elf32-littlearm&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
00000b60 &amp;lt;AES_set_decrypt_key&amp;gt;:&lt;br /&gt;
     b60:       e52de004        push    {lr}            ; (str lr, [sp, #-4]!)&lt;br /&gt;
     b64:       ebffff2d        bl      820 &amp;lt;AES_set_encrypt_key&amp;gt;&lt;br /&gt;
     b68:       e3300000        teq     r0, #0&lt;br /&gt;
     b6c:       e49de004        pop     {lr}            ; (ldr lr, [sp], #4)&lt;br /&gt;
     b70:       1afffff9        bne     b5c &amp;lt;AES_set_encrypt_key+0x33c&amp;gt;&lt;br /&gt;
     b74:       e1a00002        mov     r0, r2&lt;br /&gt;
     b78:       e1a01002        mov     r1, r2&lt;br /&gt;
     b7c:       eaffffff        b       b80 &amp;lt;AES_set_enc2dec_key&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And trace it back to the source code in &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;.globl  AES_set_decrypt_key&lt;br /&gt;
.type   AES_set_decrypt_key,%function&lt;br /&gt;
.align  5&lt;br /&gt;
AES_set_decrypt_key:&lt;br /&gt;
        str     lr,[sp,#-4]!            @ push lr&lt;br /&gt;
        bl      _armv4_AES_set_encrypt_key&lt;br /&gt;
        teq     r0,#0&lt;br /&gt;
        ldr     lr,[sp],#4              @ pop lr&lt;br /&gt;
        bne     .Labrt&lt;br /&gt;
&lt;br /&gt;
        mov     r0,r2                   @ AES_set_encrypt_key preserves r2,&lt;br /&gt;
        mov     r1,r2                   @ which is AES_KEY *key&lt;br /&gt;
        b       _armv4_AES_set_enc2dec_key&lt;br /&gt;
.size   AES_set_decrypt_key,.-AES_set_decrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. The functions of interest are &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_set_encrypt_key | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:632:int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examining &amp;lt;tt&amp;gt;aes_core.c:632&amp;lt;/tt&amp;gt; reveals the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   632  int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&lt;br /&gt;
   633                          AES_KEY *key)&lt;br /&gt;
   634  {&lt;br /&gt;
            ...&lt;br /&gt;
   728      return 0;&lt;br /&gt;
   729  }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next piece of information to discover is &amp;lt;tt&amp;gt;AES_KEY&amp;lt;/tt&amp;gt;. Again a quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; leads you to &amp;lt;tt&amp;gt;aes_key_st&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_KEY | grep typedef&lt;br /&gt;
include/openssl/aes.h:39:typedef struct aes_key_st AES_KEY;&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n include/openssl/aes.h&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    31  struct aes_key_st {&lt;br /&gt;
    32  # ifdef AES_LONG&lt;br /&gt;
    33      unsigned long rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    34  # else&lt;br /&gt;
    35      unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    36  # endif&lt;br /&gt;
    37      int rounds;&lt;br /&gt;
    38  };&lt;br /&gt;
    39  typedef struct aes_key_st AES_KEY;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, you need &amp;lt;tt&amp;gt;AES_MAXNR&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;aes.h&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -IR AES_MAXNR | grep define&lt;br /&gt;
include/openssl/aes.h:# define AES_MAXNR 14&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse repeat for &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;crypto/aes/aes_core.c:787&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_encrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:787:void AES_encrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   783  /*&lt;br /&gt;
   784   * Encrypt a single block&lt;br /&gt;
   785   * in and out can overlap&lt;br /&gt;
   786   */&lt;br /&gt;
   787  void AES_encrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   788                   const AES_KEY *key) {&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;aes_core.c:978&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_decrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:978:void AES_decrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
&lt;br /&gt;
   974  /*&lt;br /&gt;
   975   * Decrypt a single block&lt;br /&gt;
   976   * in and out can overlap&lt;br /&gt;
   977   */&lt;br /&gt;
   978  void AES_decrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   979                   const AES_KEY *key)&lt;br /&gt;
   980  {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 AES.     */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_AES.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define AES_MAXNR 14&lt;br /&gt;
&lt;br /&gt;
typedef struct AES_KEY_st {&lt;br /&gt;
    unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    int rounds;&lt;br /&gt;
} AES_KEY;&lt;br /&gt;
&lt;br /&gt;
int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
void AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
void AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_AES_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's AES with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 aes-armv4-test.c ./aes-armv4.o -o aes-armv4-test.exe&lt;br /&gt;
$ ./aes-armv4-test.exe&lt;br /&gt;
Encrypted plaintext!&lt;br /&gt;
Decrypted ciphertext!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* Test key from FIPS 197 */&lt;br /&gt;
    const uint8_t kb[] = {&lt;br /&gt;
        0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,&lt;br /&gt;
        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t pb[] = {&lt;br /&gt;
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,&lt;br /&gt;
        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t cb[] = {&lt;br /&gt;
        0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, &lt;br /&gt;
        0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /* Scratch */&lt;br /&gt;
    uint8_t buf[16];&lt;br /&gt;
    int result;&lt;br /&gt;
    &lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    result = AES_set_encrypt_key(kb, sizeof(kb)*8, &amp;amp; ekey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_encrypt(pb, buf, &amp;amp;ekey);&lt;br /&gt;
    if (memcmp(cb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Encrypted plaintext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to encrypt plaintext!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY dkey;&lt;br /&gt;
    result = AES_set_decrypt_key(kb, sizeof(kb)*8, &amp;amp; dkey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_decrypt(cb, buf, &amp;amp;dkey);&lt;br /&gt;
    if (memcmp(pb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Decrypted ciphertext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to decrypt ciphertext!\n&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt; are the names of two functions in the source code, and they will show up in the object file and when compiled and the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for AES you should rename all &amp;lt;tt&amp;gt;AES_*&amp;lt;/tt&amp;gt; names. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_decrypt/MYLIB_AES_decrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_encrypt/MYLIB_AES_encrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_decrypt_key/MYLIB_AES_set_decrypt_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_enc2dec_key/MYLIB_AES_set_enc2dec_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_encrypt_key/MYLIB_AES_set_encrypt_key/g' aes_armv4.h aes_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
typedef unsigned char byte;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    byte* buf = (byte*)malloc(STEPS*16+16);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    (void)AES_set_encrypt_key(buf, 16*8, &amp;amp;ekey);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            AES_encrypt(&amp;amp;buf[idx+i], &amp;amp;buf[idx+i+1], &amp;amp;ekey);&lt;br /&gt;
        total += 16*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 950 MHz */&lt;br /&gt;
    const double cpuFreq = 950.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a BananaPi with a Cortex-A7 Sun7i SoC running at 950 MHz. A C/C++ AES implementation runs about 65 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv7 -c aes-armv4.S -o aes-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 aes-armv7-test.c aes-armv7.o -o aes-armv7-test.exe&lt;br /&gt;
$ ./aes-armv7-test.exe&lt;br /&gt;
78426112 bytes&lt;br /&gt;
24.93 mbs&lt;br /&gt;
36.34 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the following is from a Wandboard Dual with a NXP i.MX6 Cortex-A9 running at 1 GHz.  A C/C++ implementation runs around 40 cpb.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./aes-armv7-test.exe&lt;br /&gt;
106029056 bytes&lt;br /&gt;
33.80 mbs&lt;br /&gt;
26.80 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Autotools ==&lt;br /&gt;
&lt;br /&gt;
If you are using Autotools you can add the following to &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; to conditionally compile &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; for A-32 platforms. You will need to detect ARM A-32 and set &amp;lt;tt&amp;gt;IS_ARM32&amp;lt;/tt&amp;gt; to non-0. Also see [https://www.gnu.org/software/automake/manual/html_node/Assembly-Support.html Automake Assembly Support] in section 8.13 of the manual.&lt;br /&gt;
&lt;br /&gt;
First, the &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Set ASM tools&lt;br /&gt;
AC_SUBST([CCAS], [$CC])&lt;br /&gt;
AC_SUBST([CCASFLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
# Used by Makefile.am to compile aes-armv4.S&lt;br /&gt;
if test &amp;quot;$IS_ARM32&amp;quot; != &amp;quot;0&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
   ## Save CFLAGS&lt;br /&gt;
   SAVED_CFLAGS=&amp;quot;$CFLAGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   CFLAGS=&amp;quot;-march=armv7-a -Wa,--noexecstack&amp;quot;&lt;br /&gt;
   AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
   AC_COMPILE_IFELSE(&lt;br /&gt;
      [AC_LANG_PROGRAM([])],&lt;br /&gt;
      [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
      [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
   )&lt;br /&gt;
&lt;br /&gt;
   if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
      AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
      AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
   else&lt;br /&gt;
&lt;br /&gt;
      CFLAGS=&amp;quot;-march=armv7-a&amp;quot;&lt;br /&gt;
      AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
      AC_COMPILE_IFELSE(&lt;br /&gt;
         [AC_LANG_PROGRAM([])],&lt;br /&gt;
         [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
         [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
      )&lt;br /&gt;
&lt;br /&gt;
      if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
         AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
      else&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
      fi&lt;br /&gt;
   fi&lt;br /&gt;
&lt;br /&gt;
   ## Restore CFLAGS&lt;br /&gt;
   CFLAGS=&amp;quot;$SAVED_CFLAGS&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
   # Required for other platforms&lt;br /&gt;
   AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second, the &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if CRYPTOGAMS_AES&lt;br /&gt;
&lt;br /&gt;
  aes_armv4_la_SOURCES = aes-armv4.S&lt;br /&gt;
  aes_armv4_la_CCASFLAGS = $(AM_CFLAGS) $(CRYPTOGAMS_AES)&lt;br /&gt;
&lt;br /&gt;
  pkginclude_HEADERS += aes-armv4.h&lt;br /&gt;
&lt;br /&gt;
endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ARMv8 ==&lt;br /&gt;
&lt;br /&gt;
If you need AES for ARMv8 devices, which includes aarch64 and aarch32, then use &amp;lt;tt&amp;gt;aesv8-armx.pl&amp;lt;/tt&amp;gt;. You would use something like this in your scripts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ! perl aesv8-armx.pl linux32 armx_aes.S; then&lt;br /&gt;
    echo &amp;quot;Failed to translate AES source file&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;aesv8-armx.pl&amp;lt;/tt&amp;gt; provides the following functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_set_encrypt_key&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_set_decrypt_key&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_encrypt&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;aes_v8_decrypt&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=License&amp;diff=3102</id>
		<title>License</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=License&amp;diff=3102"/>
		<updated>2020-07-22T13:35:17Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Update License terms. State current requirement to comply with both licenses.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;We appreciate material and works produced for the community. Documentation, patches, and sample programs help ensure the library is reliable and easy to use. To ensure the most benefit to the project and community, contributions to this wiki must be either:&lt;br /&gt;
&lt;br /&gt;
# existing material copied from a public domain source&lt;br /&gt;
# original content created by you and released under the current OpenSSL license (and any future version of it that the OpenSSL project may adopt)&lt;br /&gt;
# existing content already released under the current or future OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
The current [https://openssl.org/source/license.html OpenSSL license] is a combination of OpenSSL and Apache-style license. Both licenses must be complied with.&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 3.0 we are moving to purely an Apache 2.0 license; see our [https://www.openssl.org/blog/blog/categories/license/ blog posts].&lt;br /&gt;
&lt;br /&gt;
We do not accept patches through the Wiki.&lt;br /&gt;
&lt;br /&gt;
== Wiki Documentation ==&lt;br /&gt;
&lt;br /&gt;
[[Category:Wiki Usage]]&lt;br /&gt;
&lt;br /&gt;
All contributions to this wiki are considered to be released under the current OpenSSL License (and any future version of it) and contributors agree the contributed content is original, or copied from a public domain or similar free resource, or copied from OpenSSL.&lt;br /&gt;
&lt;br /&gt;
== Copyright Notice ==&lt;br /&gt;
&lt;br /&gt;
Use the following copyright notice for source files, sample programs on the wiki, etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;   Copyright OpenSSL &amp;lt;nowiki&amp;gt;[YEAR]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   Contents licensed under the terms of the OpenSSL license&lt;br /&gt;
   See https://www.openssl.org/source/license.html for details&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Legal]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Compilation_and_Installation&amp;diff=2904</id>
		<title>Compilation and Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Compilation_and_Installation&amp;diff=2904"/>
		<updated>2020-03-10T05:52:09Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on NO_FORK option.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following page is a combination of the &amp;lt;tt&amp;gt;INSTALL&amp;lt;/tt&amp;gt; file provided with the OpenSSL library and notes from the field. If you have questions about what you are doing or seeing, then you should consult &amp;lt;tt&amp;gt;INSTALL&amp;lt;/tt&amp;gt; since it contains the commands and specifies the behavior by the development team.&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses a custom build system to configure the library. Configuration will allow the library to set up the recursive makefiles from &amp;lt;tt&amp;gt;makefile.org&amp;lt;/tt&amp;gt;. Once configured, you use &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; to build the library. You should avoid custom build systems because they often miss details, like each architecture and platform has a unique &amp;lt;tt&amp;gt;opensslconf.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bn.h&amp;lt;/tt&amp;gt; generated by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You must use a C compiler to build the OpenSSL library. You cannot use a C++ compiler. Later, once the library is built, it is OK to create user programs with a C++ compiler. But the library proper must be built with a C compiler.&lt;br /&gt;
&lt;br /&gt;
There are two generations of build system. First is the build system used in OpenSSL 1.0.2 and below. The instructions below apply to it. Second is the build system for OpenSSL 1.1.0 and above. The instructions are similar, but not the same. For example, the second generation abandons the monolithic &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and places individual configurations in the &amp;lt;tt&amp;gt;Configurations&amp;lt;/tt&amp;gt; directory.  Also, the second generation is more platform agnostic and uses templates to produce a final, top level build file (&amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;descrip.mms&amp;lt;/tt&amp;gt;, what have you).&lt;br /&gt;
&lt;br /&gt;
After you configure and build the library, you should always perform a &amp;lt;tt&amp;gt;make test&amp;lt;/tt&amp;gt; to ensure the library performs as expected under its self tests. If you are building OpenSSL 1.1.0 and above, then you will also need PERL 5.10 or higher (see &amp;lt;tt&amp;gt;README.PERL&amp;lt;/tt&amp;gt; for details).&lt;br /&gt;
&lt;br /&gt;
OpenSSL's build system does not rely upon &amp;lt;tt&amp;gt;autotools&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;libtool&amp;lt;/tt&amp;gt;. Also see [http://www.openssl.org/support/faq.html#MISC5 Why aren't tools like 'autoconf' and 'libtool' used?] in the OpenSSL FAQ.&lt;br /&gt;
&lt;br /&gt;
== Retrieve source code ==&lt;br /&gt;
&lt;br /&gt;
The OpenSSL source code can be downloaded from [http://www.openssl.org/source/ OpenSSL Source Tarballs] or any suitable [http://www.openssl.org/source/mirror.html ftp mirror]. There are various versions including stable as well as unstable versions. &lt;br /&gt;
&lt;br /&gt;
The source code is managed via Git. Its referred to as Master. The repository is&lt;br /&gt;
&lt;br /&gt;
: git://git.openssl.org/openssl.git&lt;br /&gt;
&lt;br /&gt;
The source is also available via a [https://github.com/openssl/openssl GitHub] mirror. This repository is updated every 15 minutes.&lt;br /&gt;
&lt;br /&gt;
* [[Use_of_Git|Accessing OpenSSL source code via Git]]&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL is configured for a particular platform with protocol and behavior options using &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should avoid custom build systems because they often miss details, like each architecture and platform has a unique &amp;lt;tt&amp;gt;opensslconf.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bn.h&amp;lt;/tt&amp;gt; generated by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Supported Platforms ===&lt;br /&gt;
&lt;br /&gt;
You can run &amp;lt;tt&amp;gt;Configure LIST&amp;lt;/tt&amp;gt; to see a list of available platforms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure LIST&lt;br /&gt;
BC-32&lt;br /&gt;
BS2000-OSD&lt;br /&gt;
BSD-generic32&lt;br /&gt;
BSD-generic64&lt;br /&gt;
BSD-ia64&lt;br /&gt;
BSD-sparc64&lt;br /&gt;
BSD-sparcv8&lt;br /&gt;
BSD-x86&lt;br /&gt;
BSD-x86-elf&lt;br /&gt;
BSD-x86_64&lt;br /&gt;
Cygwin&lt;br /&gt;
Cygwin-x86_64&lt;br /&gt;
DJGPP&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your platform is not listed, then use a similar platform and tune the &amp;lt;tt&amp;gt;$cflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflags&amp;lt;/tt&amp;gt; by making a copy of the configure line and giving it its own name. &amp;lt;tt&amp;gt;$cflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflags&amp;lt;/tt&amp;gt; correspond to fields 2 and 6 in a configure line. An example of using a similar configure line is presented in [[Compilation_and_Installation#Using_RPATHs|Using RPATHs]].&lt;br /&gt;
&lt;br /&gt;
=== Configure &amp;amp; Config ===&lt;br /&gt;
&lt;br /&gt;
You use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; to tune the compile and installation process through options and switches. The difference between is &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; properly handles the host-arch-compiler triplet, and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; does not. &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; attempts to guess the triplet, so its a lot like autotool's &amp;lt;tt&amp;gt;config.guess&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can usually use &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; and it will do the right thing (from Ubuntu 13.04, x64):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config &lt;br /&gt;
Operating system: x86_64-whatever-linux2&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mac OS X can have issues (its often a neglected platform), and you will have to use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; ./Configure darwin64-x86_64-cc&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also configure on Darwin by exporting &amp;lt;tt&amp;gt;KERNEL_BITS&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export KERNEL_BITS=64&lt;br /&gt;
$ ./config shared no-ssl2 no-ssl3 enable-ec_nistp_64_gcc_128 --openssldir=/usr/local/ssl/macosx-x64/&lt;br /&gt;
Operating system: i686-apple-darwinDarwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you provide a option not known to configure or ask for help, then you get a brief help message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure --help&lt;br /&gt;
Usage: Configure [no-&amp;lt;cipher&amp;gt; ...] [enable-&amp;lt;cipher&amp;gt; ...] [experimental-&amp;lt;cipher&amp;gt; ...]&lt;br /&gt;
[-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared]&lt;br /&gt;
[[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR]&lt;br /&gt;
[--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And if you supply an unknown triplet: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure darwin64-x86_64-clang&lt;br /&gt;
Configuring for darwin64-x86_64-clang&lt;br /&gt;
Usage: Configure [no-&amp;lt;cipher&amp;gt; ...] [enable-&amp;lt;cipher&amp;gt; ...] [experimental-&amp;lt;cipher&amp;gt; ...]&lt;br /&gt;
[-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared]&lt;br /&gt;
[[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR]&lt;br /&gt;
[--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]&lt;br /&gt;
&lt;br /&gt;
pick os/compiler from:&lt;br /&gt;
BC-32 BS2000-OSD BSD-generic32 BSD-generic64 BSD-ia64 BSD-sparc64 BSD-sparcv8 &lt;br /&gt;
BSD-x86 BSD-x86-elf BSD-x86_64 Cygwin Cygwin-pre1.3 DJGPP MPE/iX-gcc OS2-EMX &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
NOTE: If in doubt, on Unix-ish systems use './config'.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
If you are prompted to run &amp;lt;tt&amp;gt;make depend&amp;lt;/tt&amp;gt;, then you must do so. For OpenSSL 1.0.2 and below, its required to update the standard distribution once configuration options change.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Since you've disabled or enabled at least one algorithm, you need to do&lt;br /&gt;
the following before building:&lt;br /&gt;
&lt;br /&gt;
	make depend&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 and above performs the dependency step for you, so you should not see the message. However, you should perform a &amp;lt;tt&amp;gt;make clean&amp;lt;/tt&amp;gt; to ensure the list of objects files is accurate after a reconfiguration.&lt;br /&gt;
&lt;br /&gt;
== Configure Options ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL has been around a long time, and it carries around a lot of cruft. For example, from above, SSLv2 is enabled by default. SSLv2 is completely broken, and you should disable it during configuration. You can disable protocols and provide other options through &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and the following lists some of them.&lt;br /&gt;
&lt;br /&gt;
'''Note''': if you specify a non-existent option, then the configure scripts will proceed without warning. For example, if you inadvertently specify '''no-sslv2''' rather than '''no-ssl2 no-ssl3''', the script will configure ''with'' SSLv2 and ''without'' warning for the unknown no-sslv2.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when building a shared object, both the static archive and shared objects are built. You do not need to do anything special to build both when '''shared''' is specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|+ OpenSSL Library Options&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;150px&amp;quot; | Option&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; class=&amp;quot;unsortable&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| --prefix=XXX || See [[#PREFIX_and_OPENSSLDIR|PREFIX and OPENSSLDIR]] in the next section (below).&lt;br /&gt;
|-&lt;br /&gt;
| --openssldir=XXX || See [[#PREFIX_and_OPENSSLDIR|PREFIX and OPENSSLDIR]] in the next section (below).&lt;br /&gt;
|-&lt;br /&gt;
| -d || Debug build of the library. Optimizations are disabled (no &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt; or similar) and &amp;lt;tt&amp;gt;libefence&amp;lt;/tt&amp;gt; is used (&amp;lt;tt&amp;gt;apt-get install electric-fence&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;yum install electric-fence&amp;lt;/tt&amp;gt;). TODO: Any other features?&lt;br /&gt;
|-&lt;br /&gt;
| shared || Build a shared object in addition to the static archive. You probably need a [[#Using_RPATHs|RPATH]] when enabling &amp;lt;tt&amp;gt;shared&amp;lt;/tt&amp;gt; to ensure &amp;lt;tt&amp;gt;openssl&amp;lt;/tt&amp;gt; uses the correct &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; after installation.&lt;br /&gt;
|-&lt;br /&gt;
| enable-ec_nistp_64_gcc_128 || Use on little endian platforms when GCC supports &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt;. ECDH is about 2 to 4 times faster. Not enabled by default because &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; can't determine it. Enable it if your compiler defines &amp;lt;tt&amp;gt;__SIZEOF_INT128__&amp;lt;/tt&amp;gt;, the CPU is little endian and it tolerates unaligned data access.&lt;br /&gt;
|-&lt;br /&gt;
| enable-capieng || Enables the Microsoft CAPI engine on Windows platforms. Used to access the Windows Certificate Store. Also see [http://openssl.6102.n7.nabble.com/Using-Windows-certificate-store-through-OpenSSL-td46788.html Using Windows certificate store through OpenSSL] on the OpenSSL developer list.&lt;br /&gt;
|-&lt;br /&gt;
| no-ssl2 || Disables SSLv2. &amp;lt;tt&amp;gt;OPENSSL_NO_SSL2&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-ssl3 || Disables SSLv3. &amp;lt;tt&amp;gt;OPENSSL_NO_SSL3&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-comp || Disables compression independent of &amp;lt;tt&amp;gt;zlib&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;OPENSSL_NO_COMP&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-idea || Disables IDEA algorithm. Unlike RC5 and MDC2, IDEA is enabled by default&lt;br /&gt;
|-&lt;br /&gt;
| no-asm || Disables assembly language routines (and uses C routines)&lt;br /&gt;
|-&lt;br /&gt;
| no-dtls || Disables DTLS in OpenSSL 1.1.0 and above&lt;br /&gt;
|-&lt;br /&gt;
| no-dtls1 || Disables DTLS in OpenSSL 1.0.2 and below&lt;br /&gt;
|-&lt;br /&gt;
| no-shared || Disables shared objects (only a static library is created)&lt;br /&gt;
|-&lt;br /&gt;
| no-hw || Disables hardware support (useful on mobile devices)&lt;br /&gt;
|-&lt;br /&gt;
| no-engine || Disables hardware support (useful on mobile devices)&lt;br /&gt;
|-&lt;br /&gt;
| no-threads || Disables threading support.&lt;br /&gt;
|-&lt;br /&gt;
| no-dso || Disables the OpenSSL DSO API (the library offers a shared object abstraction layer). If you disable DSO, then you must disable Engines also&lt;br /&gt;
|-&lt;br /&gt;
| no-err || Removes all error function names and error reason text to reduce footprint&lt;br /&gt;
|-&lt;br /&gt;
| no-npn/no-nextprotoneg || Disables Next Protocol Negotiation (NPN). Use &amp;lt;tt&amp;gt;no-nextprotoneg&amp;lt;/tt&amp;gt; for 1.1.0 and above; and &amp;lt;tt&amp;gt;no-npn&amp;lt;/tt&amp;gt; otherwise&lt;br /&gt;
|-&lt;br /&gt;
| no-psk || Disables Preshared Key (PSK). PSK provides mutual authentication independent of trusted authorities, but its rarely offered or used&lt;br /&gt;
|-&lt;br /&gt;
| no-srp || Disables Secure Remote Password (SRP). SRP provides mutual authentication independent of trusted authorities, but its rarely offered or used&lt;br /&gt;
|-&lt;br /&gt;
| no-ec2m || Used when configuring FIPS Capable Library with a FIPS Object Module that only includes prime curves. That is, use this switch if you use &amp;lt;tt&amp;gt;openssl-fips-ecp-2.0.5&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| no-weak-ssl-ciphers || Disables RC4. Available in OpenSSL 1.1.0 and above.&lt;br /&gt;
|-&lt;br /&gt;
| -DXXX || Defines XXX. For example, &amp;lt;tt&amp;gt;-DOPENSSL_NO_HEARTBEATS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| -DPEDANTIC || Defines PEDANTIC. The library will avoid some undefined behavior, like casting an unaligned byte array to a different pointer type. This define should be used if building OpenSSL with undefined behavior sanitizer (&amp;lt;tt&amp;gt;-fsanitize=undefined&amp;lt;/tt&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| -DOPENSSL_USE_IPV6=0 || Disables IPv6. Useful if OpenSSL encounters incorrect or inconsistent platform headers and mistakenly enables IPv6. Must be passed to &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; manually.&lt;br /&gt;
|-&lt;br /&gt;
| -DNO_FORK || Defines NO_FORK. Disables calls to &amp;lt;tt&amp;gt;fork&amp;lt;/tt&amp;gt;. Useful for operating systems like AppleTVOS, WatchOS, AppleTVSimulator and WatchSimulator.&lt;br /&gt;
|-&lt;br /&gt;
| -L''something'', -l''something'', -K''something'', -Wl,''something'' || Linker options, will become part of LDFLAGS.&lt;br /&gt;
|-&lt;br /&gt;
| -''anythingelse'', +''anythingelse'' || Compiler options, will become part of CFLAGS.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''''Note''''': on older OSes, like CentOS 5, BSD 5, and Windows XP or Vista, you will need to configure with &amp;lt;tt&amp;gt;no-async&amp;lt;/tt&amp;gt; when building OpenSSL 1.1.0 and above. The configuration system does not detect lack of the Posix feature on the platforms.&lt;br /&gt;
&lt;br /&gt;
'''''Note''''': you can verify compiler support for &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt; with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# gcc -dM -E - &amp;lt;/dev/null | grep __SIZEOF_INT128__  &lt;br /&gt;
#define __SIZEOF_INT128__ 16&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PREFIX and OPENSSLDIR ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; control the configuration of installed components. The behavior and interactions of &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; are slightly different between OpenSSL 1.0.2 and below, and OpenSSL 1.1.0 and above.&lt;br /&gt;
&lt;br /&gt;
The '''''rule of thumb''''' to use when you want something that &amp;quot;just works&amp;quot; for all recent versions of OpenSSL, including OpenSSL 1.0.2 and 1.1.0, is:&lt;br /&gt;
&lt;br /&gt;
* specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;&lt;br /&gt;
* set &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; to the same location&lt;br /&gt;
&lt;br /&gt;
One word of caution is ''avoid'' &amp;lt;tt&amp;gt;--prefix=/usr&amp;lt;/tt&amp;gt; when OpenSSL versions are '''''not''''' [[Binary_Compatibility|binary compatible]]. You will replace the distro's version of OpenSSL with your version of OpenSSL. It will most likely break everything, including the package management system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''OpenSSL 1.0.2 and below'''&lt;br /&gt;
&lt;br /&gt;
It is usually ''not'' necessary to specify &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; is ''not'' specified, then &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; is used. However, specifying ''only'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; may result in broken builds because the 1.0.2 build system attempts to build in a FIPS configuration.&lt;br /&gt;
&lt;br /&gt;
You can ''omit'' If &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and use &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. In this case, the paths for &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; will be used during configuration. If &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; is not specified, the the default &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used.&lt;br /&gt;
&lt;br /&gt;
The takeaway is &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used by default, and it can be overridden with &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. The rule of thumb applies for path overrides: specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''OpenSSL 1.1.0 and above'''&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 changed the behavior of install rules. You should specify both &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; to ensure &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt; works as expected.&lt;br /&gt;
&lt;br /&gt;
The takeaway is &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used by default, and it can be overridden with ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. The rule of thumb applies for path overrides: specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Debug Configuration ===&lt;br /&gt;
&lt;br /&gt;
From the list above, its possible to quickly configure a &amp;quot;debug&amp;quot; build with &amp;lt;tt&amp;gt;./config -d&amp;lt;/tt&amp;gt;. However, you can often get into a more amicable state ''without'' the [http://en.wikipedia.org/wiki/Electric_Fence Electric Fence] dependency by issuing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config no-asm -g3 -O0 -fno-omit-frame-pointer -fno-inline-functions&lt;br /&gt;
Operating system: x86_64-whatever-linux2&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
Configuring OpenSSL version 1.1.0-pre5-dev (0x0x10100005L)&lt;br /&gt;
    no-asm          [option]   OPENSSL_NO_ASM&lt;br /&gt;
    ...&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
IsMK1MF       =no&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-Wall -O3 -pthread -m64 -DL_ENDIAN  -g3 -O0 -fno-omit-frame-pointer&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Don't be alarmed about both &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;. The last setting ''&amp;quot;sticks&amp;quot;'', and that's the &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you are working in Visual Studio and you can't step into library calls, then see [http://stackoverflow.com/q/38249235 Step into not working, but can force stepping after some asm steps] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
=== Modifying Build Settings ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to work around OpenSSL's selections for building the library. For example, you might want to use &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt; for a mobile device (rather than &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt;), or you might want to use the &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt; compiler (rather than &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In case like these, its often easier to modify &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; rather than trying to add targets to the configure scripts. Below is a patch that modifies &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; for use under the iOS 7.0 SDK (which lacks &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;CFLAG&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;MAKEDEPPROG&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;$(CC) -M&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting and resetting of &amp;lt;tt&amp;gt;LANG&amp;lt;/tt&amp;gt; is required on Mac OSX to work around a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; bug or limitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;OLD_LANG=$LANG&lt;br /&gt;
unset LANG&lt;br /&gt;
&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's|\&amp;quot;iphoneos-cross\&amp;quot;\,\&amp;quot;llvm-gcc\:-O3|\&amp;quot;iphoneos-cross\&amp;quot;\,\&amp;quot;clang\:-Os|g' Configure&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/CC= cc/CC= clang/g' Makefile.org&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/CFLAG= -O/CFLAG= -Os/g' Makefile.org&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/MAKEDEPPROG=makedepend/MAKEDEPPROG=$(CC) -M/g' Makefile.org&lt;br /&gt;
&lt;br /&gt;
export LANG=$OLD_LANG&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After modification, be sure to dclean and configure again so the new settings are picked up:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;make dclean&lt;br /&gt;
&lt;br /&gt;
./config&lt;br /&gt;
make depend&lt;br /&gt;
make all&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using RPATHs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt;'s are supported by default on the BSD platforms, but not others. If you are working on Linux and compatibles, then you have to manually add an RPATH. One of the easiest ways to add a &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; is to configure with it as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config -Wl,-rpath=/usr/local/ssl/lib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Note well''''': you should use a RPATH when building both OpenSSL and your program. If you don't add a RPATH to both, then your program could runtime-link to the wrong version of OpenSSL.&lt;br /&gt;
&lt;br /&gt;
You can also add an &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; by hard coding the &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; into a configure line. For example, on Debian x86_64 open the file &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; in an editor, copy &amp;lt;tt&amp;gt;linux-x86_64&amp;lt;/tt&amp;gt;, name it &amp;lt;tt&amp;gt;linux-x86_64-rpath&amp;lt;/tt&amp;gt;, and make the following change to add the &amp;lt;tt&amp;gt;-rpath&amp;lt;/tt&amp;gt; option. Notice the addition of &amp;lt;tt&amp;gt;-Wl,-rpath=...&amp;lt;/tt&amp;gt; in two places.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;linux-x86_64-rpath&amp;quot;, &amp;quot;gcc:-m64 -DL_ENDIAN -O3 -Wall -Wl,-rpath=/usr/local/ssl/lib::&lt;br /&gt;
  -D_REENTRANT::-Wl,-rpath=/usr/local/ssl/lib -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:&lt;br /&gt;
  ${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64&amp;quot;,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Above, fields 2 and 6 were changed. They correspond to &amp;lt;tt&amp;gt;$cflag&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflag&amp;lt;/tt&amp;gt; in OpenSSL's builds system.&lt;br /&gt;
&lt;br /&gt;
Then, Configure with the new configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure linux-x86_64-rpath shared no-ssl2 no-ssl3 no-comp \&lt;br /&gt;
    --openssldir=/usr/local/ssl enable-ec_nistp_64_gcc_128&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, after &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, verify the settings stuck:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ readelf -d ./libssl.so | grep -i rpath&lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&lt;br /&gt;
$ readelf -d ./libcrypto.so | grep -i rpath&lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&lt;br /&gt;
$ readelf -d ./apps/openssl | grep -i rpath &lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you perform &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt;, then &amp;lt;tt&amp;gt;ldd&amp;lt;/tt&amp;gt; will produce expected results:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ldd /usr/local/ssl/lib/libssl.so&lt;br /&gt;
linux-vdso.so.1 =&amp;gt;  (0x00007ffceff6c000)&lt;br /&gt;
 ibcrypto.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007ff5eff96000)&lt;br /&gt;
...&lt;br /&gt;
    &lt;br /&gt;
$ ldd /usr/local/ssl/bin/openssl &lt;br /&gt;
linux-vdso.so.1 =&amp;gt;  (0x00007ffc30d3a000)&lt;br /&gt;
libssl.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libssl.so.1.0.0 (0x00007f9e8372e000)&lt;br /&gt;
libcrypto.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007f9e832c0000)&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== FIPS Capable Library ===&lt;br /&gt;
&lt;br /&gt;
If you want to use FIPS validated cryptography, you download, build and install the FIPS Object Module (&amp;lt;tt&amp;gt;openssl-fips-2.0.5.tar.gz&amp;lt;/tt&amp;gt;) according to the [https://www.openssl.org/docs/fips/UserGuide-2.0.pdf FIPS User Guide 2.0] and [https://www.openssl.org/docs/fips/SecurityPolicy-2.0.pdf FIPS 140-2 Security Policy]. You then download, build and install the FIPS Capable Library (&amp;lt;tt&amp;gt;openssl-1.0.1e.tar.gz&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
When configuring the FIPS Capable Library, you must use &amp;lt;tt&amp;gt;fips&amp;lt;/tt&amp;gt; as an option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config fips &amp;lt;other options ...&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are configuring the FIPS Capable Library with only prime curves (&amp;lt;tt&amp;gt;openssl-fips-ecp-2.0.5.tar.gz&amp;lt;/tt&amp;gt;), then you must configure with &amp;lt;tt&amp;gt;no-ec2m&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config fips no-ec2m &amp;lt;other options ...&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Compile Time Checking ===&lt;br /&gt;
&lt;br /&gt;
If you disable an option during configure, you can check if it's available through &amp;lt;tt&amp;gt;OPENSSL_NO_*&amp;lt;/tt&amp;gt; defines. OpenSSL writes the configure options to &amp;lt;tt&amp;gt;&amp;lt;openssl/opensslconf.h&amp;gt;&amp;lt;/tt&amp;gt;. For example, if you want to know if SSLv3 is available, then you would perform the following in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/opensslconf.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#if !defined(OPENSSL_NO_SSL3)&lt;br /&gt;
  /* SSLv3 is available */&lt;br /&gt;
#endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compilation ==&lt;br /&gt;
&lt;br /&gt;
After configuring the library, you should run &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;. If prompted, there's usually no need to &amp;lt;tt&amp;gt;make depend&amp;lt;/tt&amp;gt; since you are building from a clean download.&lt;br /&gt;
&lt;br /&gt;
==== Quick ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config &amp;lt;nowiki&amp;gt;&amp;lt;options ...&amp;gt; --openssldir=/usr/local/ssl&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
make&lt;br /&gt;
make test&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Various options can be found examining the &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; file (there is a well commented block at its top). OpenSSL ships with SSLv2, SSLv3 and Compression enabled by default (see &amp;lt;tt&amp;gt;my $disabled&amp;lt;/tt&amp;gt;), so you might want to use &amp;lt;tt&amp;gt;no-ssl2 no-ssl3&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;no-ssl3&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;no-comp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Platfom specific ==&lt;br /&gt;
&lt;br /&gt;
=== Linux ===&lt;br /&gt;
&lt;br /&gt;
==== Intel ====&lt;br /&gt;
&lt;br /&gt;
==== ARM ====&lt;br /&gt;
&lt;br /&gt;
==== X32 (ILP32) ====&lt;br /&gt;
&lt;br /&gt;
X32 uses the 32-bit data model (ILP32) on x86_64/amd64. To properly configure for X32 under current OpenSSL distributions, you must use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and use the x32 triplet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# ./Configure LIST | grep x32&lt;br /&gt;
linux-x32&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# ./Configure linux-x32      &lt;br /&gt;
Configuring OpenSSL version 1.1.0-pre6-dev (0x0x10100006L)&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN (skip dir)&lt;br /&gt;
    ...&lt;br /&gt;
Configuring for linux-x32&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-Wall -O3 -pthread -mx32 -DL_ENDIAN &lt;br /&gt;
SHARED_CFLAG  =-fPIC&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If using an amd64-compatible processor and GCC with that supports &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt;, then you usually add &amp;lt;tt&amp;gt;enable-ec_nistp_64_gcc_128 &amp;lt;/tt&amp;gt; in addition to your other flags.&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
3noch wrote a VERY good guide in 2012 [https://web.archive.org/web/20161123004257/http://developer.covenanteyes.com/building-openssl-for-visual-studio// here] (PLEASE NOTE: the guide was written in 2012 and is no longer available at the original location; the link now points to an archived version at the Internet Archive Wayback Machine).&lt;br /&gt;
&lt;br /&gt;
Like he said in his article, make absolutely sure to create separate directories for 32 and 64 bit versions.&lt;br /&gt;
&lt;br /&gt;
==== W32 / Windows NT - Windows 9x ====&lt;br /&gt;
&lt;br /&gt;
type INSTALL.W32&lt;br /&gt;
&lt;br /&gt;
* you need Perl for Win32.  Unless you will build on Cygwin, you will need ActiveState Perl, available from http://www.activestate.com/ActivePerl.&lt;br /&gt;
* one of the following C compilers:&lt;br /&gt;
** Visual C++&lt;br /&gt;
** Borland C&lt;br /&gt;
** GNU C (Cygwin or MinGW)&lt;br /&gt;
* Netwide Assembler, a.k.a. NASM, available from http://nasm.sourceforge.net/ is required if you intend to utilize assembler modules. Note that NASM is now the only supported assembler.&lt;br /&gt;
&lt;br /&gt;
==== W64 ====&lt;br /&gt;
&lt;br /&gt;
Read first the INSTALL.W64 documentation note containing some specific 64bits information.&lt;br /&gt;
See also INSTALL.W32 that still provides additonnal build information common to both the 64 and 32 bit versions.&lt;br /&gt;
&lt;br /&gt;
You may be surprised: the 64bit artefacts are indeed output in the out32* sub-directories and bear names ending *32.dll. Fact is the 64 bit compile target is so far an incremental change over the legacy 32bit windows target. Numerous compile flags are still labelled &amp;quot;32&amp;quot; although those do apply to both 32 and 64bit targets.&lt;br /&gt;
&lt;br /&gt;
The important pre-requisites are to have PERL available (for essential file processing so as to prepare sources and scripts for the target OS) and of course a C compiler like Microsoft Visual Studio for C/C++. Also note the procedure changed at OpenSSL 1.1.0 and is more streamlined. Also see [https://stackoverflow.com/q/39076244/608639 Why there is no ms\do_ms.bat after perl Configure VC-WIN64A] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.1.0 ===&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 and above perform these steps:&lt;br /&gt;
&lt;br /&gt;
# Ensure you have perl installed on your machine (e.g. ActiveState or Strawberry), and available on your %PATH%&lt;br /&gt;
# Ensure you have NASM installed on your machine, and available on your %PATH%&lt;br /&gt;
# Extract the source files to your folder, here &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# Launch Visual Studio tool x64 Cross Tools Command prompt&lt;br /&gt;
# Goto your defined folder &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure for the target OS with &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt; or other configurations to be found in the INSTALL file (e.g. UNIX targets). &lt;br /&gt;
## For instance: &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;.&lt;br /&gt;
# (''Optional'') In case you compiled before on 32 or 64-bits, make sure you run &amp;lt;code&amp;gt;nmake clean&amp;lt;/code&amp;gt; to prevent trouble across 32 and 64-bits which share output folder.&lt;br /&gt;
# Now build with: &amp;lt;code&amp;gt;nmake&amp;lt;/code&amp;gt;&lt;br /&gt;
# Output can be found in the '''root''' of your folder as '''libcrypto-1_1x64.dll''' and '''libssl-1_1-x64.dll''' (with all the build additionals such as .pdb .lik or static .lib). You may check this is true 64bit code using the Visual Studio tool 'dumpbin'. For instance &amp;lt;code&amp;gt;dumpbin  /headers libcrypto-1_1x64.dll | more&amp;lt;/code&amp;gt;, and look at the FILE HEADER section.&lt;br /&gt;
# Test the code using the 'test' make target, by running &amp;lt;code&amp;gt;nmake test&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Reminder, clean your code to prevent issues the next time you compile for a different target. See step 7.&lt;br /&gt;
&lt;br /&gt;
==== Windows CE ====&lt;br /&gt;
'' Not specified ''&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.0.2 ===&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.0.2 and earlier the procedure is as follows.&lt;br /&gt;
&lt;br /&gt;
# Ensure you have perl installed on your machine (e.g. ActiveState or Strawberry), and available on your %PATH%&lt;br /&gt;
# Ensure you have NASM installed on your machine, and available on your %PATH%&lt;br /&gt;
# launch a Visual Studio tool x64 Cross Tools Command prompt&lt;br /&gt;
# change to the directory where you have copied openssl sources &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# configure for the target OS with the command &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;. You may also be interested to set more configuration options as documented in the general INSTALL note (for UNIX targets). For instance: &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;.&lt;br /&gt;
# prepare the target environment with the command: &amp;lt;code&amp;gt;ms\do_win64a&amp;lt;/code&amp;gt;&lt;br /&gt;
# ensure you start afresh and notably without linkable products from a previous 32bit compile (as 32 and 64 bits compiling still share common directories) with the command: &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak clean&amp;lt;/code&amp;gt; for the DLL target and &amp;lt;code&amp;gt;nmake -f ms\nt.mak clean&amp;lt;/code&amp;gt; for static libraries.&lt;br /&gt;
# build the code with: &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak&amp;lt;/code&amp;gt; (respectively &amp;lt;code&amp;gt;nmake -f ms\nt.mak&amp;lt;/code&amp;gt; )&lt;br /&gt;
# the artefacts will be found in sub directories out32dll and out32dll.dbg (respectively out32 and out32.dbg for static libraries). The libcrypto and ssl libraries are still named libeay32.lib and ssleay32.lib, and associated includes in inc32 ! You may check this is true 64bit code using the Visual Studio tool 'dumpbin'. For instance &amp;lt;code&amp;gt;dumpbin  /headers out32dll/libeay32.lib | more&amp;lt;/code&amp;gt;, and look at the FILE HEADER section.&lt;br /&gt;
# test the code using the various *test.exe programs in out32dll. Use the 'test' make target to run all tests as in &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak test&amp;lt;/code&amp;gt;&lt;br /&gt;
# we recommend that you move/copy needed includes and libraries from the &amp;quot;32&amp;quot; directories under a new explicit directory tree for 64bit applications from where you will import and link your target applications, similar to that explained in INSTALL.W32.&lt;br /&gt;
&lt;br /&gt;
==== Windows CE ====&lt;br /&gt;
&lt;br /&gt;
=== OS X ===&lt;br /&gt;
&lt;br /&gt;
The earlier discussion presented a lot of information (and some of it had OS X information). Here are the TLDR versions to configure, build and install the library.&lt;br /&gt;
&lt;br /&gt;
If configuring for 64-bit OS X, then use a command similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./Configure darwin64-x86_64-cc shared enable-ec_nistp_64_gcc_128 no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl/macos-x86_64&lt;br /&gt;
make depend&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If configuring for 32-bit OS X, then use a command similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./Configure darwin-i386-cc shared no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl/macosx-i386&lt;br /&gt;
make depend&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to build a multiarch OpenSSL library, then see this answer on Stack Overflow: [http://stackoverflow.com/a/25531033/608639 Build Multiarch OpenSSL on OS X].&lt;br /&gt;
&lt;br /&gt;
=== iOS ===&lt;br /&gt;
&lt;br /&gt;
The following builds OpenSSL for iOS using the iPhoneOS SDK. The configuration avoids the dynamic library the DSO interface and engines.&lt;br /&gt;
&lt;br /&gt;
If you run &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt;, then the headers will be installed in &amp;lt;tt&amp;gt;/usr/local/openssl-ios/include&amp;lt;/tt&amp;gt; and libraries will be installed in &amp;lt;tt&amp;gt;/usr/local/openssl-ios/lib&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== 32-bit ====&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 and above, a 32-bit iOS cross-compiles uses the &amp;lt;tt&amp;gt;ios-cross&amp;lt;/tt&amp;gt; target, and options similar to &amp;lt;tt&amp;gt;--prefix=/usr/local/openssl-ios&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure ios-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios&lt;br /&gt;
&lt;br /&gt;
Configuring OpenSSL version 1.1.1-dev (0x10101000L)&lt;br /&gt;
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-dynamic-engine [forced]&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
Configuring for ios-cross&lt;br /&gt;
&lt;br /&gt;
PERL          =perl&lt;br /&gt;
PERLVERSION   =5.16.2 for darwin-thread-multi-2level&lt;br /&gt;
HASHBANGPERL  =/usr/bin/env perl&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-O3 -D_REENTRANT -arch armv7 -mios-version-min=6.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
CXX           =c++&lt;br /&gt;
CXXFLAG       =-O3 -D_REENTRANT -arch armv7 -mios-version-min=6.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
DEFINES       =NDEBUG OPENSSL_THREADS OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_PIC OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_GF2m SHA1_ASM SHA256_ASM SHA512_ASM AES_ASM BSAES_ASM GHASH_ASM ECP_NISTZ256_ASM POLY1305_ASM&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are working with OpenSSL 1.0.2 or below, then use the &amp;lt;tt&amp;gt;iphoneos-cross&amp;lt;/tt&amp;gt; target.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure iphoneos-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios&lt;br /&gt;
Configuring for iphoneos-cross&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-engine       [option]   OPENSSL_NO_ENGINE (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-hw           [option]   OPENSSL_NO_HW&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS (skip dir)&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
IsMK1MF=0&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-DOPENSSL_THREADS -D_REENTRANT -O3 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fomit-frame-pointer -fno-common&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 64-bit ====&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 , a 64-bit iOS cross-compiles uses the &amp;lt;tt&amp;gt;ios64-cross&amp;lt;/tt&amp;gt; target, and &amp;lt;tt&amp;gt;--prefix=/usr/local/openssl-ios64&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;ios64-cross&amp;lt;/tt&amp;gt;. There is no built-in 64-bit iOS support for OpenSSL 1.0.2 or below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure ios64-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios64&lt;br /&gt;
&lt;br /&gt;
Configuring OpenSSL version 1.1.1-dev (0x10101000L)&lt;br /&gt;
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-dynamic-engine [forced]&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
Configuring for ios64-cross&lt;br /&gt;
&lt;br /&gt;
PERL          =perl&lt;br /&gt;
PERLVERSION   =5.16.2 for darwin-thread-multi-2level&lt;br /&gt;
HASHBANGPERL  =/usr/bin/env perl&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
CXX           =c++&lt;br /&gt;
CXXFLAG       =-O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
DEFINES       =NDEBUG OPENSSL_THREADS OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_PIC OPENSSL_BN_ASM_MONT SHA1_ASM SHA256_ASM SHA512_ASM VPAES_ASM ECP_NISTZ256_ASM POLY1305_ASM&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Android ===&lt;br /&gt;
&lt;br /&gt;
Visit [[Android]] and [[FIPS Library and Android]].&lt;br /&gt;
&lt;br /&gt;
=== More ===&lt;br /&gt;
&lt;br /&gt;
==== VAX/VMS ====&lt;br /&gt;
&lt;br /&gt;
I you wonder what are files ending with .com like test/testca.com those are VAX/VMX scripts.&lt;br /&gt;
This code is still maintained.&lt;br /&gt;
&lt;br /&gt;
==== OS/2 ====&lt;br /&gt;
&lt;br /&gt;
==== NetWare ====&lt;br /&gt;
5.x 6.x&lt;br /&gt;
&lt;br /&gt;
==== HP-UX ====&lt;br /&gt;
[[HP-UX Itanium FIPS and OpenSSL build]]&lt;br /&gt;
&lt;br /&gt;
==Autoconf==&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses its own configuration system, and does not use Autoconf. However, a number of popular projects use both OpenSSL and Autoconf, and it would be useful to detect either &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. To craft a feature test for OpenSSL that recognizes both &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;, you can use the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if test &amp;quot;$with_openssl&amp;quot; = yes ; then&lt;br /&gt;
  dnl Order matters!&lt;br /&gt;
  if test &amp;quot;$PORTNAME&amp;quot; != &amp;quot;win32&amp;quot;; then&lt;br /&gt;
     AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_CHECK_LIB(ssl, OPENSSL_init_ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_CHECK_LIB(ssl, SSL_library_init, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])])&lt;br /&gt;
  else&lt;br /&gt;
     AC_SEARCH_LIBS(CRYPTO_new_ex_data, eay32 crypto, [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_SEARCH_LIBS(OPENSSL_init_ssl, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_SEARCH_LIBS(SSL_library_init, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])&lt;br /&gt;
  fi&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many thanks to the Postgres folks for donating part of their &amp;lt;tt&amp;gt;configure.in&amp;lt;/tt&amp;gt;. Also see [http://stackoverflow.com/q/39285733 How to tell Autoconf “require symbol A or B” from LIB?] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
[[Category:Shell level]]&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
[[Category:Compilation]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Self_Test_Failures&amp;diff=2903</id>
		<title>Self Test Failures</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Self_Test_Failures&amp;diff=2903"/>
		<updated>2020-02-09T16:17:01Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on OpenSSL 1.1.x&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The OpenSSL library includes a test suite that exercises components from both &amp;lt;tt&amp;gt;libcrypto.a&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libssl.a&amp;lt;/tt&amp;gt;. Ensuring the library builds and executes its tests properly is a keystone to using the library.&lt;br /&gt;
&lt;br /&gt;
This page will show you how to isolate the test and the cause under many conditions. The more information you can supply with a bug report or pull request, the easier it is for the team to identify the failure or accept proposed changes. Also see [http://www.openssl.org/docs/faq.html#BUILD17 Item 17. I think I've found a bug, what should I do?] in the OpenSSL FAQ.&lt;br /&gt;
&lt;br /&gt;
Generally speaking, there are two generations of self tests. The first generation is from OpenSSL 1.0.2 and below. The second generation is from OpenSSL 1.1.0 and above. This page focuses on the second generation, or OpenSSL 1.1.0 and above.&lt;br /&gt;
&lt;br /&gt;
You can sometimes isolate a bug with &amp;lt;tt&amp;gt;no-asm&amp;lt;/tt&amp;gt;, and sometimes with &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;-O1&amp;lt;/tt&amp;gt;. Ideally the bug will be present with no optimizations (&amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;), but sometimes it takes some compiler analysis to tickle it (&amp;lt;tt&amp;gt;-O1&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== OpenSSL 1.1.0 ==&lt;br /&gt;
&lt;br /&gt;
===Build the Library===&lt;br /&gt;
&lt;br /&gt;
The first thing you should do after verifying the bug is to create a debug build of the OpenSSL library and attempt to reproduce it. &lt;br /&gt;
&lt;br /&gt;
TODO: provide instrcutions.&lt;br /&gt;
&lt;br /&gt;
===Build the Test===&lt;br /&gt;
&lt;br /&gt;
You typically run &amp;lt;tt&amp;gt;make test&amp;lt;/tt&amp;gt; to validate the library after &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;'ing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ make test&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
make[1]: Entering directory '/home/test_user/openssl-1.1.1d'&lt;br /&gt;
make[1]: Leaving directory '/home/test_user/openssl-1.1.1d'&lt;br /&gt;
make[1]: Entering directory '/home/test_user/openssl-1.1.1d'&lt;br /&gt;
( cd test; \&lt;br /&gt;
  mkdir -p test-runs; \&lt;br /&gt;
  SRCTOP=../. \&lt;br /&gt;
  BLDTOP=../. \&lt;br /&gt;
  RESULT_D=test-runs \&lt;br /&gt;
  PERL=&amp;quot;/usr/bin/perl&amp;quot; \&lt;br /&gt;
  EXE_EXT= \&lt;br /&gt;
  OPENSSL_ENGINES=`cd .././engines 2&amp;gt;/dev/null &amp;amp;&amp;amp; pwd` \&lt;br /&gt;
  OPENSSL_DEBUG_MEMORY=on \&lt;br /&gt;
    /usr/bin/perl .././test/run_tests.pl  )&lt;br /&gt;
../test/recipes/01-test_abort.t .................... ok&lt;br /&gt;
../test/recipes/01-test_sanity.t ................... ok&lt;br /&gt;
...&lt;br /&gt;
../test/recipes/15-test_dh.t ....................... ok&lt;br /&gt;
../test/recipes/15-test_dsa.t ...................... ok&lt;br /&gt;
../test/recipes/15-test_ec.t ....................... Dubious, test returned 1 (wstat 256, 0x100)&lt;br /&gt;
Failed 1/5 subtests &lt;br /&gt;
../test/recipes/15-test_ecdsa.t .................... Dubious, test returned 1 (wstat 256, 0x100)&lt;br /&gt;
Failed 1/1 subtests &lt;br /&gt;
../test/recipes/15-test_ecparam.t .................. Dubious, test returned 2 (wstat 512, 0x200)&lt;br /&gt;
Failed 2/134 subtests &lt;br /&gt;
../test/recipes/15-test_genrsa.t ................... ok&lt;br /&gt;
../test/recipes/15-test_mp_rsa.t ................... ok  &lt;br /&gt;
../test/recipes/15-test_out_option.t ............... ok&lt;br /&gt;
../test/recipes/15-test_rsa.t ...................... ok&lt;br /&gt;
../test/recipes/15-test_rsapss.t ................... ok&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debug the Test ===&lt;br /&gt;
&lt;br /&gt;
You can run a specific test by setting &amp;lt;tt&amp;gt;PERL5LIB&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;TOP&amp;lt;/tt&amp;gt; variables as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# From the root of the OpenSSL directory&lt;br /&gt;
$ PERL5LIB=util/perl TOP=$PWD perl test/recipes/15-test_ec.t&lt;br /&gt;
1..5&lt;br /&gt;
ok 1 - require '/home/test_user/openssl-1.1.1d/test/recipes/tconversion.pl';&lt;br /&gt;
    # Subtest: /home/test_user/openssl-1.1.1d/test/ectest&lt;br /&gt;
    1..11&lt;br /&gt;
crypto/ec/ecp_nistp521.c:144:15: runtime error: load of misaligned address 0x7ffec57b10b7 for type 'limb', which requires 8 byte alignment&lt;br /&gt;
0x7ffec57b10b7: note: pointer points here&lt;br /&gt;
 c2 31 7e 7e f9  9b 42 6a 85 c1 b3 48 33  de a8 ff a2 27 c1 1d fe  28 59 e7 ef 77 5e 4b a1  ba 3d 4d&lt;br /&gt;
             ^ &lt;br /&gt;
/home/test_user/openssl-1.1.1d/util/shlib_wrap.sh /home/test_user/openssl-1.1.1d/test/ectest =&amp;gt; 1&lt;br /&gt;
not ok 2 - running ectest&lt;br /&gt;
#   Failed test 'running ectest'&lt;br /&gt;
#   at test/recipes/15-test_ec.t line 23.&lt;br /&gt;
# Subtest: ec conversions -- private key&lt;br /&gt;
    1..10&lt;br /&gt;
    ok 1 - initializing&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debug an Engine ===&lt;br /&gt;
&lt;br /&gt;
TODO: provide instructions&lt;br /&gt;
&lt;br /&gt;
== OpenSSL 1.0.2 ==&lt;br /&gt;
&lt;br /&gt;
The instructions that follow help determine a failue in OpenSSL 1.0.2 and below. As of January 2020, OpenSSL 1.0.2 is end of life. You should move to OpenSSL 1.1.x as soon as possible.&lt;br /&gt;
&lt;br /&gt;
===Build the Library===&lt;br /&gt;
&lt;br /&gt;
The first thing you should do after verifying the bug is to create a debug build of the OpenSSL library and attempt to reproduce it. Creating a debug build is as easy as using &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; configure argument. In the output below, notice &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; caused the library to reduce optimizations (&amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;) and increase debugging information (&amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt;). However, the debugging information will lack symbolic constants because &amp;lt;tt&amp;gt;-g3&amp;lt;/tt&amp;gt; was not used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config -d&lt;br /&gt;
Operating system: i86pc-whatever-solaris2&lt;br /&gt;
Configuring for solaris64-x86_64-gcc&lt;br /&gt;
...&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-m64 -Wall -DL_ENDIAN -O0 -g -pthread -DFILIO_H  -Wa,--noexecstack&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To ensure most of your preferred flags are used, perform the following. Not all flags will be honored, but its an improvement over &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;-DNDEBUG&amp;lt;/tt&amp;gt; is used to ensure Posix's &amp;lt;tt&amp;gt;assert&amp;lt;/tt&amp;gt; does not crash your program while under the debugger.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config no-asm -DNDEBUG -g3 -O0 -fno-omit-frame-pointer&lt;br /&gt;
Operating system: i86pc-whatever-solaris2&lt;br /&gt;
Configuring for solaris64-x86_64-gcc&lt;br /&gt;
...&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-m64 -Wall -DL_ENDIAN -O3 -pthread -DFILIO_H  -g3 -O0 -fno-omit-frame-pointer&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After configuring, run &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; as usual.&lt;br /&gt;
&lt;br /&gt;
===Build the Test===&lt;br /&gt;
&lt;br /&gt;
You typically run &amp;lt;tt&amp;gt;make test&amp;lt;/tt&amp;gt; to validate the library after &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;'ing. Since you already know there's a problem, you can build the problem test with the following. The command below is an example for tracking down a failure in the HMAC test suite&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ VERBOSE=1 make TESTS=&amp;quot;test_hmac&amp;quot; test&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
( cd test; \&lt;br /&gt;
  SRCTOP=../. \&lt;br /&gt;
  BLDTOP=../. \&lt;br /&gt;
  PERL=&amp;quot;/usr/local/bin/perl&amp;quot; \&lt;br /&gt;
  EXE_EXT= \&lt;br /&gt;
  OPENSSL_ENGINES=.././engines \&lt;br /&gt;
    /usr/local/bin/perl .././test/run_tests.pl test_hmac )&lt;br /&gt;
../test/recipes/05-test_hmac.t .. &lt;br /&gt;
1..1&lt;br /&gt;
test 0 ok&lt;br /&gt;
test 1 ok&lt;br /&gt;
test 2 ok&lt;br /&gt;
test 3 ok&lt;br /&gt;
test 4 ok&lt;br /&gt;
test 5 ok&lt;br /&gt;
test 6 ok&lt;br /&gt;
../util/shlib_wrap.sh ./hmactest =&amp;gt; 0&lt;br /&gt;
ok 1 - running hmactest&lt;br /&gt;
ok&lt;br /&gt;
All tests successful.&lt;br /&gt;
Files=1, Tests=1,  0 wallclock secs ( 0.03 usr  0.01 sys +  0.06 cusr  0.02 csys =  0.12 CPU)&lt;br /&gt;
Result: PASS&lt;br /&gt;
`test' is up to date.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debug the Test ===&lt;br /&gt;
&lt;br /&gt;
The executable for &amp;lt;tt&amp;gt;test_hmac&amp;lt;/tt&amp;gt; is created from the source &amp;lt;tt&amp;gt;05-test_hmac.t&amp;lt;/tt&amp;gt;, and it will be located at &amp;lt;tt&amp;gt;./test/buildtest_hmac&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ file ./test/buildtest_hmac&lt;br /&gt;
./test/buildtest_hmac:  ELF 64-bit LSB executable AMD64 Version 1, dynamically linked, not stripped&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can manually execute the test with the following. Note that &amp;lt;tt&amp;gt;$PWD&amp;lt;/tt&amp;gt; is the root of the OpenSSL distribution, and the libraries are put on path using &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ LD_LIBRARY_PATH=&amp;quot;.:$LD_LIBRARY_PATH&amp;quot; test/hmactest&lt;br /&gt;
^C&lt;br /&gt;
$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can run the test under a debugger with the following. As can be seen, the execution results in a loop between lines 184 and 189.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ LD_LIBRARY_PATH=&amp;quot;.:$LD_LIBRARY_PATH&amp;quot; gdb test/hmactest&lt;br /&gt;
GNU gdb (GDB) 7.6&lt;br /&gt;
...&lt;br /&gt;
Reading symbols from .../openssl/test/hmactest...done.&lt;br /&gt;
&lt;br /&gt;
(gdb) r&lt;br /&gt;
Starting program: /export/home/jwalton/openssl/test/hmactest&lt;br /&gt;
[Thread debugging using libthread_db enabled]&lt;br /&gt;
&lt;br /&gt;
^C&lt;br /&gt;
Program received signal SIGINT, Interrupt.&lt;br /&gt;
OPENSSL_cleanse () at crypto/x86_64cpuid.s:184&lt;br /&gt;
184             testq   $7,%rdi&lt;br /&gt;
&lt;br /&gt;
(gdb) where&lt;br /&gt;
#0  OPENSSL_cleanse () at crypto/x86_64cpuid.s:184&lt;br /&gt;
#1  0xffff80ffba0eabec in hmac_ctx_cleanup (ctx=0x412ac0)&lt;br /&gt;
    at crypto/hmac/hmac.c:144&lt;br /&gt;
#2  0xffff80ffba0eac6f in HMAC_CTX_reset (ctx=0x412ac0)&lt;br /&gt;
    at crypto/hmac/hmac.c:160&lt;br /&gt;
#3  0xffff80ffba0eab68 in HMAC_CTX_new () at crypto/hmac/hmac.c:129&lt;br /&gt;
#4  0xffff80ffba0eae2e in HMAC (evp_md=0xffff80ffba1afec0 &amp;lt;md5_md&amp;gt;, &lt;br /&gt;
    key=0x412700 &amp;lt;test&amp;gt;, key_len=0, &lt;br /&gt;
    d=0x412714 &amp;lt;test+20&amp;gt; &amp;quot;More text test vectors to stuff up EBCDIC machines :-)&amp;quot;, n=54, md=0xffff80ffba1c8100 &amp;lt;m.9561&amp;gt; &amp;quot;&amp;quot;, md_len=0x0)&lt;br /&gt;
    at crypto/hmac/hmac.c:209&lt;br /&gt;
#5  0x0000000000401a65 in main (argc=1, argv=0xffff80ffbffffa28)&lt;br /&gt;
    at test/hmactest.c:105&lt;br /&gt;
&lt;br /&gt;
(gdb) s&lt;br /&gt;
185             jz      .Laligned&lt;br /&gt;
(gdb) &lt;br /&gt;
186             movb    %al,(%rdi)&lt;br /&gt;
(gdb) &lt;br /&gt;
187             leaq    -0(%rsi),%rsi&lt;br /&gt;
(gdb) &lt;br /&gt;
188             leaq    0(%rdi),%rdi&lt;br /&gt;
(gdb) &lt;br /&gt;
189             jmp     .Lot&lt;br /&gt;
(gdb) &lt;br /&gt;
184             testq   $7,%rdi&lt;br /&gt;
(gdb) &lt;br /&gt;
185             jz      .Laligned&lt;br /&gt;
(gdb) &lt;br /&gt;
186             movb    %al,(%rdi)&lt;br /&gt;
(gdb) &lt;br /&gt;
187             leaq    -0(%rsi),%rsi&lt;br /&gt;
(gdb) &lt;br /&gt;
188             leaq    0(%rdi),%rdi&lt;br /&gt;
(gdb) &lt;br /&gt;
189             jmp     .Lot&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debug an Engine ===&lt;br /&gt;
&lt;br /&gt;
If you are testing an OpenSSL engine, then the procedures and paths are slightly different.&lt;br /&gt;
&lt;br /&gt;
You manually build the engine with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cd test&lt;br /&gt;
$ make test/afalgtest&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can run the engine test under a debugger with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ OPENSSL_ENGINES=../engines/afalg gdb ./afalgtest&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Library_Initialization&amp;diff=2902</id>
		<title>Library Initialization</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Library_Initialization&amp;diff=2902"/>
		<updated>2020-01-29T03:50:00Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add section on OpenSSL_config and OPENSSL_init_crypto.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page discusses OpenSSL library initialization when using the &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; components.&lt;br /&gt;
&lt;br /&gt;
There are two ways to initialize the OpenSSL library, and they depend on the version of the library you are using. If you are using OpenSSL 1.0.2 or below, then you would use &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;. If you are using OpenSSL 1.1.0 or above, then the library will initialize itself automatically. Optionally you can explicitly initialise it using &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;OPENSSL_init_crypto&amp;lt;/tt&amp;gt;. A compatibility macro exists in &amp;lt;tt&amp;gt;ssl.h&amp;lt;/tt&amp;gt; that maps &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt;, so you can continue to use &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; if desired. Also see ''[http://mta.openssl.org/pipermail/openssl-dev/2016-February/005491.html SSL_library_init]'' on the OpenSSL-dev mailing list.&lt;br /&gt;
&lt;br /&gt;
The rest of this page discusses initializing the library in 1.0.2. If you are using 1.1.0 or above then you don't need to take any further steps.&lt;br /&gt;
&lt;br /&gt;
If you fail to initialize the library in 1.0.2, then you will experience unexplained errors like &amp;lt;tt&amp;gt;SSL_CTX_new&amp;lt;/tt&amp;gt; returning &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, error messages like &amp;lt;tt&amp;gt;SSL_CTX_new:library has no ciphers&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;alert handshake failure&amp;lt;/tt&amp;gt; with no shared ciphers.&lt;br /&gt;
&lt;br /&gt;
Below is a list of some initialization calls you might encounter in code or documentation. Unfortunately, all the initialization function return a useless values (for example, always 1) or are void functions. There is no way to determine if a failure occurred.&lt;br /&gt;
&lt;br /&gt;
* SSL_library_init&lt;br /&gt;
* OpenSSL_add_ssl_algorithms&lt;br /&gt;
* OpenSSL_add_all_algorithms&lt;br /&gt;
* SSL_load_error_strings&lt;br /&gt;
* ERR_load_crypto_strings&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== libssl Initialization ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt; should be initialized with calls to &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_load_error_strings&amp;lt;/tt&amp;gt;. If your program is multi-threaded, you should install the static locks. If you need (or don't need) configuration from &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt;, then you should call &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;OPENSSL_noconfig&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you are supporting both pre-1.1.0 and post-1.1.0 version of the OpenSSL library and you want to take control of &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt;, then you can perform:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/opensslv.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#if OPENSSL_VERSION_NUMBER &amp;lt; 0x10100000L&lt;br /&gt;
SSL_library_init();&lt;br /&gt;
#else&lt;br /&gt;
OPENSSL_init_ssl(0, NULL);&lt;br /&gt;
#endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you call &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;, the function will also initialize &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; components. There are two corner cases discussed in later sections. The first corner case is static locks, and second is &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;OpenSSL_add_ssl_algorithms&amp;lt;/tt&amp;gt; is a &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; for &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;. You only need to call one or the other. If you want to print error strings using OpenSSL's built in functions, then call &amp;lt;tt&amp;gt;SSL_load_error_strings&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; function loads the algorithms use by &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. Below is an excerpt from &amp;lt;tt&amp;gt;ssl_algs.c&amp;lt;/tt&amp;gt; (with some additional formatting for clarity).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;int SSL_library_init(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
#ifndef OPENSSL_NO_DES&lt;br /&gt;
    EVP_add_cipher(EVP_des_cbc());&lt;br /&gt;
    EVP_add_cipher(EVP_des_ede3_cbc());&lt;br /&gt;
#endif&lt;br /&gt;
#ifndef OPENSSL_NO_IDEA&lt;br /&gt;
    EVP_add_cipher(EVP_idea_cbc());&lt;br /&gt;
#endif&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
#ifndef OPENSSL_NO_COMP&lt;br /&gt;
    (void)SSL_COMP_get_compression_methods();&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    /* initialize cipher/digest methods table */&lt;br /&gt;
    ssl_load_ciphers();&lt;br /&gt;
&lt;br /&gt;
    return(1);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The call to &amp;lt;tt&amp;gt;ssl_load_ciphers&amp;lt;/tt&amp;gt; simply builds a table for use in the library. The following is from &amp;lt;tt&amp;gt;ssl_ciph.c&amp;lt;/tt&amp;gt; (with some additional formatting for clarity).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;void ssl_load_ciphers(void)&lt;br /&gt;
{&lt;br /&gt;
    ssl_cipher_methods[SSL_ENC_DES_IDX] = EVP_get_cipherbyname(SN_des_cbc);&lt;br /&gt;
    ssl_cipher_methods[SSL_ENC_3DES_IDX] = EVP_get_cipherbyname(SN_des_ede3_cbc);&lt;br /&gt;
    ...&lt;br /&gt;
    ssl_digest_methods[SSL_MD_MD5_IDX] = EVP_get_digestbyname(SN_md5);&lt;br /&gt;
    ssl_mac_secret_size[SSL_MD_MD5_IDX] = EVP_MD_size(ssl_digest_methods[SSL_MD_MD5_IDX]);&lt;br /&gt;
    ...&lt;br /&gt;
    ssl_digest_methods[SSL_MD_SHA384_IDX] = EVP_get_digestbyname(SN_sha384);&lt;br /&gt;
    ssl_mac_secret_size[SSL_MD_SHA384_IDX] = EVP_MD_size(ssl_digest_methods[SSL_MD_SHA384_IDX]);&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Library Apps ===&lt;br /&gt;
&lt;br /&gt;
The following examines how the OpenSSL development team uses initialization in the OpenSSL utilities.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s_client&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* OpenSSL_add_ssl_algorithms&lt;br /&gt;
* SSL_load_error_strings&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s_server&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* SSL_load_error_strings();&lt;br /&gt;
* OpenSSL_add_ssl_algorithms();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s_time&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* OpenSSL_add_ssl_algorithms();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;state_machine&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* SSL_library_init();&lt;br /&gt;
* OpenSSL_add_ssl_algorithms();&lt;br /&gt;
* SSL_load_error_strings();&lt;br /&gt;
* ERR_load_crypto_strings();&lt;br /&gt;
&lt;br /&gt;
== libcrypto Initialization ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; should be initialized with calls to &amp;lt;tt&amp;gt;OpenSSL_add_all_algorithms&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ERR_load_crypto_strings&amp;lt;/tt&amp;gt;. If your program is multi-threaded, you should install the static locks. If you need (or don't need) configuration from &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt;, then you should call &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;OPENSSL_noconfig&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;OPENSSL_add_all_algorithms&amp;lt;/tt&amp;gt; function is &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;'d to either &amp;lt;tt&amp;gt;OPENSSL_add_all_algorithms_conf&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;OPENSSL_add_all_algorithms_noconf&amp;lt;/tt&amp;gt; depending upon the value of &amp;lt;tt&amp;gt;OPENSSL_LOAD_CONF&amp;lt;/tt&amp;gt;. A typical installation does ''not'' define &amp;lt;tt&amp;gt;OPENSSL_LOAD_CONF&amp;lt;/tt&amp;gt;, which means &amp;lt;tt&amp;gt;OPENSSL_add_all_algorithms_noconf&amp;lt;/tt&amp;gt; is used. Below is an excerpt from &amp;lt;tt&amp;gt;c_all.c&amp;lt;/tt&amp;gt; (with some additional formatting for clarity).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;void OPENSSL_add_all_algorithms_noconf(void)&lt;br /&gt;
{&lt;br /&gt;
    /*&lt;br /&gt;
     * For the moment OPENSSL_cpuid_setup does something&lt;br /&gt;
     * only on IA-32, but we reserve the option for all&lt;br /&gt;
     * platforms...&lt;br /&gt;
     */&lt;br /&gt;
    OPENSSL_cpuid_setup();&lt;br /&gt;
    OpenSSL_add_all_ciphers();&lt;br /&gt;
    OpenSSL_add_all_digests();&lt;br /&gt;
    ...&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;OpenSSL_add_all_ciphers&amp;lt;/tt&amp;gt; looks a lot like &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; from the &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt; initialization routines (sans the call to &amp;lt;tt&amp;gt;ssl_load_ciphers&amp;lt;/tt&amp;gt;). Below is an excerpt from &amp;lt;tt&amp;gt;c_allc.c&amp;lt;/tt&amp;gt; (with some additional formatting for clarity).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;void OpenSSL_add_all_ciphers(void)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
#ifndef OPENSSL_NO_DES&lt;br /&gt;
    EVP_add_cipher(EVP_des_cfb());&lt;br /&gt;
    EVP_add_cipher(EVP_des_cfb1());&lt;br /&gt;
    EVP_add_cipher(EVP_des_cfb8());&lt;br /&gt;
    EVP_add_cipher(EVP_des_ede_cfb());&lt;br /&gt;
    EVP_add_cipher(EVP_des_ede3_cfb());&lt;br /&gt;
    EVP_add_cipher(EVP_des_ede3_cfb1());&lt;br /&gt;
    EVP_add_cipher(EVP_des_ede3_cfb8());&lt;br /&gt;
    ...&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef OPENSSL_NO_RC4&lt;br /&gt;
    EVP_add_cipher(EVP_rc4());&lt;br /&gt;
    EVP_add_cipher(EVP_rc4_40());&lt;br /&gt;
# ifndef OPENSSL_NO_MD5&lt;br /&gt;
    EVP_add_cipher(EVP_rc4_hmac_md5());&lt;br /&gt;
# endif&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    /* Note: there is no call to ssl_load_ciphers() here */&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, [http://www.openssl.org/docs/crypto/OpenSSL_add_all_algorithms.html &amp;lt;tt&amp;gt;OpenSSL_add_all_algorithms(3)&amp;lt;/tt&amp;gt;] offers the following advice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Calling OpenSSL_add_all_algorithms() links in all algorithms: as a result a statically linked executable can be quite large. If this is important it is possible to just add the required ciphers and digests.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want the small footprint, then call &amp;lt;tt&amp;gt;EVP_add_cipher&amp;lt;/tt&amp;gt; with the ciphers and algorithms you need (and nothing more).&lt;br /&gt;
&lt;br /&gt;
=== Library Apps ===&lt;br /&gt;
&lt;br /&gt;
The following examines how the OpenSSL development team uses initialization in the OpenSSL utilities.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;enc&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* OpenSSL_add_all_algorithms();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;dec&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* OpenSSL_add_all_algorithms();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;pkcs8&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* ERR_load_crypto_strings();&lt;br /&gt;
* OpenSSL_add_all_algorithms();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;cms_sign&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* OpenSSL_add_all_algorithms();&lt;br /&gt;
* ERR_load_crypto_strings();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;cms_ver&amp;lt;/tt&amp;gt; initializes itself with the following calls:&lt;br /&gt;
* OpenSSL_add_all_algorithms();&lt;br /&gt;
* ERR_load_crypto_strings();&lt;br /&gt;
&lt;br /&gt;
== OpenSSL_config ==&lt;br /&gt;
&lt;br /&gt;
If you are supporting early and late versions of the library and need to call &amp;lt;tt&amp;gt;OpenSSL_config&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;OPENSSL_init_crypto&amp;lt;/tt&amp;gt;, then the following is roughly equivalent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/crypto.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#if OPENSSL_VERSION_NUMBER &amp;lt; 0x10001000L&lt;br /&gt;
    OPENSSL_config(NULL);&lt;br /&gt;
#else&lt;br /&gt;
    OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG |&lt;br /&gt;
        OPENSSL_INIT_ADD_ALL_CIPHERS |&lt;br /&gt;
        OPENSSL_INIT_ADD_ALL_DIGESTS);&lt;br /&gt;
#endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ENGINEs and RDRAND ==&lt;br /&gt;
&lt;br /&gt;
A call to &amp;lt;tt&amp;gt;ENGINE_load_builtin_engines&amp;lt;/tt&amp;gt; loads all built-in engines, including those for &amp;lt;tt&amp;gt;AES_NI&amp;lt;/tt&amp;gt; instructions and &amp;lt;tt&amp;gt;RDRAND&amp;lt;/tt&amp;gt;. After the call, OpenSSL will use the engines for AES encryption and random number generation, if available. In this case, &amp;lt;tt&amp;gt;RDRAND&amp;lt;/tt&amp;gt; will be the only source of random numbers.&lt;br /&gt;
&lt;br /&gt;
If you are concerned over possible &amp;lt;tt&amp;gt;RDRAND&amp;lt;/tt&amp;gt; tampering, then you should explicitly call &amp;lt;tt&amp;gt;RAND_set_rand_engine(NULL)&amp;lt;/tt&amp;gt; after loading all engines. If another module in the program happens to call &amp;lt;tt&amp;gt;ENGINE_load_builtin_engines&amp;lt;/tt&amp;gt; again, then you will go back to using &amp;lt;tt&amp;gt;RDRAND&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can also call &amp;lt;tt&amp;gt;ENGINE_unregister_RAND&amp;lt;/tt&amp;gt; followed by &amp;lt;tt&amp;gt;ENGINE_register_all_complete&amp;lt;/tt&amp;gt; to unregister &amp;lt;tt&amp;gt;RDRAND&amp;lt;/tt&amp;gt; as default random number generator implementation.&lt;br /&gt;
&lt;br /&gt;
To avoid accidental use of &amp;lt;tt&amp;gt;RDRAND&amp;lt;/tt&amp;gt;, you can build OpenSSL with &amp;lt;tt&amp;gt;OPENSSL_NO_RDRAND&amp;lt;/tt&amp;gt; defined. This is the preferred method to avoid all use of &amp;lt;tt&amp;gt;RDRAND&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Future version of the library will change the default behavior. That is, in the future, you will have to explicitly call &amp;lt;tt&amp;gt;ENGINE_load_rdrand&amp;lt;/tt&amp;gt; if you want to use &amp;lt;tt&amp;gt;RDRAND&amp;lt;/tt&amp;gt;. The change has been checked in, but its only available through &amp;lt;tt&amp;gt;git&amp;lt;/tt&amp;gt; at the moment.&lt;br /&gt;
&lt;br /&gt;
For the full discussion, see coderman's ''[http://seclists.org/fulldisclosure/2013/Dec/99 RDRAND used directly when default engines loaded in openssl-1.0.1-beta1 through openssl-1.0.1e]''.&lt;br /&gt;
&lt;br /&gt;
== Static Locks ==&lt;br /&gt;
&lt;br /&gt;
If your program is multi-threaded, then you will need to install the static locks. The static locks are used for extensively for &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;, and used in the random number generator for &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt;. The locks should be installed '''''after''''' the calling:&lt;br /&gt;
&lt;br /&gt;
* SSL_library_init&lt;br /&gt;
* OpenSSL_add_ssl_algorithms&lt;br /&gt;
* OpenSSL_add_all_algorithms&lt;br /&gt;
* SSL_load_error_strings&lt;br /&gt;
* ERR_load_crypto_strings&lt;br /&gt;
&lt;br /&gt;
See [http://stackoverflow.com/a/42856544/608639 Multithreaded program using OpenSSL and locks randomly crashes] on Stack Overflow and [http://www.openssl.org/docs/crypto/threads.html threads(3)] for details until the wiki is updated with an example.&lt;br /&gt;
&lt;br /&gt;
== OPENSSL_config ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OPENSSL_noconfig&amp;lt;/tt&amp;gt; loads and unloads &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt;. More correctly, a call to &amp;lt;tt&amp;gt;OPENSSL_config(NULL)&amp;lt;/tt&amp;gt; loads the default configuration in &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OPENSSL_config(filename)&amp;lt;/tt&amp;gt; loads another configuration, and &amp;lt;tt&amp;gt;OPENSSL_noconfig&amp;lt;/tt&amp;gt; unlods a configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; may (or may not) be called depending upon how the OpenSSL library was configured, and it depends on whether &amp;lt;tt&amp;gt;OPENSSL_LOAD_CONF&amp;lt;/tt&amp;gt; was defined. Because &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; may (or may not) be called, your program may or may not need to make the call to &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt;. If, for example, your program is dynamically loading an ENGINE from &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt;, then you will need to ensure a call to &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can check the value of &amp;lt;tt&amp;gt;OPENSSL_LOAD_CONF&amp;lt;/tt&amp;gt; by &amp;lt;tt&amp;gt;cat&amp;lt;/tt&amp;gt;'ing you&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;openssl/opensslconf.h&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;. You can then decide to call &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;OPENSSL_noconfig&amp;lt;/tt&amp;gt; based upon the definition (or lack threof) for &amp;lt;tt&amp;gt;OPENSSL_LOAD_CONF&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /usr/local/ssl/include/openssl/opensslconf.h | grep -i load&lt;br /&gt;
$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here are the rules you should observe. In either case, your program should not depend upon the OpenSSL library and get into a known state.&lt;br /&gt;
&lt;br /&gt;
* If you need something from &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt;, then call &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt;. Don't depend on the library to do it for you.&lt;br /&gt;
* If you don't need something from &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt; (or its mucking up you program), then call &amp;lt;tt&amp;gt;OPENSSL_noconfig&amp;lt;/tt&amp;gt;. The library may have called &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; for you.&lt;br /&gt;
&lt;br /&gt;
== Engines ==&lt;br /&gt;
&lt;br /&gt;
If your application needs to use engines, then it should either call call &amp;lt;tt&amp;gt;ENGINE_load_builtin_engines&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; to load the built-in engines (including dynamically configured engines from &amp;lt;tt&amp;gt;openssl.cnf&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Engines are are automatically loaded (or not loaded) based on the definition of &amp;lt;tt&amp;gt;OPENSSL_LOAD_CONF&amp;lt;/tt&amp;gt; (or lack of definition). You should not depend on library behavior, so you should call &amp;lt;tt&amp;gt;OPENSSL_config&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;ENGINE_load_builtin_engines&amp;lt;/tt&amp;gt; if you need engines.&lt;br /&gt;
&lt;br /&gt;
You can also load a particular engine if you know what you want to use. &amp;lt;tt&amp;gt;eng_all.c&amp;lt;/tt&amp;gt; lists the built-in engines you can load. For example, the following loads the &amp;lt;tt&amp;gt;rdrand&amp;lt;/tt&amp;gt; engine provided for some Intel CPUs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;unsigned long err = 0;&lt;br /&gt;
int rc = 0;&lt;br /&gt;
&lt;br /&gt;
OPENSSL_cpuid_setup();&lt;br /&gt;
ENGINE_load_rdrand();&lt;br /&gt;
&lt;br /&gt;
ENGINE* eng = ENGINE_by_id(&amp;quot;rdrand&amp;quot;);&lt;br /&gt;
if(NULL == eng) handleFailure();&lt;br /&gt;
&lt;br /&gt;
rc = ENGINE_init(eng);&lt;br /&gt;
if(1 != rc) handleFailure();&lt;br /&gt;
&lt;br /&gt;
rc = ENGINE_set_default(eng, ENGINE_METHOD_RAND);&lt;br /&gt;
if(1 != rc) handleFailure();&lt;br /&gt;
&lt;br /&gt;
/* OK to proceed */&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
ENGINE_finish(eng);&lt;br /&gt;
ENGINE_free(eng);&lt;br /&gt;
ENGINE_cleanup();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want an engine to provide all incumbent functionality for the OpenSSL library, then then call &amp;lt;tt&amp;gt;ENGINE_register_complete&amp;lt;/tt&amp;gt; after loading the engine. Incumbent functionality is determined by the manufacturer and includes includes RSA, DSA, DH, ECDH, MD, and RAND operations. See &amp;lt;tt&amp;gt;eng_all.c&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;eng_fat.c&amp;lt;/tt&amp;gt;, and [http://www.openssl.org/docs/crypto/engine.html engine(3)] for details.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;ENGINE* eng = ENGINE_by_id(&amp;quot;XXX&amp;quot;);&lt;br /&gt;
if(!(eng-&amp;gt;flags &amp;amp; ENGINE_FLAGS_NO_REGISTER_ALL))&lt;br /&gt;
    ENGINE_register_complete(eng);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Cleanup ==&lt;br /&gt;
&lt;br /&gt;
How to cleanup the library arises on occasion. Its often in the context of running a program under a memory checker like Valgrind.&lt;br /&gt;
&lt;br /&gt;
OpenSSL does not provide a &amp;lt;tt&amp;gt;SSL_library_uninit&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_library_cleanup&amp;lt;/tt&amp;gt; function (also see [http://rt.openssl.org/Ticket/Display.html?id=3824&amp;amp;user=guest&amp;amp;pass=guest Issue #3824, FEATURE: Please provide a function to unintialize the library]). To cleanup the library the library call the following functions:&lt;br /&gt;
&lt;br /&gt;
* FIPS_mode_set(0);&lt;br /&gt;
* ENGINE_cleanup();&lt;br /&gt;
* CONF_modules_unload(1);&lt;br /&gt;
* EVP_cleanup();&lt;br /&gt;
* CRYPTO_cleanup_all_ex_data();&lt;br /&gt;
* ERR_remove_state();&lt;br /&gt;
* ERR_free_strings();&lt;br /&gt;
&lt;br /&gt;
'''Note:''' ERR_remove_state() was deprecated in OpenSSL 1.0.0 when ERR_remove_thread_state() was introduced. ERR_remove_thread_state() was deprecated in OpenSSL 1.1.0 when the thread handling functionality was entirely rewritten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;CRYPTO_cleanup_all_ex_data&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ERR_remove_state&amp;lt;/tt&amp;gt; should be called on each thread, and not just the main thread.&lt;br /&gt;
&lt;br /&gt;
The above list is a minimum to call. You will still need to cleanup Diffie-Hellman parameters, server contexts, static locks, etc.&lt;br /&gt;
&lt;br /&gt;
After cleanup, you may have some memory leaks due to dynamic allocation of private static variables like &amp;lt;tt&amp;gt;ssl_comp_methods&amp;lt;/tt&amp;gt;. This is a well known issue (see [http://rt.openssl.org/Ticket/Display.html?id=2561&amp;amp;user=guest&amp;amp;pass=guest Issue #2561, Memory leak with SSL built-in compressions]).&lt;br /&gt;
&lt;br /&gt;
==Autoconf==&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses its own configuration system, and does not use Autoconf. However, a number of popular projects use both OpenSSL and Autoconf, and it would be usful to detect either &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. To craft a feature test for OpenSSL that recognizes both &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;, you can use the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if test &amp;quot;$with_openssl&amp;quot; = yes ; then&lt;br /&gt;
  dnl Order matters!&lt;br /&gt;
  if test &amp;quot;$PORTNAME&amp;quot; != &amp;quot;win32&amp;quot;; then&lt;br /&gt;
     AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_CHECK_LIB(ssl, OPENSSL_init_ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_CHECK_LIB(ssl, SSL_library_init, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])])&lt;br /&gt;
  else&lt;br /&gt;
     AC_SEARCH_LIBS(CRYPTO_new_ex_data, eay32 crypto, [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_SEARCH_LIBS(OPENSSL_init_ssl, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_SEARCH_LIBS(SSL_library_init, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])&lt;br /&gt;
  fi&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many thanks to the Postgres folks for donating part of their &amp;lt;tt&amp;gt;configure.in&amp;lt;/tt&amp;gt;. Also see [http://stackoverflow.com/q/39285733 How to tell Autoconf “require symbol A or B” from LIB?] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=FIPS_Library_and_Android&amp;diff=2897</id>
		<title>FIPS Library and Android</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=FIPS_Library_and_Android&amp;diff=2897"/>
		<updated>2019-12-03T07:23:30Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on sourcing.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document will provide instructions for building the OpenSSL FIPS Object Module and OpenSSL FIPS Capable library for Android devices. The FIPS Object Module provides validated cryptography, and the FIPS Capable Library uses the validated cryptography. As an OpenSSL developer, you will use the library the same as in the past – except you must call &amp;lt;tt&amp;gt;FIPS_mode_set&amp;lt;/tt&amp;gt; to enter FIPS mode and engage the validated cryptography. If you are ''not'' doing business in US Federal and ''don't'' need FIPS validated cryptography, then see [[Android]] wiki page.&lt;br /&gt;
&lt;br /&gt;
The FIPS Object Module, &amp;lt;tt&amp;gt;fipscanister.o&amp;lt;/tt&amp;gt;, is a sequestered container of object code and data built from source code. The sources, object code and data are strictly controlled by the OpenSSL FIPS 140-2 Security Policy. No changes can be made to the procedure for building the FIPS Object Module, and no changes can be made to the sources. If you need to make changes to the FIPS Object Module, you will need to engage the OpenSSL Foundation for a separate validation.&lt;br /&gt;
&lt;br /&gt;
The FIPS Capable Library is comprised of &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. They are the same libraries you have been using for years. The FIPS Capable Library is tolerant of changes to procedures and source code. You are allowed to modify them within reason, as long as the changes do not adversely affect the FIPS Object Module.&lt;br /&gt;
&lt;br /&gt;
This guide is intended to be informative and easy to use. In case of discrepancies between this document and the OpenSSL FIPS Security Policy, the Security Policy will prevail. You can download the Security Policy from http://www.openssl.org/docs/fips/.&lt;br /&gt;
&lt;br /&gt;
The script &amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; is sourced. Sourcing ensures the variables set in the script are available to other scripts that are run later in the process. If you shell does not provide the source command, then use &amp;lt;tt&amp;gt;. ./setenv-android.sh&amp;lt;/tt&amp;gt; (note the leading dot).&lt;br /&gt;
&lt;br /&gt;
The instructions that follow depend upon a properly configured Android NDK and SDK. The NDK is used to compile programs and link the OpenSSL library; while SDK tools are used to push programs to a device. Be sure &amp;lt;tt&amp;gt;ANDROID_NDK_ROOT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ANDROID_SDK_ROOT&amp;lt;/tt&amp;gt; are set properly, and the SDK's tools and platform-tools are available.&lt;br /&gt;
&lt;br /&gt;
==Executive Summary==&lt;br /&gt;
&lt;br /&gt;
Use the following commands to build and install the OpenSSL FIPS Object Module and OpenSSL FIPS Capable library. Before running the commands download openssl-1.0.1e.tar.gz, openssl-fips-2.0.5.tar.gz and [[Media:setenv-android.sh|setenv-android.sh]]; place the files in the same directory (the 'root' directory mentioned below); ensure ANDROID_NDK_ROOT is set; and verify setenv-android.sh suites your taste. ANDROID_API and ANDROID_TOOLCHAIN will be set by the setenv-android.sh script. The files can be obtained from  http://www.openssl.org/source/, http://openssl.com/fips/2.0/platforms/android/, and below (see Downloads section).&lt;br /&gt;
&lt;br /&gt;
=== Prepare the OpenSSL Sources ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# From the 'root' directory&lt;br /&gt;
$ rm -rf openssl-fips-2.0.5/&lt;br /&gt;
$ rm -rf openssl-1.0.1e/&lt;br /&gt;
$ tar xzf openssl-fips-2.0.5.tar.gz&lt;br /&gt;
$ tar xzf openssl-1.0.1e.tar.gz&lt;br /&gt;
$ chmod a+x setenv-android.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Build the FIPS Object Module ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# From the 'root' directory&lt;br /&gt;
$ . ./setenv-android.sh&lt;br /&gt;
$ cd openssl-fips-2.0.5/&lt;br /&gt;
&lt;br /&gt;
$ ./config&lt;br /&gt;
$ make&lt;br /&gt;
$ sudo make install&lt;br /&gt;
&lt;br /&gt;
# Execute after install&lt;br /&gt;
$ sudo -E cp $FIPS_SIG /usr/local/ssl/fips-2.0/bin&lt;br /&gt;
$ sudo -E mv /usr/local/ssl/fips-2.0/ /usr/local/ssl/$ANDROID_API&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Build the FIPS Capable Library ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# From the 'root' directory&lt;br /&gt;
$ . ./setenv-android.sh&lt;br /&gt;
$ cd openssl-1.0.1e/&lt;br /&gt;
&lt;br /&gt;
$ perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org&lt;br /&gt;
$ ./config fips shared no-ssl2 no-ssl3 no-comp no-hw no-engine --openssldir=/usr/local/ssl/$ANDROID_API \&lt;br /&gt;
  --with-fipsdir=/usr/local/ssl/$ANDROID_API --with-fipslibdir=/usr/local/ssl/$ANDROID_API/lib/&lt;br /&gt;
&lt;br /&gt;
$ make depend&lt;br /&gt;
$ make all&lt;br /&gt;
$ sudo -E make install CC=$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc RANLIB=$ANDROID_TOOLCHAIN/arm-linux-androideabi-ranlib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OpenSSL FIPS Components ==&lt;br /&gt;
&lt;br /&gt;
While the Executive Summary provided the whirlwind instructions for building and installing the OpenSSL library, this sections provides detailed instructions. There are six steps to building the FIPS Object Module and FIPS Capable Library for use in various projects, and they are listed below. Projects range from simple NDK based command line programs to Android activities using the JNI bridge.&lt;br /&gt;
&lt;br /&gt;
# Acquire the required files&lt;br /&gt;
# Adjust the cross-compilation script&lt;br /&gt;
# Prepare the OpenSSL sources&lt;br /&gt;
# Set the Incore utility PATH&lt;br /&gt;
# Build the FIPS Object Module&lt;br /&gt;
# Build the FIPS Capable Library&lt;br /&gt;
&lt;br /&gt;
=== Acquire the Required Files ===&lt;br /&gt;
&lt;br /&gt;
First, obtain the base files from http://www.openssl.org/source/:&lt;br /&gt;
* openssl-1.0.1e.tar.gz&lt;br /&gt;
* openssl-fips-2.0.5.tar.gz&lt;br /&gt;
&lt;br /&gt;
Next, acquire the auxiliary files which can be obtained from below (see Downloads section) or http://openssl.com/fips/2.0/platforms/android/. You won't need all the files from the location.&lt;br /&gt;
* [[Media:setenv-android.sh|setenv-android.sh]]&lt;br /&gt;
&lt;br /&gt;
In addition to the required and auxiliary files, there are two test programs available. Download them from below (see Downloads section) or http://openssl.com/fips/2.0/platforms/android/.&lt;br /&gt;
* [[Media:Fips_hmac.c|fips_hmac.c]]&lt;br /&gt;
* [[Media:Fips-test.c|fips-test.c]]&lt;br /&gt;
&lt;br /&gt;
openssl-fips-2.0.5.tar.gz includes the FIPS Object Module. openssl-1.0.1e.tar.gz includes the FIPS Capable Library. setenv-android.sh is used to set the cross-compilation environment. fips_hmac.c is used to test the static and dynamic libraries on the device.&lt;br /&gt;
&lt;br /&gt;
After collecting the required files, your working directory will look similar to below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;android-openssl-fips $ ls -l &lt;br /&gt;
-rw-r--r-- 1      2718 Jun 23 17:54 fips_hmac.c &lt;br /&gt;
-rw-r--r-- 1   4459777 Jun 15 03:32 openssl-1.0.1e.tar.gz&lt;br /&gt;
-rw-r--r-- 1   1442754 Jun 23 16:37 openssl-fips-2.0.5.tar.gz&lt;br /&gt;
-rwxr-xr-x 1      6760 Jun 23 01:52 setenv-android.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adjust the Cross-Compile Script ===&lt;br /&gt;
&lt;br /&gt;
setenv-android.sh is used to set the cross-compilation environment. Open the script an ensure the following match your needs. If you are using android-ndk-r8e, android-14, and ANDROID_NDK_ROOT is set, then the script should be ready to use as-is.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;_ANDROID_NDK&amp;lt;/tt&amp;gt; – the version of the NDK. For example, android-ndk-r8e&lt;br /&gt;
* &amp;lt;tt&amp;gt;_ANDROID_ARCH&amp;lt;/tt&amp;gt; – the architecture. For example, arch-arm or arch-x86&lt;br /&gt;
* &amp;lt;tt&amp;gt;_ANDROID_EABI&amp;lt;/tt&amp;gt; – the version of the EABI tools. For example, arm-linux-androideabi-4.6, arm-linux-androideabi-4.8, x86-4.6 or x86-4.8 &lt;br /&gt;
* &amp;lt;tt&amp;gt;_ANDROID_API&amp;lt;/tt&amp;gt; – the API level. For example, android-14 or android-18&lt;br /&gt;
&lt;br /&gt;
You should also set &amp;lt;tt&amp;gt;ANDROID_SDK_ROOT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ANDROID_NDK_ROOT&amp;lt;/tt&amp;gt;. The environmental variables are used internally by the Android platform tools and scripts. For details, see [https://groups.google.com/d/msg/android-ndk/qZjhOaynHXc/2ux2ZZdxy2MJ Recommended NDK Directory?].&lt;br /&gt;
&lt;br /&gt;
Additional environmental variables which are set by &amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; and used by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; include the following. You should not need to change them.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;MACHINE&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;armv7&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;RELEASE&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;2.6.37&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SYSTEM&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;android&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;ARCH&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;arm&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;CROSS_COMPILE&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;arm-linux-androideabi-&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;ANDROID_DEV&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;$ANDROID_NDK_ROOT/platforms/$_ANDROID_API/arch-arm/usr&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;HOSTCC&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Prepare the OpenSSL Sources ===&lt;br /&gt;
&lt;br /&gt;
Remove stale versions of the OpenSSL FIPS Object Module and FIPS Capable library, and then unpack fresh files. Also ensure the script is executable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ rm -rf openssl-fips-2.0.5/&lt;br /&gt;
$ rm -rf openssl-1.0.1e/&lt;br /&gt;
$ tar xzf openssl-fips-2.0.5.tar.gz&lt;br /&gt;
$ tar xzf openssl-1.0.1e.tar.gz&lt;br /&gt;
$ chmod a+x setenv-android.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Set the Incore Utility Path ===&lt;br /&gt;
&lt;br /&gt;
The incore utility is a shell script used by fipsld to embed the FIPS Object Module's expected fingerprint in the OpenSSL shared object or program. The script is located in openssl-fips-2.0.5/util, and you must ensure incore can be found by fipsld.&lt;br /&gt;
&lt;br /&gt;
Since openssl-fips-2.0.5/util is probably not included as one of the directories in the search list specified by the PATH environment variable, the OpenSSL library allows you to specify its path via FIPS_SIG. Export FIPS_SIG as follows by executing find from your working directory. Below, the root directory (PWD) is /home/user/android-openssl-fips/.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export FIPS_SIG=`find $PWD -name incore`&lt;br /&gt;
$ echo $FIPS_SIG&lt;br /&gt;
/home/user/android-openssl-fips/openssl-fips-2.0.5/util/incore&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If incore is already installed in a known location, you can use it from there instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export FIPS_SIG=`find /usr/local/ssl -name incore`&lt;br /&gt;
$ echo $FIPS_SIG&lt;br /&gt;
/usr/local/ssl/android-14/bin/incore&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Build the FIPS Object Module ===&lt;br /&gt;
&lt;br /&gt;
The FIPS Object Module provides the validated cryptography for the OpenSSL library. This section of the document will guide you through the creation of the FIPS Object Module. The Module is governed by the FIPS 140-2 program requirements and you cannot deviate from the OpenSSL FIPS 140-2 Security Policy during any stage during handling, from acquisition, through building, to installation.&lt;br /&gt;
&lt;br /&gt;
The FIPS Object Module build procedures use the cross-compilation tools supplied in the NDK. It does not use Android.mk and friends. A shell script is used to set the environment for the cross-compilation, and you might need to adjust the script to suit your taste.&lt;br /&gt;
&lt;br /&gt;
To compile the FIPS Object Module for the embedded platform, perform the following steps. You cannot specify any arguments to config or make. Note the leading '.' when running the setenv-android.sh script. If you have any errors from the script, then you should fix them before proceeding.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ . ./setenv-android.sh&lt;br /&gt;
$ cd openssl-fips-2.0.5/&lt;br /&gt;
$ ./config&lt;br /&gt;
$ make&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After make completes, verify fipscanister.o was built for the embedded architecture.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ find . -name fipscanister.o&lt;br /&gt;
./fips/fipscanister.o&lt;br /&gt;
$ readelf -h ./fips/fipscanister.o | grep -i 'class\|machine'&lt;br /&gt;
  Class:                   ELF32&lt;br /&gt;
  Machine:                 ARM&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, install the library. You must run make install without arguments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After installing the FIPS Object Module, the four files of interest can be found in the lib/ directory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ls /usr/local/ssl/fips-2.0/lib/ &lt;br /&gt;
fipscanister.o  fipscanister.o.sha1  fips_premain.c  fips_premain.c.sha1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once installed, you are outside the scope of FIPS 140-2 and allowed to move the library as long as it remains protected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo mv /usr/local/ssl/fips-2.0/ /usr/local/ssl/android-14&lt;br /&gt;
$ ls /usr/local/ssl/&lt;br /&gt;
android-14&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The android-14 is the API level you are building for, and is needed if you have multiple OpenSSL libraries installed (for example, you might have macosx, iphoneos, and android-14 in /usr/local/ssl). You can retrieve the API level from ANDROID_API, which was set in the setenv-android.sh script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $ANDROID_API&lt;br /&gt;
android-14&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, copy incore into the installation directory. This will allow you to delete the temporary folders in your working area (openssl-fips-2.0.5 and openssl-1.0.1e) once the libraries are installed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ find . -name incore &lt;br /&gt;
./util/incore &lt;br /&gt;
$ sudo cp ./util/incore /usr/local/ssl/android-14/bin/ &lt;br /&gt;
$ ls /usr/local/ssl/android-14/bin/ &lt;br /&gt;
fipsld  fips_standalone_sha1  incore&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Build the FIPS Capable Library ===&lt;br /&gt;
&lt;br /&gt;
The FIPS Capable Library is a standard OpenSSL distribution that can use the validated cryptography provided by the FIPS Object Module. This section of the document will guide you through the creation of the the FIPS Capable Library. You are allowed to modify the FIPS Capable Library within reason, as long as it does not adversely affect the FIPS Object Module.&lt;br /&gt;
&lt;br /&gt;
The FIPS Capable version of the library can operate with or without FIPS validated cryptography. It handles all the details of operation while in FIPS mode after you successfully call FIPS_mode_set. If you don't call FIPS_mode_set, the library will still operate as expected; but it will not be using validated cryptography.&lt;br /&gt;
Its recommended that you build the shared object since Android will load and link it out of the box. If you build a static library, then you will have to build a wrapper shared object around the static archive.&lt;br /&gt;
&lt;br /&gt;
The FIPS Capable Makefile (and Makefile.org) needs its install rule modified. The install rule includes the all target, which causes items to be built during install. A bug in the process when running as root results in an empty signature for the shared object (the signature is a string of zeros).&lt;br /&gt;
&lt;br /&gt;
To build the FIPS Capable library, you must issue config fips, but other options are up to you. Some suggested options for configure include: shared, no-ssl2, no-ssl3, no-comp, no-hw, and no-engine. shared will build and install both the shared object and static archive. You should specify --openssldir,  --with-fipsdir and --with-fipslibdir to ensure the FIPS Capable build system finds components from the FIPS Object Module.&lt;br /&gt;
&lt;br /&gt;
Begin building the FIPS Capable library by setting the cross-compilation environment. Note the leading '.' when running the setenv-android.sh script. If you have any errors from the script, then you should fix them before proceeding.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ . ./setenv-android.sh&lt;br /&gt;
$ cd openssl-1.0.1e/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, fix the makefile and run configure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org&lt;br /&gt;
$ ./config fips shared no-ssl2 no-ssl3 no-comp no-hw no-engine --openssldir=/usr/local/ssl/android-14/ \&lt;br /&gt;
  --with-fipsdir=/usr/local/ssl/android-14/ --with-fipslibdir=/usr/local/ssl/android-14/lib/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then run make depend and make all:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ make depend&lt;br /&gt;
$ make all&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After make completes, verify libcrypto.a and libssl.a were built for the embedded architecture.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ find . -name libcrypto.a&lt;br /&gt;
./libcrypto.a&lt;br /&gt;
$ readelf -h ./libcrypto.a | grep -i 'class\|machine' | head -2&lt;br /&gt;
  Class:                   ELF32&lt;br /&gt;
  Machine:                 ARM&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, install the library. The makefile's install rule uses both CC and RANLIB, so you will need to fully specify the command variables on the command line (during install, sudo drops the user's path). You must also use sudo's -E option; otherwise ANDROID_TOOLCHAIN will be empty and tools such as arm-linux-androideabi-gcc and  arm-linux-androideabi-ranlib will not be found.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo -E make install CC=$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc RANLIB=$ANDROID_TOOLCHAIN/arm-linux-androideabi-ranlib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing the OpenSSL Libraries ==&lt;br /&gt;
&lt;br /&gt;
Testing the installation consists of building a sample program, installing it with adb, and then running the program using a remote shell. Both the static and dynamic version of the OpenSSL library can be tested using fips_hmac, which is a test program to calculate a hmac over the files given as arguments.&lt;br /&gt;
&lt;br /&gt;
The test program is built in a cross-compilation environment, just like the FIPS Object Module and FIPS Capable library. To begin, set the Android environment and verify ANDROID_SYSROOT. Note the leading '.' when running the setenv-android.sh script. If you have any errors from the script, then you should fix them before proceeding.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ . ./setenv-android.sh&lt;br /&gt;
$ echo $ANDROID_SYSROOT &lt;br /&gt;
/opt/android-ndk-r8e/platforms/android-14/arch-arm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Linking with the Shared Object ===&lt;br /&gt;
&lt;br /&gt;
Linking with the shared object is easiest. That's because the FIPS Capable library build process takes care of a number of items for you, including running fipsld on the shared object. The downside to dynamic linking is you have to push the program and shared object to the device and modify the loader path before executing.&lt;br /&gt;
&lt;br /&gt;
The command below compiles fips_hmac.c using ANDROID_SYSROOT and the shared object (libcrypto.so). ANDROID_SYSROOT specifies the location of Android's headers and libraries, and is set using setenv-android.sh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ arm-linux-androideabi-gcc --sysroot=&amp;quot;$ANDROID_SYSROOT&amp;quot; -I/usr/local/ssl/android-14/include \&lt;br /&gt;
   fips_hmac.c -o fips_hmac.exe /usr/local/ssl/android-14/lib/libcrypto.so&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There's no need to run fipsld on a program which dynamically links to the OpenSSL library.&lt;br /&gt;
&lt;br /&gt;
Once the program is built, push it to the device and execute it. The hashes produced by the test program will vary with the files being digested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Copy the program and shared library to the Android device &lt;br /&gt;
$ adb push fips_hmac.exe /data/local/tmp/ &lt;br /&gt;
303 KB/s (18548 bytes in 0.059s) &lt;br /&gt;
$ adb push libcrypto.so.1.0.0 /data/local/tmp &lt;br /&gt;
1106 KB/s (2154620 bytes in 1.900s)&lt;br /&gt;
&lt;br /&gt;
# Execute the program on the Android device &lt;br /&gt;
$ adb shell &lt;br /&gt;
shell@android: $ cd /data/local/tmp &lt;br /&gt;
shell@android: $ LD_LIBRARY_PATH=./; ./fips_hmac.exe -v fips_hmac.exe &lt;br /&gt;
FIPS mode enabled&lt;br /&gt;
f178788e8a439dbaaa760ef774e8d92e01d2440e&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Linking with the Static Archive ===&lt;br /&gt;
&lt;br /&gt;
Linking against the static library is more challenging. That's because you have to set two variables – CC and FIPSLD_CC and compile with the modified CC. They must be exported because fipsld uses them in child shells. Behind the scenes, fipsld will compile and link fips_premain.c, modify the libcrypto archive, assemble the final program, and embed the fingerprint.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=`find /usr/local/ssl/$ANDROID_API -name fipsld`&lt;br /&gt;
$ echo $CC &lt;br /&gt;
/usr/local/ssl/android-14/bin/fipsld&lt;br /&gt;
$ export FIPSLD_CC=&amp;quot;$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc&amp;quot; &lt;br /&gt;
$ echo $FIPSLD_CC &lt;br /&gt;
/opt/android-ndk-r8e/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, compile and link as normal using CC. The command below compiles fips_hmac.c using ANDROID_SYSROOT and the static archive (libcrypto.a). ANDROID_SYSROOT specifies the location of Android's headers and libraries, and is set using setenv-android.sh.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ $CC --sysroot=&amp;quot;$ANDROID_SYSROOT&amp;quot; -I/usr/local/ssl/android-14/include fips-test.c \&lt;br /&gt;
    -o fips-test.exe /usr/local/ssl/android-14/lib/libcrypto.a&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can use fipsld to create an object file rather than compile and link. In this case, fipsld will simply pass all arguments to arm-linux-androideabi-gcc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ $CC --sysroot=&amp;quot;$ANDROID_SYSROOT&amp;quot; -I/usr/local/ssl/android-14/include -c fips-test.c&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the program is built, push it to the device and execute it. &lt;br /&gt;
The hashes produced by the test program will vary with the files being digested.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Copy the program to the Android device&lt;br /&gt;
$ adb push fips_hmac.exe /data/local/tmp &lt;br /&gt;
1099 KB/s (1462276 bytes in 1.298s)&lt;br /&gt;
&lt;br /&gt;
# Execute the program on the Android device&lt;br /&gt;
$ adb shell &lt;br /&gt;
shell@android: $ cd /data/local/tmp                                           &lt;br /&gt;
shell@android: $ fips_hmac.exe -v fips_hmac.exe&lt;br /&gt;
FIPS mode enabled&lt;br /&gt;
a7518364fbba32cca0df974ee646e8a13833eb3d&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Wrapper Shared Objects ==&lt;br /&gt;
&lt;br /&gt;
Using OpenSSL on Android often involves JNI and the platform's version of OpenSSL or BoringSSL. The platform likely loaded the system's version of &amp;lt;tt&amp;gt;libssl.so&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libcrypto.so&amp;lt;/tt&amp;gt; at boot during Zygote initialization. Due to issues with the loader and symbol resolution, customary &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; tricks do not work for most applications. And changing the build to output different library names, like &amp;lt;tt&amp;gt;libmyssl.so&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libmycrypto.so&amp;lt;/tt&amp;gt;, to avoid clashes does not work either.&lt;br /&gt;
&lt;br /&gt;
The solution to the namespace and symbol resolution problems is to wrap the '''''static''''' version of the OpenSSL library in a separate '''''dynamic''''' library or shared object provided by you. To do so, write a small C wrapper library with references to functions you need from the OpenSSL library. You don't need to wrap all the functions.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;tt&amp;gt;wrapper.c&amp;lt;/tt&amp;gt; might look as follows (also see GCC's [http://gcc.gnu.org/wiki/Visibility Visibility page]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#if __GNUC__ &amp;gt;= 4&lt;br /&gt;
    #define DLL_PUBLIC __attribute__ ((visibility (&amp;quot;default&amp;quot;)))&lt;br /&gt;
    #define DLL_LOCAL  __attribute__ ((visibility (&amp;quot;hidden&amp;quot;)))&lt;br /&gt;
#else&lt;br /&gt;
    #define DLL_PUBLIC&lt;br /&gt;
    #define DLL_LOCAL&lt;br /&gt;
#endif&lt;br /&gt;
    &lt;br /&gt;
DLL_PUBLIC void My_OpenSSL_add_all_algorithms() {&lt;br /&gt;
   &lt;br /&gt;
    return (void)OpenSSL_add_all_algorithms();&lt;br /&gt;
}&lt;br /&gt;
    &lt;br /&gt;
DLL_PUBLIC void My_SSL_load_error_strings() {&lt;br /&gt;
&lt;br /&gt;
    return (void)SSL_load_error_strings();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, compile the source file into a shared object. A typical command line might look as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export OPENSSL_ANDROID = /usr/local/ssl/android-14&lt;br /&gt;
$ $(CC) wrapper.c -fPIC -shared -I$(OPENSSL_ANDROID)/include -fvisibility=hidden -Wl,--exclude-libs,ALL \&lt;br /&gt;
-Wl,-Bstatic -lcrypto -lssl -L$(OPENSSL_ANDROID)/lib -o wrapper.so -Wl,-Bdynamic&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-fvisibility=hidden&amp;lt;/tt&amp;gt; works as you expect, and &amp;lt;tt&amp;gt;-Wl,--exclude-libs,ALL&amp;lt;/tt&amp;gt; means your library does not re-export other linked library symbols. Only the functions marked with &amp;lt;tt&amp;gt;DLL_PUBLIC&amp;lt;/tt&amp;gt; will be exported and callable through JNI. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;-Wl,-Bstatic&amp;lt;/tt&amp;gt; tells the linker to use the static version of the OpenSSL library for the Library. After it and the &amp;lt;tt&amp;gt;-Wl,-Bdynamic&amp;lt;/tt&amp;gt; tells the linker to use dynamic linking for anything else it might need, like &amp;lt;tt&amp;gt;libc&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Then use your shared object in place of OpenSSL.&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous ==&lt;br /&gt;
&lt;br /&gt;
The following lists some miscellaneous items we are aware. &lt;br /&gt;
&lt;br /&gt;
=== FIPS Object Module ===&lt;br /&gt;
&lt;br /&gt;
Once the FIPS Object Module and FIPS Capable Library are installed, you can safely delete the source directories. The headers, libraries and programs (such as fipsld and incore) are located in sub-directories of &amp;lt;tt&amp;gt;/usr/local/ssl/&amp;lt;platform&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you don't care about FIPS 140-2 and just want to build the library for Android, then see [[Android|OpenSSL and Android]].&lt;br /&gt;
&lt;br /&gt;
=== Position Independent Code ===&lt;br /&gt;
&lt;br /&gt;
The NDK supplies headers for each major platform - for example, API 18, API 14, API 9, API 8, and API 5. If you are building for Android 4.2 (API 17), Android 4.1 (API 16) and Android 4.0 (API 14), then you would use the NDK's API 14 (android-14 platform).&lt;br /&gt;
&lt;br /&gt;
Specify the full library name when calling Java's System.load. That is, call System.load(“libcrypto.so.1.0.0”). Also note that some Android routines expect the prefix of “lib” and suffix of “so”, so you might have to rename the library.&lt;br /&gt;
&lt;br /&gt;
Some versions of the Android Java system loader will load the system's version of the OpenSSL library, even though you built and included a copy with your application. In this case, you might need to write a wrapper shared object and link to the static version of the OpenSSL library. See, for example, ''[https://groups.google.com/forum/#!topic/android-ndk/rAf5tt4UEug &amp;quot;Unable to find native library&amp;quot; error in Native Activity app]''.&lt;br /&gt;
&lt;br /&gt;
If you compile with -fPIE and -pie, then you will core dump unless using Android 4.1 and above. Logcat shows the linker (/system/bin/linker) is the problem.&lt;br /&gt;
&amp;lt;pre&amp;gt;shell@android: $ ./fips_hmac.exe -v fips_hmac.exe&lt;br /&gt;
[2] + Stopped (signal)     ./fips_hmac.exe -v fips_hmac.exe&lt;br /&gt;
[1] - Segmentation fault   ./fips_hmac.exe -v fips_hmac.exe&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When building the OpenSSL library for Android, take care to specify &amp;lt;tt&amp;gt;-mfloat-abi=softfp&amp;lt;/tt&amp;gt;. If you specify &amp;lt;tt&amp;gt;-mfloat-abi=hard&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;-mhard-float&amp;lt;/tt&amp;gt; (even if the hardware support a floating point unit), then the entropy estimate passed through the Java VM to &amp;lt;tt&amp;gt;RAND_add&amp;lt;/tt&amp;gt; will always be 0.0f. See [https://groups.google.com/d/msg/android-ndk/NbUq9FDDZOo/TJJsAS6nM7wJ Hard-float and JNI] for details.&lt;br /&gt;
&lt;br /&gt;
=== Static Library Linking ===&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;-Bstatic&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-Bshared&amp;lt;/tt&amp;gt; can cause link problems on occasion. For example, see [http://stackoverflow.com/questions/22667953/error-when-trying-to-compile-wrapper-for-openssl-library-libcrypto-a Android: error when trying to compile wrapper for openssl library libcrypto.a]. To avoid the problem with the linker, specify the full path to the static archive (for example, &amp;lt;tt&amp;gt;/usr/local/ssl/android-14/lib/libcrypto.a&amp;lt;/tt&amp;gt;). If you suspect the wrong OpenSSL library is being linked, then use the fully qualified archive path.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
[[Media:OpenSSL_FIPS_Library_and_Android_Guide.pdf|OpenSSL FIPS Library and Android Guide]] - this page as a PDF document.&lt;br /&gt;
&lt;br /&gt;
[[Media:OpenSSL-FIPS-Android.tar.gz|OpenSSL-FIPS-Android.tar.gz]] - Roll-up of the files provided on this page.&lt;br /&gt;
&lt;br /&gt;
[[Media:setenv-android.sh|setenv-android.sh]] - script to set Android cross-compile environment.&lt;br /&gt;
&lt;br /&gt;
[[Media:Fips_hmac.c|fips_hmac.c]] - test program to mac files given as program arguments.&lt;br /&gt;
&lt;br /&gt;
[[Media:Fips-test.c|fips-test.c]] - test program to dump critical FIPS parameters.&lt;br /&gt;
&lt;br /&gt;
[[Category:FIPS 140]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Android&amp;diff=2896</id>
		<title>Android</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Android&amp;diff=2896"/>
		<updated>2019-12-03T07:22:45Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add info on sourcing.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document will provide instructions for building the OpenSSL library for Android devices. If you need the FIPS Validated Object Module and the FIPS Capable Library, see [[FIPS Library and Android]].&lt;br /&gt;
&lt;br /&gt;
The script &amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; is sourced. Sourcing ensures the variables set in the script are available to other scripts that are run later in the process. If you shell does not provide the source command, then use &amp;lt;tt&amp;gt;. ./setenv-android.sh&amp;lt;/tt&amp;gt; (note the leading dot).&lt;br /&gt;
&lt;br /&gt;
''NOTE'': The instructions on this page are for older versions of OpenSSL (they should work for OpenSSL 1.0.2). For OpenSSL 1.1.1 see the INSTALL and NOTES.ANDROID files in the source distribution.&lt;br /&gt;
&lt;br /&gt;
==Executive Summary==&lt;br /&gt;
&lt;br /&gt;
Use the following commands to build and install the OpenSSL library for Android. Before running the commands download openssl-1.0.1g.tar.gz and [[Media:setenv-android.sh|setenv-android.sh]]; place the files in the same directory (the 'root' directory mentioned below); ensure &amp;lt;tt&amp;gt;ANDROID_NDK_ROOT&amp;lt;/tt&amp;gt; is set; and verify setenv-android.sh suites your taste. &amp;lt;tt&amp;gt;ANDROID_API&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ANDROID_TOOLCHAIN&amp;lt;/tt&amp;gt; will be set by the &amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; script. The files can be obtained from http://www.openssl.org/source/, http://openssl.com/fips/2.0/platforms/android/, and below (see Downloads section).&lt;br /&gt;
&lt;br /&gt;
=== Prepare the OpenSSL Sources ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# From the 'root' directory&lt;br /&gt;
$ rm -rf openssl-1.0.1g/&lt;br /&gt;
$ tar xzf openssl-1.0.1g.tar.gz&lt;br /&gt;
$ chmod a+x setenv-android.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Build the OpenSSL Library ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# From the 'root' directory&lt;br /&gt;
$ source ./setenv-android.sh&lt;br /&gt;
$ cd openssl-1.0.1g/&lt;br /&gt;
&lt;br /&gt;
# Perl is optional, and may fail in OpenSSL 1.1.0&lt;br /&gt;
$ perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org&lt;br /&gt;
&lt;br /&gt;
# Tune to suit your taste, visit http://wiki.openssl.org/index.php/Compilation_and_Installation&lt;br /&gt;
$ ./config shared no-ssl2 no-ssl3 no-comp no-hw no-engine \&lt;br /&gt;
     --openssldir=/usr/local/ssl/$ANDROID_API --prefix=/usr/local/ssl/$ANDROID_API&lt;br /&gt;
&lt;br /&gt;
$ make depend&lt;br /&gt;
$ make all&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Install the OpenSSL Library ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# The -E is important. Root needs some of the user's environment&lt;br /&gt;
$ sudo -E make install CC=$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc RANLIB=$ANDROID_TOOLCHAIN/arm-linux-androideabi-ranlib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Compile and Link against the Library ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;arm-linux-androideabi-gcc -I /usr/local/ssl/include my_prog.c -o my_prog.exe -L /usr/local/ssl/lib -lssl -lcrypto&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OpenSSL Library ==&lt;br /&gt;
&lt;br /&gt;
While the Executive Summary provided the whirlwind instructions for building and installing the OpenSSL library, this sections provides detailed instructions. There are six steps to building the OpenSSL Library for use in various projects, and they are listed below. Projects range from simple NDK based command line programs to Android activities using the JNI bridge.&lt;br /&gt;
&lt;br /&gt;
# Acquire the required files&lt;br /&gt;
# Adjust the cross-compilation script&lt;br /&gt;
# Prepare the OpenSSL sources&lt;br /&gt;
# Build the OpenSSL Library&lt;br /&gt;
# Install the OpenSSL Library&lt;br /&gt;
&lt;br /&gt;
=== Acquire the Required Files ===&lt;br /&gt;
&lt;br /&gt;
First, obtain the base files from http://www.openssl.org/source/:&lt;br /&gt;
* openssl-1.0.1g.tar.gz&lt;br /&gt;
&lt;br /&gt;
Next, acquire the auxiliary files which can be obtained from below (see Downloads section) or http://openssl.com/fips/2.0/platforms/android/. You won't need all the files from the location.&lt;br /&gt;
* [[Media:setenv-android.sh|setenv-android.sh]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;openssl-1.0.1g.tar.gz&amp;lt;/tt&amp;gt; is the OpenSSL Library. &amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; is used to set the cross-compilation environment.&lt;br /&gt;
&lt;br /&gt;
After collecting the required files, your working directory will look similar to below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;android-openssl $ ls -l &lt;br /&gt;
-rw-r--r-- 1   4459777 Jun 15 03:32 openssl-1.0.1g.tar.gz&lt;br /&gt;
-rwxr-xr-x 1      6760 Jun 23 01:52 setenv-android.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adjust the Cross-Compile Script ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; is used to set the cross-compilation environment. Open the script an ensure the following match your needs. If you are using android-ndk-r8e, android-14, and &amp;lt;tt&amp;gt;ANDROID_NDK_ROOT&amp;lt;/tt&amp;gt; is set, then the script should be ready to use as-is.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;_ANDROID_NDK&amp;lt;/tt&amp;gt; – the version of the NDK. For example, android-ndk-r8e&lt;br /&gt;
* &amp;lt;tt&amp;gt;_ANDROID_ARCH&amp;lt;/tt&amp;gt; – the architecture. For example, arch-arm or arch-x86&lt;br /&gt;
* &amp;lt;tt&amp;gt;_ANDROID_EABI&amp;lt;/tt&amp;gt; – the version of the EABI tools. For example, arm-linux-androideabi-4.6, arm-linux-androideabi-4.8, x86-4.6 or x86-4.8 &lt;br /&gt;
* &amp;lt;tt&amp;gt;_ANDROID_API&amp;lt;/tt&amp;gt; – the API level. For example, android-14 or android-18&lt;br /&gt;
&lt;br /&gt;
You should also set &amp;lt;tt&amp;gt;ANDROID_SDK_ROOT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ANDROID_NDK_ROOT&amp;lt;/tt&amp;gt;. The environmental variables are used internally by the Android platform tools and scripts. For details, see [https://groups.google.com/d/msg/android-ndk/qZjhOaynHXc/2ux2ZZdxy2MJ Recommended NDK Directory?].&lt;br /&gt;
&lt;br /&gt;
Additional environmental variables which are set by &amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; and used by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; include the following. You should not need to change them.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;MACHINE&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;armv7&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;RELEASE&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;2.6.37&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;SYSTEM&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;android&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;ARCH&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;arm&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;CROSS_COMPILE&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;arm-linux-androideabi-&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;ANDROID_DEV&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;$ANDROID_NDK_ROOT/platforms/$_ANDROID_API/arch-arm/usr&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;HOSTCC&amp;lt;/tt&amp;gt; – set to &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Prepare the OpenSSL Sources ===&lt;br /&gt;
&lt;br /&gt;
Remove stale versions of the OpenSSL Library, and then unpack fresh files. Also ensure the script is executable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ rm -rf openssl-1.0.1g/&lt;br /&gt;
$ tar xzf openssl-1.0.1g.tar.gz&lt;br /&gt;
$ chmod a+x setenv-android.sh&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Build the OpenSSL Library ===&lt;br /&gt;
&lt;br /&gt;
This section of the document will guide you through the creation of the the OpenSSL Library. The OpenSSL Library (and Makefile.org) needs its install rule modified. The install rule includes the all target, which causes items to be built during install. A bug in the process when running as root results in an empty signature for the shared object (the signature is a string of zeros).&lt;br /&gt;
&lt;br /&gt;
To build the OpenSSL Library, you must issue &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, but other options are up to you. Some suggested options for configure include: shared, no-ssl2, no-ssl3, no-comp, no-hw, and no-engine. &amp;lt;tt&amp;gt;shared&amp;lt;/tt&amp;gt; will build and install both the shared object and static archive. You should specify --openssldir to ensure the build system installs the android version of the library in a distinct location (other than &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Begin building the OpenSSL library by setting the cross-compilation environment. Note the leading '.' when running the &amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; script. If you have any errors from the script, then you should fix them before proceeding.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ source ./setenv-android.sh&lt;br /&gt;
$ cd openssl-1.0.1g/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you receive a meesage &amp;quot;&amp;lt;tt&amp;gt;Error: FIPS_SIG does not specify incore module, please edit this script&amp;lt;/tt&amp;gt;, then its safe to ignore it. &amp;lt;tt&amp;gt;setenv-android.sh&amp;lt;/tt&amp;gt; is used to build both the FIPS Capable OpenSSL library and the non-FIPS version of the library. &amp;lt;tt&amp;gt;FIPS_SIG&amp;lt;/tt&amp;gt; is '''not''' needed in this configuration.&lt;br /&gt;
&lt;br /&gt;
Next, fix the makefile and run configure. A user on Stack Overflow reports this [http://stackoverflow.com/q/39640180/608639 fails under OpenSSL 1.1.0]. If so skip it because its not essential to the cross-compile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org&lt;br /&gt;
$ ./config shared no-ssl2 no-ssl3 no-comp no-hw no-engine --openssldir=/usr/local/ssl/android-14/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then run make depend and make all:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ make depend&lt;br /&gt;
$ make all&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After make completes, verify libcrypto.a and libssl.a were built for the embedded architecture.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ find . -name libcrypto.a&lt;br /&gt;
./libcrypto.a&lt;br /&gt;
$ readelf -h ./libcrypto.a | grep -i 'class\|machine' | head -2&lt;br /&gt;
  Class:                   ELF32&lt;br /&gt;
  Machine:                 ARM&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Install the OpenSSL Library ===&lt;br /&gt;
&lt;br /&gt;
Finally, install the library. The makefile's install rule uses both CC and RANLIB, so you will need to fully specify the command variables on the command line (during install, sudo drops the user's path). You must also use sudo's -E option; otherwise ANDROID_TOOLCHAIN will be empty and tools such as arm-linux-androideabi-gcc and arm-linux-androideabi-ranlib will not be found.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo -E make install CC=$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc RANLIB=$ANDROID_TOOLCHAIN/arm-linux-androideabi-ranlib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Compile and Link against the Library ===&lt;br /&gt;
&lt;br /&gt;
[[#Install_the_OpenSSL_Library_2|Install the OpenSSL Library]] placed the cross-compiled library in &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt;. To link against it, you must perform the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;arm-linux-androideabi-gcc -I /usr/local/ssl/include my_prog.c -o my_prog.exe -L /usr/local/ssl/lib -lssl -lcrypto&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above only tells you how to specify the OpenSSL library. You will still need to include system headers and libraries, or use &amp;lt;tt&amp;gt;--sysroot&amp;lt;/tt&amp;gt; to supply the information.&lt;br /&gt;
&lt;br /&gt;
== Testing the OpenSSL Library ==&lt;br /&gt;
&lt;br /&gt;
Testing the installation consists of building a sample program, installing it with adb, and then running the program using a remote shell. Both the static and dynamic version of the OpenSSL library can be tested. Instructions for testing the OpenSSL library are given at [[FIPS Library and Android]]. The same basic steps apply.&lt;br /&gt;
&lt;br /&gt;
== Wrapper Shared Objects ==&lt;br /&gt;
&lt;br /&gt;
Using OpenSSL on Android often involves JNI and the platform's version of OpenSSL or BoringSSL. The platform likely loaded the system's version of &amp;lt;tt&amp;gt;libssl.so&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libcrypto.so&amp;lt;/tt&amp;gt; at boot during Zygote initialization. Due to issues with the loader and symbol resolution, customary &amp;lt;tt&amp;gt;LD_LIBRARY_PATH&amp;lt;/tt&amp;gt; tricks do not work for most applications. And changing the build to output different library names, like &amp;lt;tt&amp;gt;libmyssl.so&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libmycrypto.so&amp;lt;/tt&amp;gt;, to avoid clashes does not work either.&lt;br /&gt;
&lt;br /&gt;
The solution to the namespace and symbol resolution problems is to wrap the '''''static''''' version of the OpenSSL library in a separate '''''dynamic''''' library or shared object provided by you. To do so, write a small C wrapper library with references to functions you need from the OpenSSL library. You don't need to wrap all the functions.&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;tt&amp;gt;wrapper.c&amp;lt;/tt&amp;gt; might look as follows (also see GCC's [http://gcc.gnu.org/wiki/Visibility Visibility page]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#if __GNUC__ &amp;gt;= 4&lt;br /&gt;
    #define DLL_PUBLIC __attribute__ ((visibility (&amp;quot;default&amp;quot;)))&lt;br /&gt;
    #define DLL_LOCAL  __attribute__ ((visibility (&amp;quot;hidden&amp;quot;)))&lt;br /&gt;
#else&lt;br /&gt;
    #define DLL_PUBLIC&lt;br /&gt;
    #define DLL_LOCAL&lt;br /&gt;
#endif&lt;br /&gt;
    &lt;br /&gt;
DLL_PUBLIC void My_OpenSSL_add_all_algorithms() {&lt;br /&gt;
   &lt;br /&gt;
    return (void)OpenSSL_add_all_algorithms();&lt;br /&gt;
}&lt;br /&gt;
    &lt;br /&gt;
DLL_PUBLIC void My_SSL_load_error_strings() {&lt;br /&gt;
&lt;br /&gt;
    return (void)SSL_load_error_strings();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, compile the source file into a shared object. A typical command line might look as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export OPENSSL_ANDROID = /usr/local/ssl/android-14&lt;br /&gt;
$ $(CC) wrapper.c -fPIC -shared -I$(OPENSSL_ANDROID)/include -fvisibility=hidden -Wl,--exclude-libs,ALL \&lt;br /&gt;
-Wl,-Bstatic -lcrypto -lssl -L$(OPENSSL_ANDROID)/lib -o wrapper.so -Wl,-Bdynamic&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-fvisibility=hidden&amp;lt;/tt&amp;gt; works as you expect, and &amp;lt;tt&amp;gt;-Wl,--exclude-libs,ALL&amp;lt;/tt&amp;gt; means your library does not re-export other linked library symbols. Only the functions marked with &amp;lt;tt&amp;gt;DLL_PUBLIC&amp;lt;/tt&amp;gt; will be exported and callable through JNI. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;-Wl,-Bstatic&amp;lt;/tt&amp;gt; tells the linker to use the static version of the OpenSSL library for the Library. After it and the &amp;lt;tt&amp;gt;-Wl,-Bdynamic&amp;lt;/tt&amp;gt; tells the linker to use dynamic linking for anything else it might need, like &amp;lt;tt&amp;gt;libc&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Then use your shared object in place of OpenSSL.&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous ==&lt;br /&gt;
&lt;br /&gt;
The following lists some miscellaneous items we are aware.&lt;br /&gt;
&lt;br /&gt;
=== Position Independent Code ===&lt;br /&gt;
&lt;br /&gt;
The NDK supplies headers for each major platform - for example, API 18, API 14, API 9, API 8, and API 5. If you are building for Android 4.2 (API 17), Android 4.1 (API 16) and Android 4.0 (API 14), then you would use the NDK's API 14 (android-14 platform).&lt;br /&gt;
&lt;br /&gt;
Specify the full library name when calling Java's System.load. That is, call System.load(“libcrypto.so.1.0.0”). Also note that some Android routines expect the prefix of “lib” and suffix of “so”, so you might have to rename the library.&lt;br /&gt;
&lt;br /&gt;
Some versions of the Android Java system loader will load the system's version of the OpenSSL library, even though you built and included a copy with your application. In this case, you might need to write a wrapper shared object and link to the static version of the OpenSSL library. See, for example, ''[https://groups.google.com/forum/#!topic/android-ndk/rAf5tt4UEug &amp;quot;Unable to find native library&amp;quot; error in Native Activity app]''.&lt;br /&gt;
&lt;br /&gt;
If you compile with -fPIE and -pie, then you will core dump unless using Android 4.1 and above. Logcat shows the linker (/system/bin/linker) is the problem.&lt;br /&gt;
&amp;lt;pre&amp;gt;shell@android: $ ./fips_hmac.exe -v fips_hmac.exe&lt;br /&gt;
[2] + Stopped (signal)     ./fips_hmac.exe -v fips_hmac.exe&lt;br /&gt;
[1] - Segmentation fault   ./fips_hmac.exe -v fips_hmac.exe&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When building the OpenSSL library for Android, take care to specify &amp;lt;tt&amp;gt;-mfloat-abi=softfp&amp;lt;/tt&amp;gt;. If you specify &amp;lt;tt&amp;gt;-mfloat-abi=hard&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;-mhard-float&amp;lt;/tt&amp;gt; (even if the hardware support a floating point unit), then the entropy estimate passed through the Java VM to &amp;lt;tt&amp;gt;RAND_add&amp;lt;/tt&amp;gt; will always be 0.0f. See [https://groups.google.com/d/msg/android-ndk/NbUq9FDDZOo/TJJsAS6nM7wJ Hard-float and JNI] for details.&lt;br /&gt;
&lt;br /&gt;
=== Static Library Linking ===&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;-Bstatic&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-Bshared&amp;lt;/tt&amp;gt; can cause link problems on occasion. For example, see [http://stackoverflow.com/questions/22667953/error-when-trying-to-compile-wrapper-for-openssl-library-libcrypto-a Android: error when trying to compile wrapper for openssl library libcrypto.a]. To avoid the problem with the linker, specify the full path to the static archive (for example, &amp;lt;tt&amp;gt;/usr/local/ssl/android-14/lib/libcrypto.a&amp;lt;/tt&amp;gt;). If you suspect the wrong OpenSSL library is being linked, then use the fully qualified archive path.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
[[Media:setenv-android.sh|setenv-android.sh]] - script to set Android cross-compile environment.&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Compilation_and_Installation&amp;diff=2891</id>
		<title>Talk:Compilation and Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Compilation_and_Installation&amp;diff=2891"/>
		<updated>2019-10-04T23:31:54Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Created page with &amp;quot;== Page has grown too large ==  Hi Everyone. I think this page has grown too large and should be separated into separate pages. It has become messy and hard to organize the in...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Page has grown too large ==&lt;br /&gt;
&lt;br /&gt;
Hi Everyone. I think this page has grown too large and should be separated into separate pages. It has become messy and hard to organize the information.&lt;br /&gt;
&lt;br /&gt;
Painting with a broad brush, leave &amp;quot;Compilation and Installation&amp;quot; as the main landing page. Always refer to it from external places, like Stack Overflow. At &amp;quot;Compilation and Installation&amp;quot; include the basic information, like intro discussion of various platforms and the Unix/Linux options. Then, create separate subpages for specific platforms, like Linux, OS X, Windows, Windows CE, etc. &amp;quot;Compilation and Installation&amp;quot; provides a link to each subpage.&lt;br /&gt;
&lt;br /&gt;
Does anyone have any thoughts?&lt;br /&gt;
&lt;br /&gt;
[[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 23:31, 4 October 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Compilation_and_Installation&amp;diff=2885</id>
		<title>Compilation and Installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Compilation_and_Installation&amp;diff=2885"/>
		<updated>2019-10-04T12:33:42Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add additional information&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following page is a combination of the &amp;lt;tt&amp;gt;INSTALL&amp;lt;/tt&amp;gt; file provided with the OpenSSL library and notes from the field. If you have questions about what you are doing or seeing, then you should consult &amp;lt;tt&amp;gt;INSTALL&amp;lt;/tt&amp;gt; since it contains the commands and specifies the behavior by the development team.&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses a custom build system to configure the library. Configuration will allow the library to set up the recursive makefiles from &amp;lt;tt&amp;gt;makefile.org&amp;lt;/tt&amp;gt;. Once configured, you use &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; to build the library. You should avoid custom build systems because they often miss details, like each architecture and platform has a unique &amp;lt;tt&amp;gt;opensslconf.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bn.h&amp;lt;/tt&amp;gt; generated by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You must use a C compiler to build the OpenSSL library. You cannot use a C++ compiler. Later, once the library is built, it is OK to create user programs with a C++ compiler. But the library proper must be built with a C compiler.&lt;br /&gt;
&lt;br /&gt;
There are two generations of build system. First is the build system used in OpenSSL 1.0.2 and below. The instructions below apply to it. Second is the build system for OpenSSL 1.1.0 and above. The instructions are similar, but not the same. For example, the second generation abandons the monolithic &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and places individual configurations in the &amp;lt;tt&amp;gt;Configurations&amp;lt;/tt&amp;gt; directory.  Also, the second generation is more platform agnostic and uses templates to produce a final, top level build file (&amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;descrip.mms&amp;lt;/tt&amp;gt;, what have you).&lt;br /&gt;
&lt;br /&gt;
After you configure and build the library, you should always perform a &amp;lt;tt&amp;gt;make test&amp;lt;/tt&amp;gt; to ensure the library performs as expected under its self tests. If you are building OpenSSL 1.1.0 and above, then you will also need PERL 5.10 or higher (see &amp;lt;tt&amp;gt;README.PERL&amp;lt;/tt&amp;gt; for details).&lt;br /&gt;
&lt;br /&gt;
OpenSSL's build system does not rely upon &amp;lt;tt&amp;gt;autotools&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;libtool&amp;lt;/tt&amp;gt;. Also see [http://www.openssl.org/support/faq.html#MISC5 Why aren't tools like 'autoconf' and 'libtool' used?] in the OpenSSL FAQ.&lt;br /&gt;
&lt;br /&gt;
== Retrieve source code ==&lt;br /&gt;
&lt;br /&gt;
The OpenSSL source code can be downloaded from [http://www.openssl.org/source/ OpenSSL Source Tarballs] or any suitable [http://www.openssl.org/source/mirror.html ftp mirror]. There are various versions including stable as well as unstable versions. &lt;br /&gt;
&lt;br /&gt;
The source code is managed via Git. Its referred to as Master. The repository is&lt;br /&gt;
&lt;br /&gt;
: git://git.openssl.org/openssl.git&lt;br /&gt;
&lt;br /&gt;
The source is also available via a [https://github.com/openssl/openssl GitHub] mirror. This repository is updated every 15 minutes.&lt;br /&gt;
&lt;br /&gt;
* [[Use_of_Git|Accessing OpenSSL source code via Git]]&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL is configured for a particular platform with protocol and behavior options using &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should avoid custom build systems because they often miss details, like each architecture and platform has a unique &amp;lt;tt&amp;gt;opensslconf.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bn.h&amp;lt;/tt&amp;gt; generated by &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Supported Platforms ===&lt;br /&gt;
&lt;br /&gt;
You can run &amp;lt;tt&amp;gt;Configure LIST&amp;lt;/tt&amp;gt; to see a list of available platforms.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure LIST&lt;br /&gt;
BC-32&lt;br /&gt;
BS2000-OSD&lt;br /&gt;
BSD-generic32&lt;br /&gt;
BSD-generic64&lt;br /&gt;
BSD-ia64&lt;br /&gt;
BSD-sparc64&lt;br /&gt;
BSD-sparcv8&lt;br /&gt;
BSD-x86&lt;br /&gt;
BSD-x86-elf&lt;br /&gt;
BSD-x86_64&lt;br /&gt;
Cygwin&lt;br /&gt;
Cygwin-x86_64&lt;br /&gt;
DJGPP&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your platform is not listed, then use a similar platform and tune the &amp;lt;tt&amp;gt;$cflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflags&amp;lt;/tt&amp;gt; by making a copy of the configure line and giving it its own name. &amp;lt;tt&amp;gt;$cflags&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflags&amp;lt;/tt&amp;gt; correspond to fields 2 and 6 in a configure line. An example of using a similar configure line is presented in [[Compilation_and_Installation#Using_RPATHs|Using RPATHs]].&lt;br /&gt;
&lt;br /&gt;
=== Configure &amp;amp; Config ===&lt;br /&gt;
&lt;br /&gt;
You use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; to tune the compile and installation process through options and switches. The difference between is &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; properly handles the host-arch-compiler triplet, and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; does not. &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; attempts to guess the triplet, so its a lot like autotool's &amp;lt;tt&amp;gt;config.guess&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You can usually use &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; and it will do the right thing (from Ubuntu 13.04, x64):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config &lt;br /&gt;
Operating system: x86_64-whatever-linux2&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mac OS X can have issues (its often a neglected platform), and you will have to use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; ./Configure darwin64-x86_64-cc&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128 (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also configure on Darwin by exporting &amp;lt;tt&amp;gt;KERNEL_BITS&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export KERNEL_BITS=64&lt;br /&gt;
$ ./config shared no-ssl2 no-ssl3 enable-ec_nistp_64_gcc_128 --openssldir=/usr/local/ssl/macosx-x64/&lt;br /&gt;
Operating system: i686-apple-darwinDarwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
Configuring for darwin64-x86_64-cc&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-jpake        [experimental] OPENSSL_NO_JPAKE (skip dir)&lt;br /&gt;
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5&lt;br /&gt;
    ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you provide a option not known to configure or ask for help, then you get a brief help message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure --help&lt;br /&gt;
Usage: Configure [no-&amp;lt;cipher&amp;gt; ...] [enable-&amp;lt;cipher&amp;gt; ...] [experimental-&amp;lt;cipher&amp;gt; ...]&lt;br /&gt;
[-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared]&lt;br /&gt;
[[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR]&lt;br /&gt;
[--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And if you supply an unknown triplet: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure darwin64-x86_64-clang&lt;br /&gt;
Configuring for darwin64-x86_64-clang&lt;br /&gt;
Usage: Configure [no-&amp;lt;cipher&amp;gt; ...] [enable-&amp;lt;cipher&amp;gt; ...] [experimental-&amp;lt;cipher&amp;gt; ...]&lt;br /&gt;
[-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared]&lt;br /&gt;
[[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR]&lt;br /&gt;
[--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]&lt;br /&gt;
&lt;br /&gt;
pick os/compiler from:&lt;br /&gt;
BC-32 BS2000-OSD BSD-generic32 BSD-generic64 BSD-ia64 BSD-sparc64 BSD-sparcv8 &lt;br /&gt;
BSD-x86 BSD-x86-elf BSD-x86_64 Cygwin Cygwin-pre1.3 DJGPP MPE/iX-gcc OS2-EMX &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
NOTE: If in doubt, on Unix-ish systems use './config'.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
If you are prompted to run &amp;lt;tt&amp;gt;make depend&amp;lt;/tt&amp;gt;, then you must do so. For OpenSSL 1.0.2 and below, its required to update the standard distribution once configuration options change.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Since you've disabled or enabled at least one algorithm, you need to do&lt;br /&gt;
the following before building:&lt;br /&gt;
&lt;br /&gt;
	make depend&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 and above performs the dependency step for you, so you should not see the message. However, you should perform a &amp;lt;tt&amp;gt;make clean&amp;lt;/tt&amp;gt; to ensure the list of objects files is accurate after a reconfiguration.&lt;br /&gt;
&lt;br /&gt;
== Configure Options ==&lt;br /&gt;
&lt;br /&gt;
OpenSSL has been around a long time, and it carries around a lot of cruft. For example, from above, SSLv2 is enabled by default. SSLv2 is completely broken, and you should disable it during configuration. You can disable protocols and provide other options through &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and the following lists some of them.&lt;br /&gt;
&lt;br /&gt;
'''Note''': if you specify a non-existent option, then the configure scripts will proceed without warning. For example, if you inadvertently specify '''no-sslv2''' rather than '''no-ssl2 no-ssl3''', the script will configure ''with'' SSLv2 and ''without'' warning for the unknown no-sslv2.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when building a shared object, both the static archive and shared objects are built. You do not need to do anything special to build both when '''shared''' is specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|+ OpenSSL Library Options&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;150px&amp;quot; | Option&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; class=&amp;quot;unsortable&amp;quot; | Description&lt;br /&gt;
|-&lt;br /&gt;
| --prefix=XXX || See [[#PREFIX_and_OPENSSLDIR|PREFIX and OPENSSLDIR]] in the next section (below).&lt;br /&gt;
|-&lt;br /&gt;
| --openssldir=XXX || See [[#PREFIX_and_OPENSSLDIR|PREFIX and OPENSSLDIR]] in the next section (below).&lt;br /&gt;
|-&lt;br /&gt;
| -d || Debug build of the library. Optimizations are disabled (no &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt; or similar) and &amp;lt;tt&amp;gt;libefence&amp;lt;/tt&amp;gt; is used (&amp;lt;tt&amp;gt;apt-get install electric-fence&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;yum install electric-fence&amp;lt;/tt&amp;gt;). TODO: Any other features?&lt;br /&gt;
|-&lt;br /&gt;
| shared || Build a shared object in addition to the static archive. You probably need a [[#Using_RPATHs|RPATH]] when enabling &amp;lt;tt&amp;gt;shared&amp;lt;/tt&amp;gt; to ensure &amp;lt;tt&amp;gt;openssl&amp;lt;/tt&amp;gt; uses the correct &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;libcrypto&amp;lt;/tt&amp;gt; after installation.&lt;br /&gt;
|-&lt;br /&gt;
| enable-ec_nistp_64_gcc_128 || Use on little endian platforms when GCC supports &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt;. ECDH is about 2 to 4 times faster. Not enabled by default because &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; can't determine it. Enable it if your compiler defines &amp;lt;tt&amp;gt;__SIZEOF_INT128__&amp;lt;/tt&amp;gt;, the CPU is little endian and it tolerates unaligned data access.&lt;br /&gt;
|-&lt;br /&gt;
| enable-capieng || Enables the Microsoft CAPI engine on Windows platforms. Used to access the Windows Certificate Store. Also see [http://openssl.6102.n7.nabble.com/Using-Windows-certificate-store-through-OpenSSL-td46788.html Using Windows certificate store through OpenSSL] on the OpenSSL developer list.&lt;br /&gt;
|-&lt;br /&gt;
| no-ssl2 || Disables SSLv2. &amp;lt;tt&amp;gt;OPENSSL_NO_SSL2&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-ssl3 || Disables SSLv3. &amp;lt;tt&amp;gt;OPENSSL_NO_SSL3&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-comp || Disables compression independent of &amp;lt;tt&amp;gt;zlib&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;OPENSSL_NO_COMP&amp;lt;/tt&amp;gt; will be defined in the OpenSSL headers.&lt;br /&gt;
|-&lt;br /&gt;
| no-idea || Disables IDEA algorithm. Unlike RC5 and MDC2, IDEA is enabled by default&lt;br /&gt;
|-&lt;br /&gt;
| no-asm || Disables assembly language routines (and uses C routines)&lt;br /&gt;
|-&lt;br /&gt;
| no-dtls || Disables DTLS in OpenSSL 1.1.0 and above&lt;br /&gt;
|-&lt;br /&gt;
| no-dtls1 || Disables DTLS in OpenSSL 1.0.2 and below&lt;br /&gt;
|-&lt;br /&gt;
| no-shared || Disables shared objects (only a static library is created)&lt;br /&gt;
|-&lt;br /&gt;
| no-hw || Disables hardware support (useful on mobile devices)&lt;br /&gt;
|-&lt;br /&gt;
| no-engine || Disables hardware support (useful on mobile devices)&lt;br /&gt;
|-&lt;br /&gt;
| no-threads || Disables threading support.&lt;br /&gt;
|-&lt;br /&gt;
| no-dso || Disables the OpenSSL DSO API (the library offers a shared object abstraction layer). If you disable DSO, then you must disable Engines also&lt;br /&gt;
|-&lt;br /&gt;
| no-err || Removes all error function names and error reason text to reduce footprint&lt;br /&gt;
|-&lt;br /&gt;
| no-npn/no-nextprotoneg || Disables Next Protocol Negotiation (NPN). Use &amp;lt;tt&amp;gt;no-nextprotoneg&amp;lt;/tt&amp;gt; for 1.1.0 and above; and &amp;lt;tt&amp;gt;no-npn&amp;lt;/tt&amp;gt; otherwise&lt;br /&gt;
|-&lt;br /&gt;
| no-psk || Disables Preshared Key (PSK). PSK provides mutual authentication independent of trusted authorities, but its rarely offered or used&lt;br /&gt;
|-&lt;br /&gt;
| no-srp || Disables Secure Remote Password (SRP). SRP provides mutual authentication independent of trusted authorities, but its rarely offered or used&lt;br /&gt;
|-&lt;br /&gt;
| no-ec2m || Used when configuring FIPS Capable Library with a FIPS Object Module that only includes prime curves. That is, use this switch if you use &amp;lt;tt&amp;gt;openssl-fips-ecp-2.0.5&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| no-weak-ssl-ciphers || Disables RC4. Available in OpenSSL 1.1.0 and above.&lt;br /&gt;
|-&lt;br /&gt;
| -DXXX || Defines XXX. For example, &amp;lt;tt&amp;gt;-DOPENSSL_NO_HEARTBEATS&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| -DPEDANTIC || Defines PEDANTIC. The library will avoid some undefined behavior, like casting an unaligned byte array to a different pointer type. This define should be used if building OpenSSL with undefined behavior sanitizer (&amp;lt;tt&amp;gt;-fsanitize=undefined&amp;lt;/tt&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| -DOPENSSL_USE_IPV6=0 || Disables IPv6. Useful if OpenSSL encounters incorrect or inconsistent platform headers and mistakenly enables IPv6. Must be passed to &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; manually.&lt;br /&gt;
|-&lt;br /&gt;
| -L''something'', -l''something'', -K''something'', -Wl,''something'' || Linker options, will become part of LDFLAGS.&lt;br /&gt;
|-&lt;br /&gt;
| -''anythingelse'', +''anythingelse'' || Compiler options, will become part of CFLAGS.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''''Note''''': on older OSes, like CentOS 5, BSD 5, and Windows XP or Vista, you will need to configure with &amp;lt;tt&amp;gt;no-async&amp;lt;/tt&amp;gt; when building OpenSSL 1.1.0 and above. The configuration system does not detect lack of the Posix feature on the platforms.&lt;br /&gt;
&lt;br /&gt;
'''''Note''''': you can verify compiler support for &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt; with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# gcc -dM -E - &amp;lt;/dev/null | grep __SIZEOF_INT128__  &lt;br /&gt;
#define __SIZEOF_INT128__ 16&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PREFIX and OPENSSLDIR ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; control the configuration of installed components. The behavior and interactions of &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; are slightly different between OpenSSL 1.0.2 and below, and OpenSSL 1.1.0 and above.&lt;br /&gt;
&lt;br /&gt;
The '''''rule of thumb''''' to use when you want something that &amp;quot;just works&amp;quot; for all recent versions of OpenSSL, including OpenSSL 1.0.2 and 1.1.0, is:&lt;br /&gt;
&lt;br /&gt;
* specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;&lt;br /&gt;
* set &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; to the same location&lt;br /&gt;
&lt;br /&gt;
One word of caution is ''avoid'' &amp;lt;tt&amp;gt;--prefix=/usr&amp;lt;/tt&amp;gt; when OpenSSL versions are '''''not''''' [[Binary_Compatibility|binary compatible]]. You will replace the distro's version of OpenSSL with your version of OpenSSL. It will most likely break everything, including the package management system.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''OpenSSL 1.0.2 and below'''&lt;br /&gt;
&lt;br /&gt;
It is usually ''not'' necessary to specify &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; is ''not'' specified, then &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; is used. However, specifying ''only'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; may result in broken builds because the 1.0.2 build system attempts to build in a FIPS configuration.&lt;br /&gt;
&lt;br /&gt;
You can ''omit'' If &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and use &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. In this case, the paths for &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; will be used during configuration. If &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; is not specified, the the default &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used.&lt;br /&gt;
&lt;br /&gt;
The takeaway is &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used by default, and it can be overridden with &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. The rule of thumb applies for path overrides: specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''OpenSSL 1.1.0 and above'''&lt;br /&gt;
&lt;br /&gt;
OpenSSL 1.1.0 changed the behavior of install rules. You should specify both &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt; to ensure &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt; works as expected.&lt;br /&gt;
&lt;br /&gt;
The takeaway is &amp;lt;tt&amp;gt;/usr/local/ssl&amp;lt;/tt&amp;gt; is used by default, and it can be overridden with ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;. The rule of thumb applies for path overrides: specify ''both'' &amp;lt;tt&amp;gt;--prefix&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--openssldir&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Debug Configuration ===&lt;br /&gt;
&lt;br /&gt;
From the list above, its possible to quickly configure a &amp;quot;debug&amp;quot; build with &amp;lt;tt&amp;gt;./config -d&amp;lt;/tt&amp;gt;. However, you can often get into a more amicable state ''without'' the [http://en.wikipedia.org/wiki/Electric_Fence Electric Fence] dependency by issuing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./config no-asm -g3 -O0 -fno-omit-frame-pointer -fno-inline-functions&lt;br /&gt;
Operating system: x86_64-whatever-linux2&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
Configuring OpenSSL version 1.1.0-pre5-dev (0x0x10100005L)&lt;br /&gt;
    no-asm          [option]   OPENSSL_NO_ASM&lt;br /&gt;
    ...&lt;br /&gt;
Configuring for linux-x86_64&lt;br /&gt;
IsMK1MF       =no&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-Wall -O3 -pthread -m64 -DL_ENDIAN  -g3 -O0 -fno-omit-frame-pointer&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Don't be alarmed about both &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;. The last setting ''&amp;quot;sticks&amp;quot;'', and that's the &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you are working in Visual Studio and you can't step into library calls, then see [http://stackoverflow.com/q/38249235 Step into not working, but can force stepping after some asm steps] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
=== Modifying Build Settings ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to work around OpenSSL's selections for building the library. For example, you might want to use &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt; for a mobile device (rather than &amp;lt;tt&amp;gt;-O3&amp;lt;/tt&amp;gt;), or you might want to use the &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt; compiler (rather than &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
In case like these, its often easier to modify &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; rather than trying to add targets to the configure scripts. Below is a patch that modifies &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; for use under the iOS 7.0 SDK (which lacks &amp;lt;tt&amp;gt;gcc&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;Makefile.org&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;clang&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;CFLAG&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Modifies &amp;lt;tt&amp;gt;MAKEDEPPROG&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;$(CC) -M&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting and resetting of &amp;lt;tt&amp;gt;LANG&amp;lt;/tt&amp;gt; is required on Mac OSX to work around a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; bug or limitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;OLD_LANG=$LANG&lt;br /&gt;
unset LANG&lt;br /&gt;
&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's|\&amp;quot;iphoneos-cross\&amp;quot;\,\&amp;quot;llvm-gcc\:-O3|\&amp;quot;iphoneos-cross\&amp;quot;\,\&amp;quot;clang\:-Os|g' Configure&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/CC= cc/CC= clang/g' Makefile.org&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/CFLAG= -O/CFLAG= -Os/g' Makefile.org&lt;br /&gt;
sed -i &amp;quot;&amp;quot; 's/MAKEDEPPROG=makedepend/MAKEDEPPROG=$(CC) -M/g' Makefile.org&lt;br /&gt;
&lt;br /&gt;
export LANG=$OLD_LANG&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After modification, be sure to dclean and configure again so the new settings are picked up:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;make dclean&lt;br /&gt;
&lt;br /&gt;
./config&lt;br /&gt;
make depend&lt;br /&gt;
make all&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using RPATHs ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt;'s are supported by default on the BSD platforms, but not others. If you are working on Linux and compatibles, then you have to manually add an RPATH. One of the easiest ways to add a &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; is to configure with it as shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config -Wl,-rpath=/usr/local/ssl/lib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Note well''''': you should use a RPATH when building both OpenSSL and your program. If you don't add a RPATH to both, then your program could runtime-link to the wrong version of OpenSSL.&lt;br /&gt;
&lt;br /&gt;
You can also add an &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; by hard coding the &amp;lt;tt&amp;gt;RPATH&amp;lt;/tt&amp;gt; into a configure line. For example, on Debian x86_64 open the file &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; in an editor, copy &amp;lt;tt&amp;gt;linux-x86_64&amp;lt;/tt&amp;gt;, name it &amp;lt;tt&amp;gt;linux-x86_64-rpath&amp;lt;/tt&amp;gt;, and make the following change to add the &amp;lt;tt&amp;gt;-rpath&amp;lt;/tt&amp;gt; option. Notice the addition of &amp;lt;tt&amp;gt;-Wl,-rpath=...&amp;lt;/tt&amp;gt; in two places.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;linux-x86_64-rpath&amp;quot;, &amp;quot;gcc:-m64 -DL_ENDIAN -O3 -Wall -Wl,-rpath=/usr/local/ssl/lib::&lt;br /&gt;
  -D_REENTRANT::-Wl,-rpath=/usr/local/ssl/lib -ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:&lt;br /&gt;
  ${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64&amp;quot;,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Above, fields 2 and 6 were changed. They correspond to &amp;lt;tt&amp;gt;$cflag&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;$ldflag&amp;lt;/tt&amp;gt; in OpenSSL's builds system.&lt;br /&gt;
&lt;br /&gt;
Then, Configure with the new configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./Configure linux-x86_64-rpath shared no-ssl2 no-ssl3 no-comp \&lt;br /&gt;
    --openssldir=/usr/local/ssl enable-ec_nistp_64_gcc_128&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, after &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, verify the settings stuck:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ readelf -d ./libssl.so | grep -i rpath&lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&lt;br /&gt;
$ readelf -d ./libcrypto.so | grep -i rpath&lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&lt;br /&gt;
$ readelf -d ./apps/openssl | grep -i rpath &lt;br /&gt;
0x000000000000000f (RPATH)              Library rpath: [/usr/local/ssl/lib]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you perform &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt;, then &amp;lt;tt&amp;gt;ldd&amp;lt;/tt&amp;gt; will produce expected results:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ldd /usr/local/ssl/lib/libssl.so&lt;br /&gt;
linux-vdso.so.1 =&amp;gt;  (0x00007ffceff6c000)&lt;br /&gt;
 ibcrypto.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007ff5eff96000)&lt;br /&gt;
...&lt;br /&gt;
    &lt;br /&gt;
$ ldd /usr/local/ssl/bin/openssl &lt;br /&gt;
linux-vdso.so.1 =&amp;gt;  (0x00007ffc30d3a000)&lt;br /&gt;
libssl.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libssl.so.1.0.0 (0x00007f9e8372e000)&lt;br /&gt;
libcrypto.so.1.0.0 =&amp;gt; /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007f9e832c0000)&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== FIPS Capable Library ===&lt;br /&gt;
&lt;br /&gt;
If you want to use FIPS validated cryptography, you download, build and install the FIPS Object Module (&amp;lt;tt&amp;gt;openssl-fips-2.0.5.tar.gz&amp;lt;/tt&amp;gt;) according to the [https://www.openssl.org/docs/fips/UserGuide-2.0.pdf FIPS User Guide 2.0] and [https://www.openssl.org/docs/fips/SecurityPolicy-2.0.pdf FIPS 140-2 Security Policy]. You then download, build and install the FIPS Capable Library (&amp;lt;tt&amp;gt;openssl-1.0.1e.tar.gz&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
When configuring the FIPS Capable Library, you must use &amp;lt;tt&amp;gt;fips&amp;lt;/tt&amp;gt; as an option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config fips &amp;lt;other options ...&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are configuring the FIPS Capable Library with only prime curves (&amp;lt;tt&amp;gt;openssl-fips-ecp-2.0.5.tar.gz&amp;lt;/tt&amp;gt;), then you must configure with &amp;lt;tt&amp;gt;no-ec2m&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config fips no-ec2m &amp;lt;other options ...&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Compile Time Checking ===&lt;br /&gt;
&lt;br /&gt;
If you disable an option during configure, you can check if it's available through &amp;lt;tt&amp;gt;OPENSSL_NO_*&amp;lt;/tt&amp;gt; defines. OpenSSL writes the configure options to &amp;lt;tt&amp;gt;&amp;lt;openssl/opensslconf.h&amp;gt;&amp;lt;/tt&amp;gt;. For example, if you want to know if SSLv3 is available, then you would perform the following in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/opensslconf.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#if !defined(OPENSSL_NO_SSL3)&lt;br /&gt;
  /* SSLv3 is available */&lt;br /&gt;
#endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compilation ==&lt;br /&gt;
&lt;br /&gt;
After configuring the library, you should run &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;. If prompted, there's usually no need to &amp;lt;tt&amp;gt;make depend&amp;lt;/tt&amp;gt; since you are building from a clean download.&lt;br /&gt;
&lt;br /&gt;
==== Quick ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./config &amp;lt;nowiki&amp;gt;&amp;lt;options ...&amp;gt; --openssldir=/usr/local/ssl&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
make&lt;br /&gt;
make test&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Various options can be found examining the &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; file (there is a well commented block at its top). OpenSSL ships with SSLv2, SSLv3 and Compression enabled by default (see &amp;lt;tt&amp;gt;my $disabled&amp;lt;/tt&amp;gt;), so you might want to use &amp;lt;tt&amp;gt;no-ssl2 no-ssl3&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;no-ssl3&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;no-comp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Platfom specific ==&lt;br /&gt;
&lt;br /&gt;
=== Linux ===&lt;br /&gt;
&lt;br /&gt;
==== Intel ====&lt;br /&gt;
&lt;br /&gt;
==== ARM ====&lt;br /&gt;
&lt;br /&gt;
==== X32 (ILP32) ====&lt;br /&gt;
&lt;br /&gt;
X32 uses the 32-bit data model (ILP32) on x86_64/amd64. To properly configure for X32 under current OpenSSL distributions, you must use &amp;lt;tt&amp;gt;Configure&amp;lt;/tt&amp;gt; and use the x32 triplet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# ./Configure LIST | grep x32&lt;br /&gt;
linux-x32&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# ./Configure linux-x32      &lt;br /&gt;
Configuring OpenSSL version 1.1.0-pre6-dev (0x0x10100006L)&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN (skip dir)&lt;br /&gt;
    ...&lt;br /&gt;
Configuring for linux-x32&lt;br /&gt;
CC            =gcc&lt;br /&gt;
CFLAG         =-Wall -O3 -pthread -mx32 -DL_ENDIAN &lt;br /&gt;
SHARED_CFLAG  =-fPIC&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If using an amd64-compatible processor and GCC with that supports &amp;lt;tt&amp;gt;__uint128_t&amp;lt;/tt&amp;gt;, then you usually add &amp;lt;tt&amp;gt;enable-ec_nistp_64_gcc_128 &amp;lt;/tt&amp;gt; in addition to your other flags.&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
3noch wrote a VERY good guide [http://developer.covenanteyes.com/building-openssl-for-visual-studio/ here].&lt;br /&gt;
Like he said in his article, make absolutely sure to create separate directories for 32 and 64 bit versions.&lt;br /&gt;
&lt;br /&gt;
==== W32 / Windows NT - Windows 9x ====&lt;br /&gt;
&lt;br /&gt;
type INSTALL.W32&lt;br /&gt;
&lt;br /&gt;
* you need Perl for Win32.  Unless you will build on Cygwin, you will need ActiveState Perl, available from http://www.activestate.com/ActivePerl.&lt;br /&gt;
* one of the following C compilers:&lt;br /&gt;
** Visual C++&lt;br /&gt;
** Borland C&lt;br /&gt;
** GNU C (Cygwin or MinGW)&lt;br /&gt;
* Netwide Assembler, a.k.a. NASM, available from http://nasm.sourceforge.net/ is required if you intend to utilize assembler modules. Note that NASM is now the only supported assembler.&lt;br /&gt;
&lt;br /&gt;
==== W64 ====&lt;br /&gt;
&lt;br /&gt;
Read first the INSTALL.W64 documentation note containing some specific 64bits information.&lt;br /&gt;
See also INSTALL.W32 that still provides additonnal build information common to both the 64 and 32 bit versions.&lt;br /&gt;
&lt;br /&gt;
You may be surprised: the 64bit artefacts are indeed output in the out32* sub-directories and bear names ending *32.dll. Fact is the 64 bit compile target is so far an incremental change over the legacy 32bit windows target. Numerous compile flags are still labelled &amp;quot;32&amp;quot; although those do apply to both 32 and 64bit targets.&lt;br /&gt;
&lt;br /&gt;
The important pre-requisites are to have PERL available (for essential file processing so as to prepare sources and scripts for the target OS) and of course a C compiler like Microsoft Visual Studio for C/C++. Also note the procedure changed at OpenSSL 1.1.0 and is more streamlined. Also see [https://stackoverflow.com/q/39076244/608639 Why there is no ms\do_ms.bat after perl Configure VC-WIN64A] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.1.0 ===&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL 1.0.2 ===&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.0.2 and earlier the procedure is as follows.&lt;br /&gt;
&lt;br /&gt;
# launch a Visual Studio tool x64 Cross Tools Command prompt&lt;br /&gt;
# change to the directory where you have copied openssl sources &amp;lt;code&amp;gt;cd c:\myPath\openssl&amp;lt;/code&amp;gt;&lt;br /&gt;
# configure for the target OS with the command &amp;lt;code&amp;gt;perl Configure VC-WIN64A&amp;lt;/code&amp;gt;. You may also be interested to set more configuration options as documented in the general INSTALL note (for UNIX targets). For instance: &amp;lt;code&amp;gt;perl Configure no-asm VC-WIN64A&amp;lt;/code&amp;gt;.&lt;br /&gt;
# prepare the target environment with the command: &amp;lt;code&amp;gt;ms\do_win64a&amp;lt;/code&amp;gt;&lt;br /&gt;
# ensure you start afresh and notably without linkable products from a previous 32bit compile (as 32 and 64 bits compiling still share common directories) with the command: &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak clean&amp;lt;/code&amp;gt; for the DLL target and &amp;lt;code&amp;gt;nmake -f ms\nt.mak clean&amp;lt;/code&amp;gt; for static libraries.&lt;br /&gt;
# build the code with: &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak&amp;lt;/code&amp;gt; (respectively &amp;lt;code&amp;gt;nmake -f ms\nt.mak&amp;lt;/code&amp;gt; )&lt;br /&gt;
# the artefacts will be found in sub directories out32dll and out32dll.dbg (respectively out32 and out32.dbg for static libraries). The libcrypto and ssl libraries are still named libeay32.lib and ssleay32.lib, and associated includes in inc32 ! You may check this is true 64bit code using the Visual Studio tool 'dumpbin'. For instance &amp;lt;code&amp;gt;dumpbin  /headers out32dll/libeay32.lib | more&amp;lt;/code&amp;gt;, and look at the FILE HEADER section.&lt;br /&gt;
# test the code using the various *test.exe programs in out32dll. Use the 'test' make target to run all tests as in &amp;lt;code&amp;gt;nmake -f ms\ntdll.mak test&amp;lt;/code&amp;gt;&lt;br /&gt;
# we recommend that you move/copy needed includes and libraries from the &amp;quot;32&amp;quot; directories under a new explicit directory tree for 64bit applications from where you will import and link your target applications, similar to that explained in INSTALL.W32.&lt;br /&gt;
&lt;br /&gt;
==== Windows CE ====&lt;br /&gt;
&lt;br /&gt;
=== OS X ===&lt;br /&gt;
&lt;br /&gt;
The earlier discussion presented a lot of information (and some of it had OS X information). Here are the TLDR versions to configure, build and install the library.&lt;br /&gt;
&lt;br /&gt;
If configuring for 64-bit OS X, then use a command similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./Configure darwin64-x86_64-cc shared enable-ec_nistp_64_gcc_128 no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl/macos-x86_64&lt;br /&gt;
make depend&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If configuring for 32-bit OS X, then use a command similar to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./Configure darwin-i386-cc shared no-ssl2 no-ssl3 no-comp --openssldir=/usr/local/ssl/macosx-i386&lt;br /&gt;
make depend&lt;br /&gt;
sudo make install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to build a multiarch OpenSSL library, then see this answer on Stack Overflow: [http://stackoverflow.com/a/25531033/608639 Build Multiarch OpenSSL on OS X].&lt;br /&gt;
&lt;br /&gt;
=== iOS ===&lt;br /&gt;
&lt;br /&gt;
The following builds OpenSSL for iOS using the iPhoneOS SDK. The configuration avoids the dynamic library the DSO interface and engines.&lt;br /&gt;
&lt;br /&gt;
If you run &amp;lt;tt&amp;gt;make install&amp;lt;/tt&amp;gt;, then the headers will be installed in &amp;lt;tt&amp;gt;/usr/local/openssl-ios/include&amp;lt;/tt&amp;gt; and libraries will be installed in &amp;lt;tt&amp;gt;/usr/local/openssl-ios/lib&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== 32-bit ====&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 and above, a 32-bit iOS cross-compiles uses the &amp;lt;tt&amp;gt;ios-cross&amp;lt;/tt&amp;gt; target, and options similar to &amp;lt;tt&amp;gt;--prefix=/usr/local/openssl-ios&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure ios-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios&lt;br /&gt;
&lt;br /&gt;
Configuring OpenSSL version 1.1.1-dev (0x10101000L)&lt;br /&gt;
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-dynamic-engine [forced]&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
Configuring for ios-cross&lt;br /&gt;
&lt;br /&gt;
PERL          =perl&lt;br /&gt;
PERLVERSION   =5.16.2 for darwin-thread-multi-2level&lt;br /&gt;
HASHBANGPERL  =/usr/bin/env perl&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-O3 -D_REENTRANT -arch armv7 -mios-version-min=6.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
CXX           =c++&lt;br /&gt;
CXXFLAG       =-O3 -D_REENTRANT -arch armv7 -mios-version-min=6.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
DEFINES       =NDEBUG OPENSSL_THREADS OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_PIC OPENSSL_BN_ASM_MONT OPENSSL_BN_ASM_GF2m SHA1_ASM SHA256_ASM SHA512_ASM AES_ASM BSAES_ASM GHASH_ASM ECP_NISTZ256_ASM POLY1305_ASM&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are working with OpenSSL 1.0.2 or below, then use the &amp;lt;tt&amp;gt;iphoneos-cross&amp;lt;/tt&amp;gt; target.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure iphoneos-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios&lt;br /&gt;
Configuring for iphoneos-cross&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-engine       [option]   OPENSSL_NO_ENGINE (skip dir)&lt;br /&gt;
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)&lt;br /&gt;
    no-hw           [option]   OPENSSL_NO_HW&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS (skip dir)&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
IsMK1MF=0&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-DOPENSSL_THREADS -D_REENTRANT -O3 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fomit-frame-pointer -fno-common&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 64-bit ====&lt;br /&gt;
&lt;br /&gt;
For OpenSSL 1.1.0 , a 64-bit iOS cross-compiles uses the &amp;lt;tt&amp;gt;ios64-cross&amp;lt;/tt&amp;gt; target, and &amp;lt;tt&amp;gt;--prefix=/usr/local/openssl-ios64&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;ios64-cross&amp;lt;/tt&amp;gt;. There is no built-in 64-bit iOS support for OpenSSL 1.0.2 or below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ export CC=clang;&lt;br /&gt;
$ export CROSS_TOP=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer&lt;br /&gt;
$ export CROSS_SDK=iPhoneOS.sdk&lt;br /&gt;
$ export PATH=&amp;quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
$ ./Configure ios64-cross no-shared no-dso no-hw no-engine --prefix=/usr/local/openssl-ios64&lt;br /&gt;
&lt;br /&gt;
Configuring OpenSSL version 1.1.1-dev (0x10101000L)&lt;br /&gt;
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG&lt;br /&gt;
    no-asan         [default]  OPENSSL_NO_ASAN&lt;br /&gt;
    no-dso          [option]&lt;br /&gt;
    no-dynamic-engine [forced]&lt;br /&gt;
    ...&lt;br /&gt;
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS&lt;br /&gt;
    no-zlib         [default]&lt;br /&gt;
    no-zlib-dynamic [default]&lt;br /&gt;
Configuring for ios64-cross&lt;br /&gt;
&lt;br /&gt;
PERL          =perl&lt;br /&gt;
PERLVERSION   =5.16.2 for darwin-thread-multi-2level&lt;br /&gt;
HASHBANGPERL  =/usr/bin/env perl&lt;br /&gt;
CC            =clang&lt;br /&gt;
CFLAG         =-O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
CXX           =c++&lt;br /&gt;
CXXFLAG       =-O3 -D_REENTRANT -arch arm64 -mios-version-min=7.0.0 -isysroot $(CROSS_TOP)/SDKs/$(CROSS_SDK) -fno-common&lt;br /&gt;
DEFINES       =NDEBUG OPENSSL_THREADS OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_PIC OPENSSL_BN_ASM_MONT SHA1_ASM SHA256_ASM SHA512_ASM VPAES_ASM ECP_NISTZ256_ASM POLY1305_ASM&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Android ===&lt;br /&gt;
&lt;br /&gt;
Visit [[Android]] and [[FIPS Library and Android]].&lt;br /&gt;
&lt;br /&gt;
=== More ===&lt;br /&gt;
&lt;br /&gt;
==== VAX/VMS ====&lt;br /&gt;
&lt;br /&gt;
I you wonder what are files ending with .com like test/testca.com those are VAX/VMX scripts.&lt;br /&gt;
This code is still maintained.&lt;br /&gt;
&lt;br /&gt;
==== OS/2 ====&lt;br /&gt;
&lt;br /&gt;
==== NetWare ====&lt;br /&gt;
5.x 6.x&lt;br /&gt;
&lt;br /&gt;
==== HP-UX ====&lt;br /&gt;
[[HP-UX Itanium FIPS and OpenSSL build]]&lt;br /&gt;
&lt;br /&gt;
==Autoconf==&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses its own configuration system, and does not use Autoconf. However, a number of popular projects use both OpenSSL and Autoconf, and it would be useful to detect either &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;libssl&amp;lt;/tt&amp;gt;. To craft a feature test for OpenSSL that recognizes both &amp;lt;tt&amp;gt;OPENSSL_init_ssl&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SSL_library_init&amp;lt;/tt&amp;gt;, you can use the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if test &amp;quot;$with_openssl&amp;quot; = yes ; then&lt;br /&gt;
  dnl Order matters!&lt;br /&gt;
  if test &amp;quot;$PORTNAME&amp;quot; != &amp;quot;win32&amp;quot;; then&lt;br /&gt;
     AC_CHECK_LIB(crypto, CRYPTO_new_ex_data, [], [AC_MSG_ERROR([library 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_CHECK_LIB(ssl, OPENSSL_init_ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_CHECK_LIB(ssl, SSL_library_init, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssl' is required for OpenSSL])])&lt;br /&gt;
  else&lt;br /&gt;
     AC_SEARCH_LIBS(CRYPTO_new_ex_data, eay32 crypto, [], [AC_MSG_ERROR([library 'eay32' or 'crypto' is required for OpenSSL])])&lt;br /&gt;
     FOUND_SSL_LIB=&amp;quot;no&amp;quot;&lt;br /&gt;
     AC_SEARCH_LIBS(OPENSSL_init_ssl, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AC_SEARCH_LIBS(SSL_library_init, ssleay32 ssl, [FOUND_SSL_LIB=&amp;quot;yes&amp;quot;])&lt;br /&gt;
     AS_IF([test &amp;quot;x$FOUND_SSL_LIB&amp;quot; = xno], [AC_MSG_ERROR([library 'ssleay32' or 'ssl' is required for OpenSSL])])&lt;br /&gt;
  fi&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many thanks to the Postgres folks for donating part of their &amp;lt;tt&amp;gt;configure.in&amp;lt;/tt&amp;gt;. Also see [http://stackoverflow.com/q/39285733 How to tell Autoconf “require symbol A or B” from LIB?] on Stack Overflow.&lt;br /&gt;
&lt;br /&gt;
[[Category:Shell level]]&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
[[Category:Compilation]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=User_talk:Pauli&amp;diff=2880</id>
		<title>User talk:Pauli</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=User_talk:Pauli&amp;diff=2880"/>
		<updated>2019-09-15T04:00:01Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: /* KDF Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== KDF Changes ==&lt;br /&gt;
I think the [modified] KDF example may be too new for most users of OpenSSL. For example, it appears OSSL_PARAM is part of an upcoming release: https://www.openssl.org/docs/manmaster/man3/OSSL_PARAM.html .&lt;br /&gt;
&lt;br /&gt;
I think the new example is going to cause confusion for most users rather than helping them. Also, answers on Stack Overflow a pointing back to the wiki and the old example.&lt;br /&gt;
&lt;br /&gt;
Perhaps you can add the new example as a distinct second example, and clearly state it is part of the OpenSSL 3.0 API.&lt;br /&gt;
&lt;br /&gt;
[[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 00:14, 15 September 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
: Shouldn't this be discussed on the discussion tab of the page that was changed? That would probably make it a little easier for the rest of us to understand what's going on, rather than this random discussion added to a user page that doesn't even exist... &lt;br /&gt;
: --[[User:Levitte|Levitte]] ([[User talk:Levitte|talk]]) 03:57, 15 September 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
:: Yeah, I was trying to have a sidebar to encourage an edit. Sorry about that.&lt;br /&gt;
::&lt;br /&gt;
:: [[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 04:00, 15 September 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=User_talk:Jwalton&amp;diff=2878</id>
		<title>User talk:Jwalton</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=User_talk:Jwalton&amp;diff=2878"/>
		<updated>2019-09-15T01:04:00Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Not sure if I am replying correctly.&lt;br /&gt;
&lt;br /&gt;
The EVP KDF APIs have never been in a release.  There is no example of their use that works on anything except master and the existing example didn't work.  The use of ctrl functions was removed because of the upcoming changes and a general drift to OSSL_PARAMs instead.&lt;br /&gt;
&lt;br /&gt;
Earlier releases of OpenSSL required either calling the KDF functions directly or using the PKEY interface kludge.&lt;br /&gt;
&lt;br /&gt;
: No, you're not replying correctly. You should reply on the thread and not start a new one on a different page.&lt;br /&gt;
:&lt;br /&gt;
: Removing the exiting information was the wrong choice. Add a new example with the new information. Since a user will have two examples to chose from, explain when to use the new example.&lt;br /&gt;
:&lt;br /&gt;
: [[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 00:57, 15 September 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=User_talk:Jwalton&amp;diff=2877</id>
		<title>User talk:Jwalton</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=User_talk:Jwalton&amp;diff=2877"/>
		<updated>2019-09-15T00:57:29Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Not sure if I am replying correctly.&lt;br /&gt;
&lt;br /&gt;
The EVP KDF APIs have never been in a release.  There is no example of their use that works on anything except master and the existing example didn't work.  The use of ctrl functions was removed because of the upcoming changes and a general drift to OSSL_PARAMs instead.&lt;br /&gt;
&lt;br /&gt;
Earlier releases of OpenSSL required either calling the KDF functions directly or using the PKEY interface kludge.&lt;br /&gt;
&lt;br /&gt;
: No, you're not replying correctly. You should reply on the thread and not start a new one on a different page.&lt;br /&gt;
:&lt;br /&gt;
: Removing the exiting information was the wrong choice. Add a new example with the new information.&lt;br /&gt;
:&lt;br /&gt;
: [[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 00:57, 15 September 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=User_talk:Jwalton&amp;diff=2876</id>
		<title>User talk:Jwalton</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=User_talk:Jwalton&amp;diff=2876"/>
		<updated>2019-09-15T00:57:16Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Not sure if I am replying correctly.&lt;br /&gt;
&lt;br /&gt;
The EVP KDF APIs have never been in a release.  There is no example of their use that works on anything except master and the existing example didn't work.  The use of ctrl functions was removed because of the upcoming changes and a general drift to OSSL_PARAMs instead.&lt;br /&gt;
&lt;br /&gt;
Earlier releases of OpenSSL required either calling the KDF functions directly or using the PKEY interface kludge.&lt;br /&gt;
&lt;br /&gt;
: No, you're not replying correctly. You should reply on the thread and not start a new one on a different page.&lt;br /&gt;
:&lt;br /&gt;
: Removing the exiting information was the wrong choice. Add a new example with the new information.&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=User_talk:Pauli&amp;diff=2874</id>
		<title>User talk:Pauli</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=User_talk:Pauli&amp;diff=2874"/>
		<updated>2019-09-15T00:14:54Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== KDF Changes ==&lt;br /&gt;
I think the [modified] KDF example may be too new for most users of OpenSSL. For example, it appears OSSL_PARAM is part of an upcoming release: https://www.openssl.org/docs/manmaster/man3/OSSL_PARAM.html .&lt;br /&gt;
&lt;br /&gt;
I think the new example is going to cause confusion for most users rather than helping them. Also, answers on Stack Overflow a pointing back to the wiki and the old example.&lt;br /&gt;
&lt;br /&gt;
Perhaps you can add the new example as a distinct second example, and clearly state it is part of the OpenSSL 3.0 API.&lt;br /&gt;
&lt;br /&gt;
[[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 00:14, 15 September 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=User_talk:Pauli&amp;diff=2873</id>
		<title>User talk:Pauli</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=User_talk:Pauli&amp;diff=2873"/>
		<updated>2019-09-15T00:14:18Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Created page with &amp;quot;I think the [modified] KDF example may be too new for most users of OpenSSL. For example, it appears OSSL_PARAM is part of an upcoming release: https://www.openssl.org/docs/ma...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I think the [modified] KDF example may be too new for most users of OpenSSL. For example, it appears OSSL_PARAM is part of an upcoming release: https://www.openssl.org/docs/manmaster/man3/OSSL_PARAM.html .&lt;br /&gt;
&lt;br /&gt;
I think the new example is going to cause confusion for most users rather than helping them. Also, answers on Stack Overflow a pointing back to the wiki and the old example.&lt;br /&gt;
&lt;br /&gt;
Perhaps you can add the new example as a distinct second example, and clearly state it is part of the OpenSSL 3.0 API.&lt;br /&gt;
&lt;br /&gt;
[[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 00:14, 15 September 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Library_Initialization&amp;diff=2840</id>
		<title>Talk:Library Initialization</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Library_Initialization&amp;diff=2840"/>
		<updated>2019-07-29T20:59:37Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
You said:&lt;br /&gt;
&amp;quot;CRYPTO_cleanup_all_ex_data and ERR_remove_state should be called on each thread, and not just the main thread.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
However the FAQ says:&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;Brutal&amp;quot; (thread-unsafe) Application-global cleanup functions:&lt;br /&gt;
 &lt;br /&gt;
   ERR_free_strings(), EVP_cleanup() and CRYPTO_cleanup_all_ex_data().'&lt;br /&gt;
&lt;br /&gt;
And the code comments for CRYPTO_cleanup_all_ex_data() say:&lt;br /&gt;
 /* Release all &amp;quot;ex_data&amp;quot; state to prevent memory leaks. This can't be made&lt;br /&gt;
  * thread-safe without overhauling a lot of stuff, and shouldn't really be&lt;br /&gt;
  * called under potential race-conditions anyway (it's for program shutdown&lt;br /&gt;
  * after all). */&lt;br /&gt;
&lt;br /&gt;
So I don't think its right to say CRYPTO_cleanup_all_ex_data() should be called on each thread.&lt;br /&gt;
--[[User:Matt|Matt]] ([[User talk:Matt|talk]]) 14:30, 7 May 2015 (UTC)&lt;br /&gt;
&lt;br /&gt;
: This is going back 5 or 7 years... I was having trouble under Valgrind. I asked a few messages on the mailing list about how to cleanup properly. Both CRYPTO_cleanup_all_ex_data and ERR_remove_state (on each thread) dropped out of the messages/questions. Also see [http://openssl.6102.n7.nabble.com/Order-of-Cleanup-to-avoid-memory-leaks-td48474.html Order of Cleanup to avoid memory leaks?]. I don't know if it correct thing to do nowadays.&lt;br /&gt;
: [[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 20:58, 29 July 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Library_Initialization&amp;diff=2839</id>
		<title>Talk:Library Initialization</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Library_Initialization&amp;diff=2839"/>
		<updated>2019-07-29T20:59:01Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
You said:&lt;br /&gt;
&amp;quot;CRYPTO_cleanup_all_ex_data and ERR_remove_state should be called on each thread, and not just the main thread.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
However the FAQ says:&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;Brutal&amp;quot; (thread-unsafe) Application-global cleanup functions:&lt;br /&gt;
 &lt;br /&gt;
   ERR_free_strings(), EVP_cleanup() and CRYPTO_cleanup_all_ex_data().'&lt;br /&gt;
&lt;br /&gt;
And the code comments for CRYPTO_cleanup_all_ex_data() say:&lt;br /&gt;
 /* Release all &amp;quot;ex_data&amp;quot; state to prevent memory leaks. This can't be made&lt;br /&gt;
  * thread-safe without overhauling a lot of stuff, and shouldn't really be&lt;br /&gt;
  * called under potential race-conditions anyway (it's for program shutdown&lt;br /&gt;
  * after all). */&lt;br /&gt;
&lt;br /&gt;
So I don't think its right to say CRYPTO_cleanup_all_ex_data() should be called on each thread.&lt;br /&gt;
--[[User:Matt|Matt]] ([[User talk:Matt|talk]]) 14:30, 7 May 2015 (UTC)&lt;br /&gt;
&lt;br /&gt;
: This is going back 5 or 7 years... I was having trouble under Valgrind. I asked a few messages on the mailing list about how to cleanup properly. Both CRYPTO_cleanup_all_ex_data and ERR_remove_state (on each thread) dropped out of it. Also see [http://openssl.6102.n7.nabble.com/Order-of-Cleanup-to-avoid-memory-leaks-td48474.html Order of Cleanup to avoid memory leaks?]. I don't know if it correct thing to do nowadays.&lt;br /&gt;
: [[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 20:58, 29 July 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Library_Initialization&amp;diff=2838</id>
		<title>Talk:Library Initialization</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Library_Initialization&amp;diff=2838"/>
		<updated>2019-07-29T20:58:38Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
You said:&lt;br /&gt;
&amp;quot;CRYPTO_cleanup_all_ex_data and ERR_remove_state should be called on each thread, and not just the main thread.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
However the FAQ says:&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;Brutal&amp;quot; (thread-unsafe) Application-global cleanup functions:&lt;br /&gt;
 &lt;br /&gt;
   ERR_free_strings(), EVP_cleanup() and CRYPTO_cleanup_all_ex_data().'&lt;br /&gt;
&lt;br /&gt;
And the code comments for CRYPTO_cleanup_all_ex_data() say:&lt;br /&gt;
 /* Release all &amp;quot;ex_data&amp;quot; state to prevent memory leaks. This can't be made&lt;br /&gt;
  * thread-safe without overhauling a lot of stuff, and shouldn't really be&lt;br /&gt;
  * called under potential race-conditions anyway (it's for program shutdown&lt;br /&gt;
  * after all). */&lt;br /&gt;
&lt;br /&gt;
So I don't think its right to say CRYPTO_cleanup_all_ex_data() should be called on each thread.&lt;br /&gt;
--[[User:Matt|Matt]] ([[User talk:Matt|talk]]) 14:30, 7 May 2015 (UTC)&lt;br /&gt;
&lt;br /&gt;
: This is going back 5 or 7 years... I was having trouble under Valgrind. I asked a few messages on the mailing list about how to cleanup properly. Both CRYPTO_cleanup_all_ex_data and ERR_remove_state (on each thread) dropped out of it. Also see [http://openssl.6102.n7.nabble.com/Order-of-Cleanup-to-avoid-memory-leaks-td48474.html Order of Cleanup to avoid memory leaks?].&lt;br /&gt;
:&lt;br /&gt;
: I don't know if it correct thing to do nowadays.&lt;br /&gt;
:&lt;br /&gt;
: [[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 20:58, 29 July 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Multiprecision_arithmetic_internals&amp;diff=2833</id>
		<title>Talk:Multiprecision arithmetic internals</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Multiprecision_arithmetic_internals&amp;diff=2833"/>
		<updated>2019-07-29T16:03:53Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Some formatting.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== BN Library Broken Link ==&lt;br /&gt;
&lt;br /&gt;
It looks like [https://www.openssl.org/docs/man1.0.2/man3/bn.html this] is the documentation the first link was supposed to point to, but this documentation module is not in version 1.1.1. Since &lt;br /&gt;
I would assume this means either the module or the interface is deprecated, what is the recommendation in this scenario where we're updating the documentation regarding a deprecated function or library?&lt;br /&gt;
Should I keep the broken link notice and not even list it to prevent new users from using a deprecated feature, at least until we finish modernizing the documentation? Or do I add it in and simply&lt;br /&gt;
append a notice stating the feature is part of a deprecated API?&lt;br /&gt;
&lt;br /&gt;
--[[User:Jflopezfernandez|Jflopezfernandez]] ([[User talk:Jflopezfernandez|talk]]) 06:25, 29 July 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
: Actually the BN API is not deprecated. It's just that there's been quite a lot of work over time on trying to improve the documentation and lots of stuff got moved around. It looks like at some point this overview page got deleted - I'm not entirely sure why. I'd suggest we could direct users to some of the key BIGNUM pages instead, such as [https://www.openssl.org/docs/man1.1.1/man3/BN_new.html BN_new()], [https://www.openssl.org/docs/man1.1.1/man3/BN_add.html BN_add()], etc.&lt;br /&gt;
:&lt;br /&gt;
: --[[User:Matt|Matt]] ([[User talk:Matt|talk]]) 07:57, 29 July 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
:: Ah, okay, that's good to know. I'll go ahead and add links to those pages.&lt;br /&gt;
::&lt;br /&gt;
:: --[[User:Jflopezfernandez|Jflopezfernandez]] ([[User talk:Jflopezfernandez|talk]]) 14:58, 29 July 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Elliptic_Curve_Cryptography&amp;diff=2817</id>
		<title>Talk:Elliptic Curve Cryptography</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Elliptic_Curve_Cryptography&amp;diff=2817"/>
		<updated>2019-07-29T03:28:08Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: /* Source Code Highlighting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Source Code Highlighting ==&lt;br /&gt;
&lt;br /&gt;
I messed around with the sample code and came up with some basic highlighting that I thought made the code easier to read. This is a sample of what I would be changing the sample code to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: blue;&amp;quot;&amp;gt;#include &amp;lt;&amp;lt;/span&amp;gt;openssl/obj_mac.h&amp;lt;span style=&amp;quot;color: blue&amp;quot;&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: blue;&amp;quot;&amp;gt;#include &amp;lt;&amp;lt;/span&amp;gt;openssl/ec.h&amp;lt;span style=&amp;quot;color: blue&amp;quot;&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: green;&amp;quot;&amp;gt;/* Other things up here... */&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #000000;&amp;quot;&amp;gt;EC_GROUP&amp;lt;/span&amp;gt; *curve;&lt;br /&gt;
  &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: blue&amp;quot;&amp;gt;if&amp;lt;/span&amp;gt;(&amp;lt;span style=&amp;quot;color: purple&amp;quot;&amp;gt;NULL&amp;lt;/span&amp;gt; == (curve = EC_GROUP_new_by_curve_name(&amp;lt;span style=&amp;quot;color: purple&amp;quot;&amp;gt;NID_secp224r1&amp;lt;/span&amp;gt;)))&lt;br /&gt;
     handleErrors();&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I have no strong feelings towards the specific colors, I just picked something I thought was simple and clean. By all means if you have a suggestion regarding the theme I'm all ears. As I said, the point of this change is to make the code easier to read, and since I know theme selection and taste are pretty arbitrary and some people might prefer the code as it is, I thought it best to leave the sample code on live as it was for now. &lt;br /&gt;
 &lt;br /&gt;
[[User:Jflopezfernandez|Jflopezfernandez]] ([[User talk:Jflopezfernandez|talk]]) 02:50, 29 July 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
: I believe mediawiki has colorizers to do that; see [https://www.mediawiki.org/wiki/Category:Syntax_highlighting_extensions Syntax highlighting extensions]. Maybe you can ping Richard and ask him to install one.&lt;br /&gt;
: If there is a pain point, it will likely be CentOS. Red Hat provides ancient software (even with SCL enabled) so OpenSSL mediawiki software is old. You may have a hard time finding an acceptable extension because mediawiki is too old.&lt;br /&gt;
:&lt;br /&gt;
: [[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 03:24, 29 July 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Elliptic_Curve_Cryptography&amp;diff=2815</id>
		<title>Talk:Elliptic Curve Cryptography</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Elliptic_Curve_Cryptography&amp;diff=2815"/>
		<updated>2019-07-29T03:24:46Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Source Code Highlighting ==&lt;br /&gt;
&lt;br /&gt;
I messed around with the sample code and came up with some basic highlighting that I thought made the code easier to read. This is a sample of what I would be changing the sample code to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: blue;&amp;quot;&amp;gt;#include &amp;lt;&amp;lt;/span&amp;gt;openssl/obj_mac.h&amp;lt;span style=&amp;quot;color: blue&amp;quot;&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: blue;&amp;quot;&amp;gt;#include &amp;lt;&amp;lt;/span&amp;gt;openssl/ec.h&amp;lt;span style=&amp;quot;color: blue&amp;quot;&amp;gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: green;&amp;quot;&amp;gt;/* Other things up here... */&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #000000;&amp;quot;&amp;gt;EC_GROUP&amp;lt;/span&amp;gt; *curve;&lt;br /&gt;
  &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: blue&amp;quot;&amp;gt;if&amp;lt;/span&amp;gt;(&amp;lt;span style=&amp;quot;color: purple&amp;quot;&amp;gt;NULL&amp;lt;/span&amp;gt; == (curve = EC_GROUP_new_by_curve_name(&amp;lt;span style=&amp;quot;color: purple&amp;quot;&amp;gt;NID_secp224r1&amp;lt;/span&amp;gt;)))&lt;br /&gt;
     handleErrors();&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I have no strong feelings towards the specific colors, I just picked something I thought was simple and clean. By all means if you have a suggestion regarding the theme I'm all ears. As I said, the point of this change is to make the code easier to read, and since I know theme selection and taste are pretty arbitrary and some people might prefer the code as it is, I thought it best to leave the sample code on live as it was for now. &lt;br /&gt;
 &lt;br /&gt;
[[User:Jflopezfernandez|Jflopezfernandez]] ([[User talk:Jflopezfernandez|talk]]) 02:50, 29 July 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
: I believe mediawiki has colorizers to do that; see [https://www.mediawiki.org/wiki/Category:Syntax_highlighting_extensions Syntax highlighting extensions]. Maybe you can ping Richard and ask him to install one.&lt;br /&gt;
:&lt;br /&gt;
: [[User:Jwalton|Jwalton]] ([[User talk:Jwalton|talk]]) 03:24, 29 July 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Elliptic_Curve_Cryptography&amp;diff=2812</id>
		<title>Elliptic Curve Cryptography</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Elliptic_Curve_Cryptography&amp;diff=2812"/>
		<updated>2019-07-29T02:26:50Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Fix EC_KEY_get_asn1_flag return value on all paths&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The OpenSSL '''EC''' library provides support for [https://en.wikipedia.org/wiki/Elliptic-curve_cryptography '''Elliptic Curve Cryptography'''] ('''ECC'''). It is the basis for the OpenSSL implementation of the [https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm Elliptic Curve Digital Signature Algorithm] (ECDSA) and [https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman Elliptic Curve Diffie-Hellman] (ECDH).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong&amp;gt;Note:&amp;lt;/strong&amp;gt; This page provides an overview of what ECC is, as well as a description of the low-level OpenSSL API for working with Elliptic Curves. If all you need is support for normal ECDSA and ECDH operations then you should normally use the high-level [[EVP|EVP API]]. Refer to [[EVP Signing and Verifying]] for how to perform digital signature operations (including using ECDSA), [[EVP Key Derivation]] for how to derive shared secrets using Diffie-Hellman and Elliptic Curve Diffie-Hellman, and [[EVP Key and Parameter Generation]] for details of how to create EC Keys.&lt;br /&gt;
&lt;br /&gt;
== Why use Elliptic Curves? ==&lt;br /&gt;
&lt;br /&gt;
The primary advantage of using Elliptic Curve based cryptography is reduced key size and hence speed. Elliptic curve based algorithms use significantly smaller key sizes than their non elliptic curve equivalents. The difference in equivalent key sizes increases dramatically as the key sizes increase. The approximate equivalence in security strength for symmetric algorithms compared to standard asymmetric algorithms and elliptic curve algorithms is shown in the table below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div name=&amp;quot;div-table&amp;quot; style=&amp;quot;margin: 24px;&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin: auto; width: 40%; text-align: center; padding: 8px;&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Symmetric Key Length !! Standard asymmetric Key Length !! Elliptic Curve Key Length&lt;br /&gt;
|-&lt;br /&gt;
| 80 || 1024 || 160&lt;br /&gt;
|-&lt;br /&gt;
| 112 || 2048 || 224&lt;br /&gt;
|-&lt;br /&gt;
| 128 || 3072 || 256&lt;br /&gt;
|-&lt;br /&gt;
| 192 || 7680 || 384&lt;br /&gt;
|-&lt;br /&gt;
| 256 || 15360 || 512&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be seen, to get equivalent strength to a 256 bit symmetric key, a standard asymmetric algorithm would have to use an enormous key of 15360 bits. Keys of this size are typically not practical due to the amount of processing power that would be required, and therefore the speed of the operations. However, with elliptic curve algorithms, the equivalent key length is 512 bits, which is entirely practical. &lt;br /&gt;
&lt;br /&gt;
== What is an Elliptic Curve? ==&lt;br /&gt;
&lt;br /&gt;
First of all some terminology. We need to define what is meant by a field. In essence a field is a '''set''' of elements with operations defined for the elements of that set that equate to something like addition, substraction, multiplication and division. The elements could be numbers, or they could be something else entirely. In order to be a field the following conditions also have to be met:&lt;br /&gt;
* Both addition and multiplicaiton are closed over the set, so for example if a and b are in the set then so are a + b and a * b&lt;br /&gt;
* Addition and multiplication must be associative: so a + (b + c) = (a + b) + c and similarly for multiplication&lt;br /&gt;
* Addition and multiplication must be commutative: so a + b = b + a and similarly for multiplication&lt;br /&gt;
* Both addition and multiplication must have identity elements. So, for example 0 and 1 where: a + 0 = a, and a * 1 = a&lt;br /&gt;
* There must be additive and multiplicative inverses for all elements in the set. So, for example, for every element a in the set there is also a -a so that a + (-a) = 0 (where 0 is the identity element for addition). Similarly for multiplication.&lt;br /&gt;
* Multiplication distributes over addition. So if a, b and c are in the set then a * (b + c) = (a * b) + (a * c)&lt;br /&gt;
&lt;br /&gt;
A finite field is simply a field where the set has a finite number of elements. So, for example, the set of all integers could not be used as the basis for a finite field because there are an infinite number of them. However the set of integers from 0 to 100 could form the basis of a finite field.&lt;br /&gt;
&lt;br /&gt;
So now we can define what an Elliptic Curve is. In general an Elliptic Curve is one of the form:&lt;br /&gt;
y&amp;amp;sup2; = x&amp;amp;sup3; + ax + b, where x, y, a and b are elements of some Field&lt;br /&gt;
&lt;br /&gt;
In Elliptic Curve Cryptography we further restrict this such that x, y, a and b are elements of a '''finite''' field.&lt;br /&gt;
&lt;br /&gt;
Contrary to its name Elliptic Curves do not form an ellipse!&lt;br /&gt;
&lt;br /&gt;
Ok, so far so good - but now it gets a bit more complicated! As well as the points on our curve we add an additional &amp;quot;special&amp;quot; point known as infinity. Using this set of points (i.e. all the points on the curve and infinity), we can define some operations on this set, which we call Point Addition and Point Multiplication. &lt;br /&gt;
&lt;br /&gt;
Points on a curve are given in terms of their x and y co-ordinates, (x, y). Point Addition is essentially an operation which takes any two given points on a curve and yields a third point which is also on the curve. The maths behind this gets a bit complicated but think of it in these terms. Plot two points on an elliptic curve. Now draw a straight line which goes through both points. That line will intersect the curve at some third point. That third point is the result of the addition operation. Point Doubling is similar and can be thought of as adding a point to itself. Imagine a point on the curve and draw a straight line which is a tangent to the curve at that point. The result of the Point Doubling operation is where that tangent line intersects the curve at some other point.&lt;br /&gt;
&lt;br /&gt;
Point multiplication is the operation of taking a point on the curve and &amp;quot;multiplying&amp;quot; it by some number. In practice this is achieved through repeated addition and doubling operations. &lt;br /&gt;
&lt;br /&gt;
So with our set of points on a curve (plus the special point, infinity) we can start doing something useful. First of all we pick a point on the curve called the '''generator''' (we'll call it g).&lt;br /&gt;
&lt;br /&gt;
Now:&lt;br /&gt;
* 0g = infinity&lt;br /&gt;
* 1g = g&lt;br /&gt;
* 2g = g + g&lt;br /&gt;
* 3g = g + g + g (or 2g + g)&lt;br /&gt;
* and so on.&lt;br /&gt;
&lt;br /&gt;
Remember g, 2g and 3g are all points on the curve, and '''+''' in this context means point addition as defined above. If you keep going in this way you will eventually come to some number (lets call it '''n'''), such that ng = infinity. The set of points generated by repeatedly adding g to itself, along with the Point Addition operation together form a mathematical structure known as a '''group'''.&lt;br /&gt;
&lt;br /&gt;
If you are lucky then you may have chosen a curve and a g, such that continually adding g to itself will eventually visit all of the possible points on the curve - but often this is not the case. The number '''n''' as defined above, is called the '''order''' of g. For various complicated mathematical reasons it also turns out that the total number of points that exist on the curve is divisble by n. Dividing the total number of points by n gives you another number known as the cofactor.&lt;br /&gt;
&lt;br /&gt;
The security of Elliptic Curve Cryptography comes from the fact that given some point on the curve kg, (where k is a number and g is the known generator point), it is difficult to work out what the value of '''k''' is. This is known as the '''discrete logarithm problem'''. In the Elliptic Curve Cryptography algorithms ECDH and ECDSA, the point kg would be a public key, and the number k would be the private key.&lt;br /&gt;
&lt;br /&gt;
== Types of Field ==&lt;br /&gt;
&lt;br /&gt;
In principle there are many different types of field that could be used for the values x and y of a point (x, y). In practice however there are two primary ones used, and these are the two that are supported by the OpenSSL EC library.&lt;br /&gt;
&lt;br /&gt;
The simplest is typically referred to as the prime field F&amp;lt;sub&amp;gt;p&amp;lt;/sub&amp;gt; where p is a prime number. In cryptographic applications p must be a very large prime number. The elements of the set are simply the numbers 0 through to p-1, and addition and multiplication over the field have the normal meaning for modular (or clock) arithmetic. So, if p=7 then the elements of the set are {0, 1, 2, 3, 4, 5, 6} and:&lt;br /&gt;
&lt;br /&gt;
0 + 1 = 1&lt;br /&gt;
&lt;br /&gt;
2 + 3 = 5&lt;br /&gt;
&lt;br /&gt;
3 + 3 = 6&lt;br /&gt;
&lt;br /&gt;
4 + 3 = 0&lt;br /&gt;
&lt;br /&gt;
5 + 4 = 2&lt;br /&gt;
&lt;br /&gt;
and so on.&lt;br /&gt;
&lt;br /&gt;
The next common type of field is referred to as the binary field F&amp;lt;sub&amp;gt;2&amp;lt;sup&amp;gt;m&amp;lt;/sup&amp;gt;&amp;lt;/sub&amp;gt;. Elements of a binary field are typically represented as polynomials and not as numbers. So for example an element could be:&lt;br /&gt;
&lt;br /&gt;
x&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt;+x&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
&lt;br /&gt;
This can then be expressed as a binary number ({1 0 1 0 1} in this case), where each term represents one bit in the binary representation. Addition of such polynomials is done as normal but with the result of each term reduced modulo 2. So for example:&lt;br /&gt;
&lt;br /&gt;
(x&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; + 1) + (x&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; + x) = 2x&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; + x + 1&lt;br /&gt;
&lt;br /&gt;
Each term is then reduced modulo 2 to give an answer 0x&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; + x +1 = x + 1&lt;br /&gt;
&lt;br /&gt;
In binary representation this sum could be expressed as follows:&lt;br /&gt;
&lt;br /&gt;
{1 0 1} + {1 1 0} = {0 1 1}&lt;br /&gt;
&lt;br /&gt;
Note then that addition is just a simple XOR operation.&lt;br /&gt;
&lt;br /&gt;
Multiplication in the binary field is done respective to an '''irreducible polynomial'''. Multiplication of polynomials is done in the normal way and the result is then divided by the irreducible polynomial. The remainder is the result of the multiplication. See [http://en.wikipedia.org/wiki/Finite_field_arithmetic Finite Field Arithmetic], for a discussion of binary field arithmetic.&lt;br /&gt;
&lt;br /&gt;
== Defining Curves ==&lt;br /&gt;
&lt;br /&gt;
The parameters necessary for performing cryptographic operations for ECDH and ECDSA are simply the parameters required to set up the curve. Namely, the type of field e.g. prime (F&amp;lt;sub&amp;gt;p&amp;lt;/sub&amp;gt;) or binary (F&amp;lt;sub&amp;gt;2&amp;lt;sup&amp;gt;m&amp;lt;/sup&amp;gt;&amp;lt;/sub&amp;gt;), the value p for a prime field, the irreducible polynomial for a binary field, the values a and b from the curve equation, the generator point (g), the order, and the cofactor.&lt;br /&gt;
&lt;br /&gt;
Fortunately, unless you are defining a new curve (not recommended unless you know what you are doing), or you are using an unusual curve that OpenSSL does not have support for, you can usually utilise one of the '''named''' curves that are built-in to OpenSSL. These are a set of well known and widely used curves. The complete collection of curve parameters can be set in one go simply by selecting the appropriate named curve using [[Manual:EC_GROUP_new(3)|EC_GROUP_new_by_curve_name]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/obj_mac.h&amp;gt;&lt;br /&gt;
#include &amp;lt;openssl/ec.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
EC_GROUP *curve;&lt;br /&gt;
 &lt;br /&gt;
if(NULL == (curve = EC_GROUP_new_by_curve_name(NID_secp224r1)))&lt;br /&gt;
    handleErrors();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a custom curve needs to be created, then it can be done as follows. This example code creates the same curve as the code above, but creates it &amp;quot;manually&amp;quot;. In this example a prime field is being used, and the prime number is provided in the variable p. If a binary field was being created instead then a bit string representing the irreducible polynomial would have been provided in the p variable. For further information on the low level EC functions being used refer to the [[Manual:Ec(3)|EC]] manual pages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
 EC_GROUP *create_curve(void)&lt;br /&gt;
 {&lt;br /&gt;
     BN_CTX *ctx;&lt;br /&gt;
     EC_GROUP *curve;&lt;br /&gt;
     BIGNUM *a, *b, *p, *order, *x, *y;&lt;br /&gt;
     EC_POINT *generator;&lt;br /&gt;
 &lt;br /&gt;
     /* Binary data for the curve parameters */&lt;br /&gt;
     unsigned char a_bin[28] =&lt;br /&gt;
         {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,&lt;br /&gt;
             0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,&lt;br /&gt;
             0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE};&lt;br /&gt;
     unsigned char b_bin[28] =&lt;br /&gt;
         {0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41,&lt;br /&gt;
             0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA,&lt;br /&gt;
             0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4};&lt;br /&gt;
     unsigned char p_bin[28] =&lt;br /&gt;
         {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,&lt;br /&gt;
             0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,&lt;br /&gt;
             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};&lt;br /&gt;
     unsigned char order_bin[28] =&lt;br /&gt;
         {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,&lt;br /&gt;
             0xFF,0xFF,0xFF,0xFF,0x16,0xA2,0xE0,0xB8,0xF0,0x3E,&lt;br /&gt;
             0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D };&lt;br /&gt;
     unsigned char x_bin[28] =&lt;br /&gt;
         {0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13,&lt;br /&gt;
             0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22,&lt;br /&gt;
             0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21};&lt;br /&gt;
     unsigned char y_bin[28] =&lt;br /&gt;
         {0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22,&lt;br /&gt;
             0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64,&lt;br /&gt;
             0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34};&lt;br /&gt;
 &lt;br /&gt;
     /* Set up the BN_CTX */&lt;br /&gt;
     if(NULL == (ctx = BN_CTX_new())) handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /* Set the values for the various parameters */&lt;br /&gt;
     if(NULL == (a = BN_bin2bn(a_bin, 28, NULL))) handleErrors();&lt;br /&gt;
     if(NULL == (b = BN_bin2bn(b_bin, 28, NULL))) handleErrors();&lt;br /&gt;
     if(NULL == (p = BN_bin2bn(p_bin, 28, NULL))) handleErrors();&lt;br /&gt;
     if(NULL == (order = BN_bin2bn(order_bin, 28, NULL))) handleErrors();&lt;br /&gt;
     if(NULL == (x = BN_bin2bn(x_bin, 28, NULL))) handleErrors();&lt;br /&gt;
     if(NULL == (y = BN_bin2bn(y_bin, 28, NULL))) handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /* Create the curve */&lt;br /&gt;
     if(NULL == (curve = EC_GROUP_new_curve_GFp(p, a, b, ctx))) handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /* Create the generator */&lt;br /&gt;
     if(NULL == (generator = EC_POINT_new(curve))) handleErrors();&lt;br /&gt;
     if(1 != EC_POINT_set_affine_coordinates_GFp(curve, generator, x, y, ctx))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /* Set the generator and the order */&lt;br /&gt;
     if(1 != EC_GROUP_set_generator(curve, generator, order, NULL))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     EC_POINT_free(generator);&lt;br /&gt;
     BN_free(y);&lt;br /&gt;
     BN_free(x);&lt;br /&gt;
     BN_free(order);&lt;br /&gt;
     BN_free(p);&lt;br /&gt;
     BN_free(b);&lt;br /&gt;
     BN_free(a);&lt;br /&gt;
     BN_CTX_free(ctx); &lt;br /&gt;
 &lt;br /&gt;
     return curve;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Working with Keys==&lt;br /&gt;
&lt;br /&gt;
Keys for ECDH and ECDSA are represented using an [[Manual:EC_KEY_new(3)|EC_KEY]] structure in the low level [[Manual:Ec(3)|EC]] API. If you are using the preferred high-level [[EVP]] API then this EC_KEY structure will be wrapped in an [[EVP#EVP Working with EVP_PKEYs|EVP_PKEY]] object.&lt;br /&gt;
&lt;br /&gt;
Creating a new EC_KEY is a process of creating a curve as described above, creating a new EC_KEY object, and then setting the key to use the curve using the [[Manual:EC_KEY_new(3)|EC_KEY_set_group]] function. Alternatively, the creation of the curve and the key can be done in one step as shown below using [[Manual:EC_KEY_new(3)|EC_KEY_new_by_curve_name]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/obj_mac.h&amp;gt;&lt;br /&gt;
#include &amp;lt;openssl/ec.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
EC_KEY *key;&lt;br /&gt;
&lt;br /&gt;
if(NULL == (key = EC_KEY_new_by_curve_name(NID_secp224r1)))&lt;br /&gt;
    handleErrors();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point the EC_KEY object has been set up and associated with the curve - but it is empty. There is no key data in it. In order to generate new keys for use with the EVP interface see [[EVP Key and Parameter Generation]]. To generate them using the low level API this can be done as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	if(1 != EC_KEY_generate_key(key)) handleErrors();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this operation generates a public and private key '''pair'''. Alternatively you may already know either the private key, the public key, or both. Setting the private key and/or public key is done as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;BIGNUM *prv;&lt;br /&gt;
EC_POINT *pub;&lt;br /&gt;
&lt;br /&gt;
/* Set up private key in prv */&lt;br /&gt;
/* Set up public key in pub */&lt;br /&gt;
&lt;br /&gt;
if(1 != EC_KEY_set_private_key(key, prv)) handleErrors();&lt;br /&gt;
if(1 != EC_KEY_set_public_key(key, pub)) handleErrors();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you set the private key then you '''must''' also set the public key. There have been occasional questions on the openssl-users email list from people who only have the private key but do not know the public key. Fortunately calculating the public key is simply a matter of multiplying the private key by the generator for the curve using [[Manual:EC_POINT_add(3)|EC_POINT_mul]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if (1 != EC_POINT_mul(curve, pub, prv, NULL, NULL, ctx))&lt;br /&gt;
    handleErrors();&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, it is possible to convert a low-level EC_KEY object into an EVP_PKEY object using the EVP_PKEY_set1_EC_KEY function described in the manual here: [[Manual:EVP_PKEY_set1_RSA(3)]]&lt;br /&gt;
&lt;br /&gt;
==Named Curves==&lt;br /&gt;
&lt;br /&gt;
If you want to save a key and later load it with &amp;lt;tt&amp;gt;SSL_CTX_use_PrivateKey_file&amp;lt;/tt&amp;gt;, then you '''must''' set the &amp;lt;tt&amp;gt;OPENSSL_EC_NAMED_CURVE&amp;lt;/tt&amp;gt; flag on the key. You do that by calling &amp;lt;tt&amp;gt;EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE)&amp;lt;/tt&amp;gt;. Failure to do so will result in a SSL error of 0x1408a0c1 (no shared cipher) at the server.&lt;br /&gt;
&lt;br /&gt;
As an example, the following creates a elliptic curve key and saves it using a named curve rather than an expanded list of group paramters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;EC_KEY *key = NULL;&lt;br /&gt;
&lt;br /&gt;
key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);&lt;br /&gt;
EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to detect the flags after reading a key or certificate from disk, then use the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;int EC_KEY_get_asn1_flag(const EC_KEY* key)&lt;br /&gt;
{&lt;br /&gt;
  if (key)&lt;br /&gt;
  {&lt;br /&gt;
    const EC_GROUP* group = EC_KEY_get0_group(key);&lt;br /&gt;
    if (group)&lt;br /&gt;
      return EC_GROUP_get_asn1_flag(group);&lt;br /&gt;
  }&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
int flags = EC_KEY_get_asn1_flag(ecKey);&lt;br /&gt;
ASSERT(flags &amp;amp; OPENSSL_EC_NAMED_CURVE);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The certificates below were dumped with &amp;lt;tt&amp;gt;openssl x509 -in server-ecdsa-cert.pem -text -noout&amp;lt;/tt&amp;gt;. The certificate on the left was created with a key using &amp;lt;tt&amp;gt;OPENSSL_EC_NAMED_CURVE&amp;lt;/tt&amp;gt;, while the certificate on the right was not. Notice the certificate on the left includes '''ASN1 OID: prime256v1'''. The certificate on the left can be used with SSL server using ECDSA, but the certificate on the right cannot because it will result in 0x1408a0c1 at the server.&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot;&lt;br /&gt;
| [[File:cert-with-flag.png|thumb|350px|Figure 1: Key with OPENSSL_EC_NAMED_CURVE]]&lt;br /&gt;
| [[File:cert-without-flag.png|thumb|350px|Figure 2: Key without OPENSSL_EC_NAMED_CURVE]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you use a key or certificate without without the &amp;lt;tt&amp;gt;OPENSSL_EC_NAMED_CURVE&amp;lt;/tt&amp;gt; flag (i.e., one that looks like the image on the right), then the SSL connection will fail with the following symptoms:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Client (s_client):&lt;br /&gt;
&lt;br /&gt;
139925962778272:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1256:SSL alert number 40&lt;br /&gt;
139925962778272:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:596:&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Server (s_server):&lt;br /&gt;
&lt;br /&gt;
140339533272744:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1353:&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that OpenSSL's &amp;lt;tt&amp;gt;X509_verify&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;X509_verify_cert&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_CTX_check_private_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SSL_CTX_use_PrivateKey_file&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SSL_CTX_use_certificate_chain_file&amp;lt;/tt&amp;gt; will not return a failure when using a key or certificate in the wrong format.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Elliptic Curve Diffie Hellman]]&lt;br /&gt;
* [[Command Line Elliptic Curve Operations]]&lt;br /&gt;
* [[Manual:ec(3)]]&lt;br /&gt;
&lt;br /&gt;
[[Category:C level]]&lt;br /&gt;
[[Category:Cryptographic Algorithm]]&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Talk:Contributions&amp;diff=2802</id>
		<title>Talk:Contributions</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Talk:Contributions&amp;diff=2802"/>
		<updated>2019-07-26T18:51:23Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: /* Broken link in the introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Broken link in the introduction ==&lt;br /&gt;
&lt;br /&gt;
The broken link points to https://www.openssl.org/contributions.html. I propose changing the introduction to:&lt;br /&gt;
&lt;br /&gt;
There are a number of reasons why code or documentation contributions may not be adopted by the OpenSSL maintainers. See [https://www.openssl.org/community/getting-started.html Getting Started] for an introduction on becoming a contributor. &lt;br /&gt;
&lt;br /&gt;
[[User:Jflopezfernandez|Jflopezfernandez]] ([[User talk:Jflopezfernandez|talk]]) 16:26, 26 July 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
: Works for me. Go for it.&lt;br /&gt;
:&lt;br /&gt;
: --[[User:Matt|Matt]] ([[User talk:Matt|talk]]) 16:38, 26 July 2019 (UTC)&lt;br /&gt;
&lt;br /&gt;
:: Great, it is done.&lt;br /&gt;
:: [[User:Jflopezfernandez|Jflopezfernandez]] ([[User talk:Jflopezfernandez|talk]]) 16:46, 26 July 2019 (UTC)&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2794</id>
		<title>EVP Key Derivation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2794"/>
		<updated>2019-07-23T20:23:58Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: /* HKDF key derivation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Key derivation is the process of deriving one or more secret keys from a secret value such as a password or a passphrase. Several key derivation algoirthms have been standardized, and they are usually referred to a Key Derivation Functions (KDFs). KDFs include PBKDF2 from RFC 2898, HKDF form RFC 5869 and Scrypt from RFC 7914. OpenSSL provides PBKDF2, Scrypt, HKDF, ANSI X9.42 and ANSI X9.63 by way of &amp;lt;tt&amp;gt;EVP_KDF&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Not all key derivation functions are available in all versions of OpenSSL. OpenSSL 1.0.2 and below provide WWW, XXX, YYY and ZZZ. OpenSSL 1.1.0 and above provide WWW, XXX, YYY and ZZZ. TODO: fill in the pieces here and talk about changes.&lt;br /&gt;
&lt;br /&gt;
== HKDF key derivation ==&lt;br /&gt;
&lt;br /&gt;
The following example derives a key and initialization vector using HKDF from RFC 5869 and SHA-256. HKDF was designed by Krawczyk and Eronen, and it is state of the art in expand-then-extract key derivation algorithms. It is usually a good choice when you need a KDF. The program below was taken from the OpenSSL man pages.&lt;br /&gt;
&lt;br /&gt;
HKDF takes three parameter:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;secret&amp;lt;/tt&amp;gt; - private information to use during derivation, like a password or passphrase. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_KEY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; - possibly public information to use during derivation. &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_SALT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; - additional, possibly public information to use during derivation. &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/evp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;openssl/kdf.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    EVP_KDF_CTX *kctx = NULL;&lt;br /&gt;
    unsigned char derived[32];&lt;br /&gt;
&lt;br /&gt;
    if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF)) == NULL) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTX_new_id&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_MD&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, &amp;quot;salt&amp;quot;, (size_t)4) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_SALT&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, &amp;quot;secret&amp;quot;, (size_t)6) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_KEY&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO, &amp;quot;label&amp;quot;, (size_t)5) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_derive(kctx, derived, sizeof(derived)) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_derive&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Use the 32 bytes as a Key and IV */&lt;br /&gt;
    const unsigned char *key = derived+0;&lt;br /&gt;
    const unsigned char  *iv = derived+16;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;Key: &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, key[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;IV:  &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, iv[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    EVP_KDF_CTX_free(kctx);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can compile the program using C99 with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ gcc -std=c99 test.c -o test.exe -l:libcrypto.a -pthread -ldl&lt;br /&gt;
openssl$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Running the program results in the following output.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./test.exe&lt;br /&gt;
Key: 2a c4 36 9f 52 59 96 f8 de 13 73 1f 56 22 4f 34&lt;br /&gt;
IV:  df 0e 4c 96 ca a9 3b fd ec cf 23 7b 50 39 c8 db&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2793</id>
		<title>EVP Key Derivation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2793"/>
		<updated>2019-07-11T01:35:34Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add error checking on EVP_KDF_CTX_new_id&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Key derivation is the process of deriving one or more secret keys from a secret value such as a password or a passphrase. Several key derivation algoirthms have been standardized, and they are usually referred to a Key Derivation Functions (KDFs). KDFs include PBKDF2 from RFC 2898, HKDF form RFC 5869 and Scrypt from RFC 7914. OpenSSL provides PBKDF2, Scrypt, HKDF, ANSI X9.42 and ANSI X9.63 by way of &amp;lt;tt&amp;gt;EVP_KDF&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Not all key derivation functions are available in all versions of OpenSSL. OpenSSL 1.0.2 and below provide WWW, XXX, YYY and ZZZ. OpenSSL 1.1.0 and above provide WWW, XXX, YYY and ZZZ. TODO: fill in the pieces here and talk about changes.&lt;br /&gt;
&lt;br /&gt;
== HKDF key derivation ==&lt;br /&gt;
&lt;br /&gt;
The following example derives a key and initialization vector using HKDF from RFC 5869. HKDF was designed by Krawczyk and Eronen, and it is state of the art in expand-then-extract key derivation algorithms. It is usually a good choice when you need a KDF. The program below was taken from the OpenSSL man pages.&lt;br /&gt;
&lt;br /&gt;
HKDF takes three parameter:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;secret&amp;lt;/tt&amp;gt; - private information to use during derivation, like a password or passphrase. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_KEY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; - possibly public information to use during derivation. &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_SALT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; - additional, possibly public information to use during derivation. &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/evp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;openssl/kdf.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    EVP_KDF_CTX *kctx = NULL;&lt;br /&gt;
    unsigned char derived[32];&lt;br /&gt;
&lt;br /&gt;
    if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF)) == NULL) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTX_new_id&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_MD&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, &amp;quot;salt&amp;quot;, (size_t)4) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_SALT&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, &amp;quot;secret&amp;quot;, (size_t)6) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_KEY&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO, &amp;quot;label&amp;quot;, (size_t)5) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_derive(kctx, derived, sizeof(derived)) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_derive&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Use the 32 bytes as a Key and IV */&lt;br /&gt;
    const unsigned char *key = derived+0;&lt;br /&gt;
    const unsigned char  *iv = derived+16;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;Key: &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, key[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;IV:  &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, iv[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    EVP_KDF_CTX_free(kctx);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can compile the program using C99 with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ gcc -std=c99 test.c -o test.exe -l:libcrypto.a -pthread -ldl&lt;br /&gt;
openssl$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Running the program results in the following output.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./test.exe&lt;br /&gt;
Key: 2a c4 36 9f 52 59 96 f8 de 13 73 1f 56 22 4f 34&lt;br /&gt;
IV:  df 0e 4c 96 ca a9 3b fd ec cf 23 7b 50 39 c8 db&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2792</id>
		<title>EVP Key Derivation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2792"/>
		<updated>2019-07-11T01:32:28Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Tweak introduction.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Key derivation is the process of deriving one or more secret keys from a secret value such as a password or a passphrase. Several key derivation algoirthms have been standardized, and they are usually referred to a Key Derivation Functions (KDFs). KDFs include PBKDF2 from RFC 2898, HKDF form RFC 5869 and Scrypt from RFC 7914. OpenSSL provides PBKDF2, Scrypt, HKDF, ANSI X9.42 and ANSI X9.63 by way of &amp;lt;tt&amp;gt;EVP_KDF&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Not all key derivation functions are available in all versions of OpenSSL. OpenSSL 1.0.2 and below provide WWW, XXX, YYY and ZZZ. OpenSSL 1.1.0 and above provide WWW, XXX, YYY and ZZZ. TODO: fill in the pieces here and talk about changes.&lt;br /&gt;
&lt;br /&gt;
== HKDF key derivation ==&lt;br /&gt;
&lt;br /&gt;
The following example derives a key and initialization vector using HKDF from RFC 5869. HKDF was designed by Krawczyk and Eronen, and it is state of the art in expand-then-extract key derivation algorithms. It is usually a good choice when you need a KDF. The program below was taken from the OpenSSL man pages.&lt;br /&gt;
&lt;br /&gt;
HKDF takes three parameter:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;secret&amp;lt;/tt&amp;gt; - private information to use during derivation, like a password or passphrase. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_KEY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; - possibly public information to use during derivation. &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_SALT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; - additional, possibly public information to use during derivation. &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/evp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;openssl/kdf.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    EVP_KDF_CTX *kctx = NULL;&lt;br /&gt;
    unsigned char derived[32];&lt;br /&gt;
&lt;br /&gt;
    kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF);&lt;br /&gt;
&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_MD&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, &amp;quot;salt&amp;quot;, (size_t)4) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_SALT&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, &amp;quot;secret&amp;quot;, (size_t)6) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_KEY&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO, &amp;quot;label&amp;quot;, (size_t)5) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_derive(kctx, derived, sizeof(derived)) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_derive&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Use the 32 bytes as a Key and IV */&lt;br /&gt;
    const unsigned char *key = derived+0;&lt;br /&gt;
    const unsigned char  *iv = derived+16;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;Key: &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, key[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;IV:  &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, iv[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    EVP_KDF_CTX_free(kctx);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can compile the program using C99 with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ gcc -std=c99 test.c -o test.exe -l:libcrypto.a -pthread -ldl&lt;br /&gt;
openssl$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Running the program results in the following output.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./test.exe&lt;br /&gt;
Key: 2a c4 36 9f 52 59 96 f8 de 13 73 1f 56 22 4f 34&lt;br /&gt;
IV:  df 0e 4c 96 ca a9 3b fd ec cf 23 7b 50 39 c8 db&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2791</id>
		<title>EVP Key Derivation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2791"/>
		<updated>2019-07-11T01:23:59Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Use 'derived' instead of 'out'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Key derivation is the process of deriving one or more secret keys from a secret value such as a password or a passphrase. Several key derivation algoirthms have been standardized, and they are usually referred to a Key Derivation Functions (KDFs). KDFs include PBKDF2 from RFC 2898, HKDF form RFC 5869 and Scrypt from RFC 7914. OpenSSL provides PBKDF2, Scrypt, HKDF, ANSI X9.42 and ANSI X9.63 by way of &amp;lt;tt&amp;gt;EVP_KDF&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Not all key derivation functions are available in all versions of OpenSSL. OpenSSL 1.0.2 and below provide WWW, XXX, YYY and ZZZ. OpenSSL 1.1.0 and above provide WWW, XXX, YYY and ZZZ. TODO: fill in the pieces here and talk about changes.&lt;br /&gt;
&lt;br /&gt;
== HKDF key derivation ==&lt;br /&gt;
&lt;br /&gt;
The following program derives a key using HKDF from RFC 5869. HKDF was designed by Krawczyk and Eronen, and it is state of the art in expand-then-extract key derivation algorithms. It is usually a good choice when you need a KDF. The program below was taken from the OpenSSL man pages.&lt;br /&gt;
&lt;br /&gt;
HKDF takes three parameter:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;secret&amp;lt;/tt&amp;gt; - private information to use during derivation, like a password or passphrase. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_KEY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; - possibly public information to use during derivation. &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_SALT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; - additional, possibly public information to use during derivation. &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/evp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;openssl/kdf.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    EVP_KDF_CTX *kctx = NULL;&lt;br /&gt;
    unsigned char derived[32];&lt;br /&gt;
&lt;br /&gt;
    kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF);&lt;br /&gt;
&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_MD&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, &amp;quot;salt&amp;quot;, (size_t)4) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_SALT&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, &amp;quot;secret&amp;quot;, (size_t)6) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_KEY&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO, &amp;quot;label&amp;quot;, (size_t)5) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_derive(kctx, derived, sizeof(derived)) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_derive&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Use the 32 bytes as a Key and IV */&lt;br /&gt;
    const unsigned char *key = derived+0;&lt;br /&gt;
    const unsigned char  *iv = derived+16;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;Key: &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, key[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;IV:  &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, iv[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    EVP_KDF_CTX_free(kctx);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can compile the program using C99 with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ gcc -std=c99 test.c -o test.exe -l:libcrypto.a -pthread -ldl&lt;br /&gt;
openssl$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Running the program results in the following output.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./test.exe&lt;br /&gt;
Key: 2a c4 36 9f 52 59 96 f8 de 13 73 1f 56 22 4f 34&lt;br /&gt;
IV:  df 0e 4c 96 ca a9 3b fd ec cf 23 7b 50 39 c8 db&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2790</id>
		<title>EVP Key Derivation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2790"/>
		<updated>2019-07-11T01:21:31Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add bullet points.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Key derivation is the process of deriving one or more secret keys from a secret value such as a password or a passphrase. Several key derivation algoirthms have been standardized, and they are usually referred to a Key Derivation Functions (KDFs). KDFs include PBKDF2 from RFC 2898, HKDF form RFC 5869 and Scrypt from RFC 7914. OpenSSL provides PBKDF2, Scrypt, HKDF, ANSI X9.42 and ANSI X9.63 by way of &amp;lt;tt&amp;gt;EVP_KDF&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Not all key derivation functions are available in all versions of OpenSSL. OpenSSL 1.0.2 and below provide WWW, XXX, YYY and ZZZ. OpenSSL 1.1.0 and above provide WWW, XXX, YYY and ZZZ. TODO: fill in the pieces here and talk about changes.&lt;br /&gt;
&lt;br /&gt;
== HKDF key derivation ==&lt;br /&gt;
&lt;br /&gt;
The following program derives a key using HKDF from RFC 5869. HKDF was designed by Krawczyk and Eronen, and it is state of the art in expand-then-extract key derivation algorithms. It is usually a good choice when you need a KDF. The program below was taken from the OpenSSL man pages.&lt;br /&gt;
&lt;br /&gt;
HKDF takes three parameter:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;secret&amp;lt;/tt&amp;gt; - private information to use during derivation, like a password or passphrase. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_KEY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; - possibly public information to use during derivation. &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_SALT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; - additional, possibly public information to use during derivation. &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/evp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;openssl/kdf.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    EVP_KDF_CTX *kctx = NULL;&lt;br /&gt;
    unsigned char out[32];&lt;br /&gt;
&lt;br /&gt;
    kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF);&lt;br /&gt;
&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_MD&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, &amp;quot;salt&amp;quot;, (size_t)4) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_SALT&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, &amp;quot;secret&amp;quot;, (size_t)6) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_KEY&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO, &amp;quot;label&amp;quot;, (size_t)5) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_derive(kctx, out, sizeof(out)) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_derive&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Use the 32 bytes as a Key and IV */&lt;br /&gt;
    const unsigned char *key = out+0;&lt;br /&gt;
    const unsigned char  *iv = out+16;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;Key: &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, key[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;IV:  &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, iv[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    EVP_KDF_CTX_free(kctx);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can compile the program using C99 with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ gcc -std=c99 test.c -o test.exe -l:libcrypto.a -pthread -ldl&lt;br /&gt;
openssl$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Running the program results in the following output.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./test.exe&lt;br /&gt;
Key: 2a c4 36 9f 52 59 96 f8 de 13 73 1f 56 22 4f 34&lt;br /&gt;
IV:  df 0e 4c 96 ca a9 3b fd ec cf 23 7b 50 39 c8 db&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2789</id>
		<title>EVP Key Derivation</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Key_Derivation&amp;diff=2789"/>
		<updated>2019-07-11T01:17:17Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add KDF example; stop redirect to Key Agreement page.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Key derivation is the process of deriving one or more secret keys from a secret value such as a password or a passphrase. Several key derivation algoirthms have been standardized, and they are usually referred to a Key Derivation Functions (KDFs). KDFs include PBKDF2 from RFC 2898, HKDF form RFC 5869 and Scrypt from RFC 7914. OpenSSL provides PBKDF2, Scrypt, HKDF, ANSI X9.42 and ANSI X9.63 by way of &amp;lt;tt&amp;gt;EVP_KDF&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Not all key derivation functions are available in all versions of OpenSSL. OpenSSL 1.0.2 and below provide WWW, XXX, YYY and ZZZ. OpenSSL 1.1.0 and above provide WWW, XXX, YYY and ZZZ. TODO: fill in the pieces here and talk about changes.&lt;br /&gt;
&lt;br /&gt;
== HKDF key derivation ==&lt;br /&gt;
&lt;br /&gt;
The following program derives a key using HKDF from RFC 5869. HKDF was designed by Krawczyk and Eronen, and it is state of the art in expand-then-extract key derivation algorithms. It is usually a good choice when you need a KDF. The program below was taken from the OpenSSL man pages.&lt;br /&gt;
&lt;br /&gt;
HKDF takes three parameter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;secret&amp;lt;/tt&amp;gt; - private information to use during derivation, like a password or passphrase. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_KEY&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; - possibly public information to use during derivation. &amp;lt;tt&amp;gt;salt&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_SET_SALT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; - additional, possibly public information to use during derivation. &amp;lt;tt&amp;gt;info&amp;lt;/tt&amp;gt; is optional. The parameter is set using &amp;lt;tt&amp;gt;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;openssl/evp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;openssl/kdf.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    EVP_KDF_CTX *kctx = NULL;&lt;br /&gt;
    unsigned char out[32];&lt;br /&gt;
&lt;br /&gt;
    kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF);&lt;br /&gt;
&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_MD&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, &amp;quot;salt&amp;quot;, (size_t)4) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_SALT&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, &amp;quot;secret&amp;quot;, (size_t)6) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_SET_KEY&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO, &amp;quot;label&amp;quot;, (size_t)5) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_CTRL_ADD_HKDF_INFO&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (EVP_KDF_derive(kctx, out, sizeof(out)) &amp;lt;= 0) {&lt;br /&gt;
        error(&amp;quot;EVP_KDF_derive&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* Use the 32 bytes as a Key and IV */&lt;br /&gt;
    const unsigned char *key = out+0;&lt;br /&gt;
    const unsigned char  *iv = out+16;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;Key: &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, key[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;IV:  &amp;quot;);&lt;br /&gt;
    for (size_t i=0; i&amp;lt;16; ++i)&lt;br /&gt;
        printf(&amp;quot;%02x &amp;quot;, iv[i]);&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    EVP_KDF_CTX_free(kctx);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can compile the program using C99 with the following command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ gcc -std=c99 test.c -o test.exe -l:libcrypto.a -pthread -ldl&lt;br /&gt;
openssl$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Running the program results in the following output.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./test.exe&lt;br /&gt;
Key: 2a c4 36 9f 52 59 96 f8 de 13 73 1f 56 22 4f 34&lt;br /&gt;
IV:  df 0e 4c 96 ca a9 3b fd ec cf 23 7b 50 39 c8 db&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Symmetric_Encryption_and_Decryption&amp;diff=2787</id>
		<title>EVP Symmetric Encryption and Decryption</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Symmetric_Encryption_and_Decryption&amp;diff=2787"/>
		<updated>2019-07-04T21:59:59Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Whitespace.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DocInclude&lt;br /&gt;
|Name=Symmetric Encryption and Decryption&lt;br /&gt;
|Url=http://wiki.openssl.org/index.php/Manual:Evp(3)&lt;br /&gt;
|Include=evp.h}}&lt;br /&gt;
&lt;br /&gt;
The [[Libcrypto API|libcrypto]] library within OpenSSL provides functions for performing symmetric encryption and decryption operations across a wide range of algorithms and modes. This page walks you through the basics of performing a simple encryption and corresponding decryption operation.&lt;br /&gt;
&lt;br /&gt;
In order to perform encryption/decryption you need to know:&lt;br /&gt;
* Your algorithm&lt;br /&gt;
* Your mode&lt;br /&gt;
* Your key&lt;br /&gt;
* Your Initialisation Vector (IV)&lt;br /&gt;
&lt;br /&gt;
This page assumes that you know what all of these things mean. If you don't then please refer to [[Basics of Encryption]].&lt;br /&gt;
&lt;br /&gt;
The complete source code of the following example can be downloaded as [[Media:evp-symmetric-encrypt.c|evp-symmetric-encrypt.c]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Setting it up==&lt;br /&gt;
&lt;br /&gt;
The code below sets up the program. In this example we are going to take a simple message (&amp;quot;The quick brown fox jumps over the lazy dog&amp;quot;), and then encrypt it using a predefined key and IV. In this example the key and IV have been hard coded in - in a real situation you would never do this! Following encryption we will then decrypt the resulting ciphertext, and (hopefully!) end up with the message we first started with. This program expects two functions to be defined: &amp;quot;encrypt&amp;quot; and &amp;quot;decrypt&amp;quot;. We will define those further down the page. Note that this uses the auto-init facility in 1.1.0.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;openssl/conf.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;openssl/evp.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;openssl/err.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 int main (void)&lt;br /&gt;
 {&lt;br /&gt;
     /*&lt;br /&gt;
      * Set up the key and iv. Do I need to say to not hard code these in a&lt;br /&gt;
      * real application? :-)&lt;br /&gt;
      */&lt;br /&gt;
 &lt;br /&gt;
     /* A 256 bit key */&lt;br /&gt;
     unsigned char *key = (unsigned char *)&amp;quot;01234567890123456789012345678901&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     /* A 128 bit IV */&lt;br /&gt;
     unsigned char *iv = (unsigned char *)&amp;quot;0123456789012345&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     /* Message to be encrypted */&lt;br /&gt;
     unsigned char *plaintext =&lt;br /&gt;
         (unsigned char *)&amp;quot;The quick brown fox jumps over the lazy dog&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Buffer for ciphertext. Ensure the buffer is long enough for the&lt;br /&gt;
      * ciphertext which may be longer than the plaintext, depending on the&lt;br /&gt;
      * algorithm and mode.&lt;br /&gt;
      */&lt;br /&gt;
     unsigned char ciphertext[128];&lt;br /&gt;
 &lt;br /&gt;
     /* Buffer for the decrypted text */&lt;br /&gt;
     unsigned char decryptedtext[128];&lt;br /&gt;
 &lt;br /&gt;
     int decryptedtext_len, ciphertext_len;&lt;br /&gt;
 &lt;br /&gt;
     /* Encrypt the plaintext */&lt;br /&gt;
     ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv,&lt;br /&gt;
                               ciphertext);&lt;br /&gt;
 &lt;br /&gt;
     /* Do something useful with the ciphertext here */&lt;br /&gt;
     printf(&amp;quot;Ciphertext is:\n&amp;quot;);&lt;br /&gt;
     BIO_dump_fp (stdout, (const char *)ciphertext, ciphertext_len);&lt;br /&gt;
 &lt;br /&gt;
     /* Decrypt the ciphertext */&lt;br /&gt;
     decryptedtext_len = decrypt(ciphertext, ciphertext_len, key, iv,&lt;br /&gt;
                                 decryptedtext);&lt;br /&gt;
 &lt;br /&gt;
     /* Add a NULL terminator. We are expecting printable text */&lt;br /&gt;
     decryptedtext[decryptedtext_len] = '\0';&lt;br /&gt;
 &lt;br /&gt;
     /* Show the decrypted text */&lt;br /&gt;
     printf(&amp;quot;Decrypted text is:\n&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;%s\n&amp;quot;, decryptedtext);&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The program sets up a 256 bit key and a 128 bit IV. This is appropriate for the 256-bit AES encryption that we going to be doing in CBC mode. Make sure you use the right key and IV length for the cipher you have selected, or it will go horribly wrong!! The IV should be random for CBC mode.&lt;br /&gt;
&lt;br /&gt;
We've also set up a buffer for the ciphertext to be placed in. It is important to ensure that this buffer is sufficiently large for the expected ciphertext or you may see a program crash (or potentially introduce a security vulnerability into your code). Note: The ciphertext may be longer than the plaintext (e.g. if padding is being used).&lt;br /&gt;
&lt;br /&gt;
We're also going to need a helper function to handle any errors. This will simply dump any error messages from the OpenSSL error stack to the screen, and then abort the program.&lt;br /&gt;
&lt;br /&gt;
 void handleErrors(void)&lt;br /&gt;
 {&lt;br /&gt;
     ERR_print_errors_fp(stderr);&lt;br /&gt;
     abort();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Encrypting the message==&lt;br /&gt;
&lt;br /&gt;
So now that we have set up the program we need to define the &amp;quot;encrypt&amp;quot; function. This will take as parameters the plaintext, the length of the plaintext, the key to be used, and the IV. We'll also take in a buffer to put the ciphertext in (which we assume to be long enough), and will return the length of the ciphertext that we have written.&lt;br /&gt;
&lt;br /&gt;
Encrypting consists of the following stages:&lt;br /&gt;
* Setting up a context&lt;br /&gt;
* Initialising the encryption operation&lt;br /&gt;
* Providing plaintext bytes to be encrypted&lt;br /&gt;
* Finalising the encryption operation&lt;br /&gt;
&lt;br /&gt;
During initialisation we will provide an EVP_CIPHER object. In this case we are using EVP_aes_256_cbc(), which uses the AES algorithm with a 256-bit key in [[CBC]] mode. Refer to [[EVP#Working with Algorithms and Modes|Working with Algorithms and Modes]] for further details.&lt;br /&gt;
&lt;br /&gt;
 int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,&lt;br /&gt;
             unsigned char *iv, unsigned char *ciphertext)&lt;br /&gt;
 {&lt;br /&gt;
     EVP_CIPHER_CTX *ctx;&lt;br /&gt;
 &lt;br /&gt;
     int len;&lt;br /&gt;
 &lt;br /&gt;
     int ciphertext_len;&lt;br /&gt;
 &lt;br /&gt;
     /* Create and initialise the context */&lt;br /&gt;
     if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Initialise the encryption operation. IMPORTANT - ensure you use a key&lt;br /&gt;
      * and IV size appropriate for your cipher&lt;br /&gt;
      * In this example we are using 256 bit AES (i.e. a 256 bit key). The&lt;br /&gt;
      * IV size for *most* modes is the same as the block size. For AES this&lt;br /&gt;
      * is 128 bits&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Provide the message to be encrypted, and obtain the encrypted output.&lt;br /&gt;
      * EVP_EncryptUpdate can be called multiple times if necessary&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_EncryptUpdate(ctx, ciphertext, &amp;amp;len, plaintext, plaintext_len))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
     ciphertext_len = len;&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Finalise the encryption. Further ciphertext bytes may be written at&lt;br /&gt;
      * this stage.&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &amp;amp;len))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
     ciphertext_len += len;&lt;br /&gt;
 &lt;br /&gt;
     /* Clean up */&lt;br /&gt;
     EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
 &lt;br /&gt;
     return ciphertext_len;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Decrypting the Message==&lt;br /&gt;
&lt;br /&gt;
Finally we need to define the &amp;quot;decrypt&amp;quot; operation. This is very similar to encryption and consists of the following stages:&lt;br /&gt;
Decrypting consists of the following stages:&lt;br /&gt;
* Setting up a context&lt;br /&gt;
* Initialising the decryption operation&lt;br /&gt;
* Providing ciphertext bytes to be decrypted&lt;br /&gt;
* Finalising the decryption operation&lt;br /&gt;
&lt;br /&gt;
Again through the parameters we will receive the ciphertext to be decrypted, the length of the ciphertext, the key and the IV. We'll also receive a buffer to place the decrypted text into, and return the length of the plaintext we have found.&lt;br /&gt;
&lt;br /&gt;
Note that we have passed the length of the ciphertext. This is required as you cannot use functions such as &amp;quot;strlen&amp;quot; on this data - its binary! Similarly, even though in this example our plaintext really is ASCII text, OpenSSL does not know that. In spite of the name plaintext could be binary data, and therefore no NULL terminator will be put on the end (unless you encrypt the NULL as well of course).&lt;br /&gt;
&lt;br /&gt;
Here is the decrypt function:&lt;br /&gt;
&lt;br /&gt;
 int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,&lt;br /&gt;
             unsigned char *iv, unsigned char *plaintext)&lt;br /&gt;
 {&lt;br /&gt;
     EVP_CIPHER_CTX *ctx;&lt;br /&gt;
 &lt;br /&gt;
     int len;&lt;br /&gt;
 &lt;br /&gt;
     int plaintext_len;&lt;br /&gt;
 &lt;br /&gt;
     /* Create and initialise the context */&lt;br /&gt;
     if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Initialise the decryption operation. IMPORTANT - ensure you use a key&lt;br /&gt;
      * and IV size appropriate for your cipher&lt;br /&gt;
      * In this example we are using 256 bit AES (i.e. a 256 bit key). The&lt;br /&gt;
      * IV size for *most* modes is the same as the block size. For AES this&lt;br /&gt;
      * is 128 bits&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Provide the message to be decrypted, and obtain the plaintext output.&lt;br /&gt;
      * EVP_DecryptUpdate can be called multiple times if necessary.&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_DecryptUpdate(ctx, plaintext, &amp;amp;len, ciphertext, ciphertext_len))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
     plaintext_len = len;&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Finalise the decryption. Further plaintext bytes may be written at&lt;br /&gt;
      * this stage.&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &amp;amp;len))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
     plaintext_len += len;&lt;br /&gt;
 &lt;br /&gt;
     /* Clean up */&lt;br /&gt;
     EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
 &lt;br /&gt;
     return plaintext_len;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Ciphertext Output==&lt;br /&gt;
&lt;br /&gt;
If all goes well you should end up with output that looks like the following:&lt;br /&gt;
 Ciphertext is:&lt;br /&gt;
 0000 - e0 6f 63 a7 11 e8 b7 aa-9f 94 40 10 7d 46 80 a1   .oc.......@.}F..&lt;br /&gt;
 0010 - 17 99 43 80 ea 31 d2 a2-99 b9 53 02 d4 39 b9 70   ..C..1....S..9.p&lt;br /&gt;
 0020 - 2c 8e 65 a9 92 36 ec 92-07 04 91 5c f1 a9 8a 44   ,.e..6.....\...D&lt;br /&gt;
 Decrypted text is:&lt;br /&gt;
 The quick brown fox jumps over the lazy dog&lt;br /&gt;
&lt;br /&gt;
For further details about symmetric encryption and decryption operations refer to the OpenSSL documentation [[Manual:EVP_EncryptInit(3)]].&lt;br /&gt;
&lt;br /&gt;
==Padding==&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses PKCS padding by default. If the mode you are using allows you to change the padding, then you can change it with &amp;lt;tt&amp;gt;[http://www.openssl.org/docs/man1.0.2/crypto/EVP_CIPHER_CTX_set_padding.html EVP_CIPHER_CTX_set_padding]&amp;lt;/tt&amp;gt;. From the man page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;EVP_CIPHER_CTX_set_padding() enables or disables padding. By default encryption operations are padded using standard block padding and the padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur...&lt;br /&gt;
&lt;br /&gt;
PKCS padding works by adding n padding bytes of value n to make the total length of the encrypted data a multiple of the block size. Padding is always added so if the data is already a multiple of the block size n will equal the block size. For example if the block size is 8 and 11 bytes are to be encrypted then 5 padding bytes of value 5 will be added...&lt;br /&gt;
&lt;br /&gt;
If padding is disabled then the decryption operation will only succeed if the total amount of data decrypted is a multiple of the block size.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Programs==&lt;br /&gt;
&lt;br /&gt;
Questions regarding how to use the EVP interfaces from a C++ program arise on occasion. Generally speaking, using the EVP interfaces from a C++ program is the same as using them from a C program.&lt;br /&gt;
&lt;br /&gt;
You can download a sample program using EVP symmetric encryption and C++11 called [[Media:Evp-encrypt-cxx.tar.gz|evp-encrypt.cxx]]. The sample uses a custom allocator to zeroize memory, C++ smart pointers to manage resources, and provides a &amp;lt;tt&amp;gt;secure_string&amp;lt;/tt&amp;gt; using &amp;lt;tt&amp;gt;basic_string&amp;lt;/tt&amp;gt; and the custom allocator. You need to use &amp;lt;tt&amp;gt;g++ -std=c++11 ...&amp;lt;/tt&amp;gt; to compile it because of &amp;lt;tt&amp;gt;std::unique_ptr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should also ensure you configure an build with &amp;lt;tt&amp;gt;-fexception&amp;lt;/tt&amp;gt; to ensure C++ exceptions pass as expected through C code. And you should avoid other flags, like &amp;lt;tt&amp;gt;-fno-exceptions&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-fno-rtti&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The program's &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; simply encrypts and decrypts a string using AES-256 in CBC mode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;typedef unsigned char byte;&lt;br /&gt;
typedef std::basic_string&amp;lt;char, std::char_traits&amp;lt;char&amp;gt;, zallocator&amp;lt;char&amp;gt; &amp;gt; secure_string;&lt;br /&gt;
using EVP_CIPHER_CTX_ptr = std::unique_ptr&amp;lt;EVP_CIPHER_CTX, decltype(&amp;amp;::EVP_CIPHER_CTX_free)&amp;gt;;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    // Load the necessary cipher&lt;br /&gt;
    EVP_add_cipher(EVP_aes_256_cbc());&lt;br /&gt;
&lt;br /&gt;
    // plaintext, ciphertext, recovered text&lt;br /&gt;
    secure_string ptext = &amp;quot;Yoda said, Do or do not. There is no try.&amp;quot;;&lt;br /&gt;
    secure_string ctext, rtext;&lt;br /&gt;
&lt;br /&gt;
    byte key[KEY_SIZE], iv[BLOCK_SIZE];&lt;br /&gt;
    gen_params(key, iv);&lt;br /&gt;
  &lt;br /&gt;
    aes_encrypt(key, iv, ptext, ctext);&lt;br /&gt;
    aes_decrypt(key, iv, ctext, rtext);&lt;br /&gt;
    &lt;br /&gt;
    OPENSSL_cleanse(key, KEY_SIZE);&lt;br /&gt;
    OPENSSL_cleanse(iv, BLOCK_SIZE);&lt;br /&gt;
&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Original message:\n&amp;quot; &amp;lt;&amp;lt; ptext &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Recovered message:\n&amp;quot; &amp;lt;&amp;lt; rtext &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the encryption routine is as follows. The decryption routine is similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;void aes_encrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const secure_string&amp;amp; ptext, secure_string&amp;amp; ctext)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX_ptr ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);&lt;br /&gt;
    int rc = EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_cbc(), NULL, key, iv);&lt;br /&gt;
    if (rc != 1)&lt;br /&gt;
      throw std::runtime_error(&amp;quot;EVP_EncryptInit_ex failed&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Cipher text expands upto BLOCK_SIZE&lt;br /&gt;
    ctext.resize(ptext.size()+BLOCK_SIZE);&lt;br /&gt;
    int out_len1 = (int)ctext.size();&lt;br /&gt;
&lt;br /&gt;
    rc = EVP_EncryptUpdate(ctx.get(), (byte*)&amp;amp;ctext[0], &amp;amp;out_len1, (const byte*)&amp;amp;ptext[0], (int)ptext.size());&lt;br /&gt;
    if (rc != 1)&lt;br /&gt;
      throw std::runtime_error(&amp;quot;EVP_EncryptUpdate failed&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
    int out_len2 = (int)ctext.size() - out_len1;&lt;br /&gt;
    rc = EVP_EncryptFinal_ex(ctx.get(), (byte*)&amp;amp;ctext[0]+out_len1, &amp;amp;out_len2);&lt;br /&gt;
    if (rc != 1)&lt;br /&gt;
      throw std::runtime_error(&amp;quot;EVP_EncryptFinal_ex failed&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Set cipher text size now that we know it&lt;br /&gt;
    ctext.resize(out_len1 + out_len2);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Notes on some unusual modes==&lt;br /&gt;
&lt;br /&gt;
Worthy of mention here is the [[XTS]] mode (e.g. EVP_aes_256_xts()). This works in exactly the same way as shown above, except that the &amp;quot;tweak&amp;quot; is provided in the IV parameter. A further &amp;quot;gotcha&amp;quot; is that XTS mode expects a key which is twice as long as normal. Therefore EVP_aes_256_xts() expects a key which is 512-bits long.&lt;br /&gt;
&lt;br /&gt;
Authenticated encryption modes ([[GCM]] or [[CCM]]) work in essentially the same way as shown above but require some special handling. See [[EVP Authenticated Encryption and Decryption]] for further details.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[EVP]]&lt;br /&gt;
* [[Libcrypto API]]&lt;br /&gt;
* [[EVP Authenticated Encryption and Decryption]]&lt;br /&gt;
* [[EVP Asymmetric Encryption and Decryption of an Envelope]]&lt;br /&gt;
* [[EVP Signing and Verifying]]&lt;br /&gt;
* [[EVP Message Digests]]&lt;br /&gt;
* [[EVP Key Agreement]]&lt;br /&gt;
* [[EVP Key and Parameter Generation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Crypto API]]&lt;br /&gt;
[[Category:C level]]&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Symmetric_Encryption_and_Decryption&amp;diff=2786</id>
		<title>EVP Symmetric Encryption and Decryption</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Symmetric_Encryption_and_Decryption&amp;diff=2786"/>
		<updated>2019-07-04T21:40:28Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Cleanup link.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DocInclude&lt;br /&gt;
|Name=Symmetric Encryption and Decryption&lt;br /&gt;
|Url=http://wiki.openssl.org/index.php/Manual:Evp(3)&lt;br /&gt;
|Include=evp.h}}&lt;br /&gt;
&lt;br /&gt;
The [[Libcrypto API|libcrypto]] library within OpenSSL provides functions for performing symmetric encryption and decryption operations across a wide range of algorithms and modes. This page walks you through the basics of performing a simple encryption and corresponding decryption operation.&lt;br /&gt;
&lt;br /&gt;
In order to perform encryption/decryption you need to know:&lt;br /&gt;
* Your algorithm&lt;br /&gt;
* Your mode&lt;br /&gt;
* Your key&lt;br /&gt;
* Your Initialisation Vector (IV)&lt;br /&gt;
&lt;br /&gt;
This page assumes that you know what all of these things mean. If you don't then please refer to [[Basics of Encryption]].&lt;br /&gt;
&lt;br /&gt;
The complete source code of the following example can be downloaded as [[Media:evp-symmetric-encrypt.c|evp-symmetric-encrypt.c]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Setting it up==&lt;br /&gt;
&lt;br /&gt;
The code below sets up the program. In this example we are going to take a simple message (&amp;quot;The quick brown fox jumps over the lazy dog&amp;quot;), and then encrypt it using a predefined key and IV. In this example the key and IV have been hard coded in - in a real situation you would never do this! Following encryption we will then decrypt the resulting ciphertext, and (hopefully!) end up with the message we first started with. This program expects two functions to be defined: &amp;quot;encrypt&amp;quot; and &amp;quot;decrypt&amp;quot;. We will define those further down the page. Note that this uses the auto-init facility in 1.1.0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;openssl/conf.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;openssl/evp.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;openssl/err.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 int main (void)&lt;br /&gt;
 {&lt;br /&gt;
     /*&lt;br /&gt;
      * Set up the key and iv. Do I need to say to not hard code these in a&lt;br /&gt;
      * real application? :-)&lt;br /&gt;
      */&lt;br /&gt;
 &lt;br /&gt;
     /* A 256 bit key */&lt;br /&gt;
     unsigned char *key = (unsigned char *)&amp;quot;01234567890123456789012345678901&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     /* A 128 bit IV */&lt;br /&gt;
     unsigned char *iv = (unsigned char *)&amp;quot;0123456789012345&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     /* Message to be encrypted */&lt;br /&gt;
     unsigned char *plaintext =&lt;br /&gt;
         (unsigned char *)&amp;quot;The quick brown fox jumps over the lazy dog&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Buffer for ciphertext. Ensure the buffer is long enough for the&lt;br /&gt;
      * ciphertext which may be longer than the plaintext, depending on the&lt;br /&gt;
      * algorithm and mode.&lt;br /&gt;
      */&lt;br /&gt;
     unsigned char ciphertext[128];&lt;br /&gt;
 &lt;br /&gt;
     /* Buffer for the decrypted text */&lt;br /&gt;
     unsigned char decryptedtext[128];&lt;br /&gt;
 &lt;br /&gt;
     int decryptedtext_len, ciphertext_len;&lt;br /&gt;
 &lt;br /&gt;
     /* Encrypt the plaintext */&lt;br /&gt;
     ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv,&lt;br /&gt;
                               ciphertext);&lt;br /&gt;
 &lt;br /&gt;
     /* Do something useful with the ciphertext here */&lt;br /&gt;
     printf(&amp;quot;Ciphertext is:\n&amp;quot;);&lt;br /&gt;
     BIO_dump_fp (stdout, (const char *)ciphertext, ciphertext_len);&lt;br /&gt;
 &lt;br /&gt;
     /* Decrypt the ciphertext */&lt;br /&gt;
     decryptedtext_len = decrypt(ciphertext, ciphertext_len, key, iv,&lt;br /&gt;
                                 decryptedtext);&lt;br /&gt;
 &lt;br /&gt;
     /* Add a NULL terminator. We are expecting printable text */&lt;br /&gt;
     decryptedtext[decryptedtext_len] = '\0';&lt;br /&gt;
 &lt;br /&gt;
     /* Show the decrypted text */&lt;br /&gt;
     printf(&amp;quot;Decrypted text is:\n&amp;quot;);&lt;br /&gt;
     printf(&amp;quot;%s\n&amp;quot;, decryptedtext);&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
     return 0;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The program sets up a 256 bit key and a 128 bit IV. This is appropriate for the 256-bit AES encryption that we going to be doing in CBC mode. Make sure you use the right key and IV length for the cipher you have selected, or it will go horribly wrong!! The IV should be random for CBC mode.&lt;br /&gt;
&lt;br /&gt;
We've also set up a buffer for the ciphertext to be placed in. It is important to ensure that this buffer is sufficiently large for the expected ciphertext or you may see a program crash (or potentially introduce a security vulnerability into your code). Note: The ciphertext may be longer than the plaintext (e.g. if padding is being used).&lt;br /&gt;
&lt;br /&gt;
We're also going to need a helper function to handle any errors. This will simply dump any error messages from the OpenSSL error stack to the screen, and then abort the program.&lt;br /&gt;
&lt;br /&gt;
 void handleErrors(void)&lt;br /&gt;
 {&lt;br /&gt;
     ERR_print_errors_fp(stderr);&lt;br /&gt;
     abort();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Encrypting the message==&lt;br /&gt;
&lt;br /&gt;
So now that we have set up the program we need to define the &amp;quot;encrypt&amp;quot; function. This will take as parameters the plaintext, the length of the plaintext, the key to be used, and the IV. We'll also take in a buffer to put the ciphertext in (which we assume to be long enough), and will return the length of the ciphertext that we have written.&lt;br /&gt;
&lt;br /&gt;
Encrypting consists of the following stages:&lt;br /&gt;
* Setting up a context&lt;br /&gt;
* Initialising the encryption operation&lt;br /&gt;
* Providing plaintext bytes to be encrypted&lt;br /&gt;
* Finalising the encryption operation&lt;br /&gt;
&lt;br /&gt;
During initialisation we will provide an EVP_CIPHER object. In this case we are using EVP_aes_256_cbc(), which uses the AES algorithm with a 256-bit key in [[CBC]] mode. Refer to [[EVP#Working with Algorithms and Modes|Working with Algorithms and Modes]] for further details.&lt;br /&gt;
&lt;br /&gt;
 int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,&lt;br /&gt;
             unsigned char *iv, unsigned char *ciphertext)&lt;br /&gt;
 {&lt;br /&gt;
     EVP_CIPHER_CTX *ctx;&lt;br /&gt;
 &lt;br /&gt;
     int len;&lt;br /&gt;
 &lt;br /&gt;
     int ciphertext_len;&lt;br /&gt;
 &lt;br /&gt;
     /* Create and initialise the context */&lt;br /&gt;
     if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Initialise the encryption operation. IMPORTANT - ensure you use a key&lt;br /&gt;
      * and IV size appropriate for your cipher&lt;br /&gt;
      * In this example we are using 256 bit AES (i.e. a 256 bit key). The&lt;br /&gt;
      * IV size for *most* modes is the same as the block size. For AES this&lt;br /&gt;
      * is 128 bits&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Provide the message to be encrypted, and obtain the encrypted output.&lt;br /&gt;
      * EVP_EncryptUpdate can be called multiple times if necessary&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_EncryptUpdate(ctx, ciphertext, &amp;amp;len, plaintext, plaintext_len))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
     ciphertext_len = len;&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Finalise the encryption. Further ciphertext bytes may be written at&lt;br /&gt;
      * this stage.&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &amp;amp;len))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
     ciphertext_len += len;&lt;br /&gt;
 &lt;br /&gt;
     /* Clean up */&lt;br /&gt;
     EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
 &lt;br /&gt;
     return ciphertext_len;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Decrypting the Message==&lt;br /&gt;
&lt;br /&gt;
Finally we need to define the &amp;quot;decrypt&amp;quot; operation. This is very similar to encryption and consists of the following stages:&lt;br /&gt;
Decrypting consists of the following stages:&lt;br /&gt;
* Setting up a context&lt;br /&gt;
* Initialising the decryption operation&lt;br /&gt;
* Providing ciphertext bytes to be decrypted&lt;br /&gt;
* Finalising the decryption operation&lt;br /&gt;
&lt;br /&gt;
Again through the parameters we will receive the ciphertext to be decrypted, the length of the ciphertext, the key and the IV. We'll also receive a buffer to place the decrypted text into, and return the length of the plaintext we have found.&lt;br /&gt;
&lt;br /&gt;
Note that we have passed the length of the ciphertext. This is required as you cannot use functions such as &amp;quot;strlen&amp;quot; on this data - its binary! Similarly, even though in this example our plaintext really is ASCII text, OpenSSL does not know that. In spite of the name plaintext could be binary data, and therefore no NULL terminator will be put on the end (unless you encrypt the NULL as well of course).&lt;br /&gt;
&lt;br /&gt;
Here is the decrypt function:&lt;br /&gt;
&lt;br /&gt;
 int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,&lt;br /&gt;
             unsigned char *iv, unsigned char *plaintext)&lt;br /&gt;
 {&lt;br /&gt;
     EVP_CIPHER_CTX *ctx;&lt;br /&gt;
 &lt;br /&gt;
     int len;&lt;br /&gt;
 &lt;br /&gt;
     int plaintext_len;&lt;br /&gt;
 &lt;br /&gt;
     /* Create and initialise the context */&lt;br /&gt;
     if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Initialise the decryption operation. IMPORTANT - ensure you use a key&lt;br /&gt;
      * and IV size appropriate for your cipher&lt;br /&gt;
      * In this example we are using 256 bit AES (i.e. a 256 bit key). The&lt;br /&gt;
      * IV size for *most* modes is the same as the block size. For AES this&lt;br /&gt;
      * is 128 bits&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Provide the message to be decrypted, and obtain the plaintext output.&lt;br /&gt;
      * EVP_DecryptUpdate can be called multiple times if necessary.&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_DecryptUpdate(ctx, plaintext, &amp;amp;len, ciphertext, ciphertext_len))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
     plaintext_len = len;&lt;br /&gt;
 &lt;br /&gt;
     /*&lt;br /&gt;
      * Finalise the decryption. Further plaintext bytes may be written at&lt;br /&gt;
      * this stage.&lt;br /&gt;
      */&lt;br /&gt;
     if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &amp;amp;len))&lt;br /&gt;
         handleErrors();&lt;br /&gt;
     plaintext_len += len;&lt;br /&gt;
 &lt;br /&gt;
     /* Clean up */&lt;br /&gt;
     EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
 &lt;br /&gt;
     return plaintext_len;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Ciphertext Output==&lt;br /&gt;
&lt;br /&gt;
If all goes well you should end up with output that looks like the following:&lt;br /&gt;
 Ciphertext is:&lt;br /&gt;
 0000 - e0 6f 63 a7 11 e8 b7 aa-9f 94 40 10 7d 46 80 a1   .oc.......@.}F..&lt;br /&gt;
 0010 - 17 99 43 80 ea 31 d2 a2-99 b9 53 02 d4 39 b9 70   ..C..1....S..9.p&lt;br /&gt;
 0020 - 2c 8e 65 a9 92 36 ec 92-07 04 91 5c f1 a9 8a 44   ,.e..6.....\...D&lt;br /&gt;
 Decrypted text is:&lt;br /&gt;
 The quick brown fox jumps over the lazy dog&lt;br /&gt;
&lt;br /&gt;
For further details about symmetric encryption and decryption operations refer to the OpenSSL documentation [[Manual:EVP_EncryptInit(3)]].&lt;br /&gt;
&lt;br /&gt;
==Padding==&lt;br /&gt;
&lt;br /&gt;
OpenSSL uses PKCS padding by default. If the mode you are using allows you to change the padding, then you can change it with &amp;lt;tt&amp;gt;[http://www.openssl.org/docs/man1.0.2/crypto/EVP_CIPHER_CTX_set_padding.html EVP_CIPHER_CTX_set_padding]&amp;lt;/tt&amp;gt;. From the man page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;EVP_CIPHER_CTX_set_padding() enables or disables padding. By default encryption operations are padded using standard block padding and the padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur...&lt;br /&gt;
&lt;br /&gt;
PKCS padding works by adding n padding bytes of value n to make the total length of the encrypted data a multiple of the block size. Padding is always added so if the data is already a multiple of the block size n will equal the block size. For example if the block size is 8 and 11 bytes are to be encrypted then 5 padding bytes of value 5 will be added...&lt;br /&gt;
&lt;br /&gt;
If padding is disabled then the decryption operation will only succeed if the total amount of data decrypted is a multiple of the block size.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==C++ Programs==&lt;br /&gt;
&lt;br /&gt;
Questions regarding how to use the EVP interfaces from a C++ program arise on occasion. Generally speaking, using the EVP interfaces from a C++ program is the same as using them from a C program.&lt;br /&gt;
&lt;br /&gt;
You can download a sample program using EVP symmetric encryption and C++11 called [[Media:Evp-encrypt-cxx.tar.gz|evp-encrypt.cxx]]. The sample uses a custom allocator to zeroize memory, C++ smart pointers to manage resources, and provides a &amp;lt;tt&amp;gt;secure_string&amp;lt;/tt&amp;gt; using &amp;lt;tt&amp;gt;basic_string&amp;lt;/tt&amp;gt; and the custom allocator. You need to use &amp;lt;tt&amp;gt;g++ -std=c++11 ...&amp;lt;/tt&amp;gt; to compile it because of &amp;lt;tt&amp;gt;std::unique_ptr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You should also ensure you configure an build with &amp;lt;tt&amp;gt;-fexception&amp;lt;/tt&amp;gt; to ensure C++ exceptions pass as expected through C code. And you should avoid other flags, like &amp;lt;tt&amp;gt;-fno-exceptions&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-fno-rtti&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The program's &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; simply encrypts and decrypts a string using AES-256 in CBC mode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;typedef unsigned char byte;&lt;br /&gt;
typedef std::basic_string&amp;lt;char, std::char_traits&amp;lt;char&amp;gt;, zallocator&amp;lt;char&amp;gt; &amp;gt; secure_string;&lt;br /&gt;
using EVP_CIPHER_CTX_ptr = std::unique_ptr&amp;lt;EVP_CIPHER_CTX, decltype(&amp;amp;::EVP_CIPHER_CTX_free)&amp;gt;;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    // Load the necessary cipher&lt;br /&gt;
    EVP_add_cipher(EVP_aes_256_cbc());&lt;br /&gt;
&lt;br /&gt;
    // plaintext, ciphertext, recovered text&lt;br /&gt;
    secure_string ptext = &amp;quot;Yoda said, Do or do not. There is no try.&amp;quot;;&lt;br /&gt;
    secure_string ctext, rtext;&lt;br /&gt;
&lt;br /&gt;
    byte key[KEY_SIZE], iv[BLOCK_SIZE];&lt;br /&gt;
    gen_params(key, iv);&lt;br /&gt;
  &lt;br /&gt;
    aes_encrypt(key, iv, ptext, ctext);&lt;br /&gt;
    aes_decrypt(key, iv, ctext, rtext);&lt;br /&gt;
    &lt;br /&gt;
    OPENSSL_cleanse(key, KEY_SIZE);&lt;br /&gt;
    OPENSSL_cleanse(iv, BLOCK_SIZE);&lt;br /&gt;
&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Original message:\n&amp;quot; &amp;lt;&amp;lt; ptext &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; &amp;quot;Recovered message:\n&amp;quot; &amp;lt;&amp;lt; rtext &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the encryption routine is as follows. The decryption routine is similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;void aes_encrypt(const byte key[KEY_SIZE], const byte iv[BLOCK_SIZE], const secure_string&amp;amp; ptext, secure_string&amp;amp; ctext)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX_ptr ctx(EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);&lt;br /&gt;
    int rc = EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_cbc(), NULL, key, iv);&lt;br /&gt;
    if (rc != 1)&lt;br /&gt;
      throw std::runtime_error(&amp;quot;EVP_EncryptInit_ex failed&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Cipher text expands upto BLOCK_SIZE&lt;br /&gt;
    ctext.resize(ptext.size()+BLOCK_SIZE);&lt;br /&gt;
    int out_len1 = (int)ctext.size();&lt;br /&gt;
&lt;br /&gt;
    rc = EVP_EncryptUpdate(ctx.get(), (byte*)&amp;amp;ctext[0], &amp;amp;out_len1, (const byte*)&amp;amp;ptext[0], (int)ptext.size());&lt;br /&gt;
    if (rc != 1)&lt;br /&gt;
      throw std::runtime_error(&amp;quot;EVP_EncryptUpdate failed&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
    int out_len2 = (int)ctext.size() - out_len1;&lt;br /&gt;
    rc = EVP_EncryptFinal_ex(ctx.get(), (byte*)&amp;amp;ctext[0]+out_len1, &amp;amp;out_len2);&lt;br /&gt;
    if (rc != 1)&lt;br /&gt;
      throw std::runtime_error(&amp;quot;EVP_EncryptFinal_ex failed&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    // Set cipher text size now that we know it&lt;br /&gt;
    ctext.resize(out_len1 + out_len2);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Notes on some unusual modes==&lt;br /&gt;
&lt;br /&gt;
Worthy of mention here is the [[XTS]] mode (e.g. EVP_aes_256_xts()). This works in exactly the same way as shown above, except that the &amp;quot;tweak&amp;quot; is provided in the IV parameter. A further &amp;quot;gotcha&amp;quot; is that XTS mode expects a key which is twice as long as normal. Therefore EVP_aes_256_xts() expects a key which is 512-bits long.&lt;br /&gt;
&lt;br /&gt;
Authenticated encryption modes ([[GCM]] or [[CCM]]) work in essentially the same way as shown above but require some special handling. See [[EVP Authenticated Encryption and Decryption]] for further details.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[EVP]]&lt;br /&gt;
* [[Libcrypto API]]&lt;br /&gt;
* [[EVP Authenticated Encryption and Decryption]]&lt;br /&gt;
* [[EVP Asymmetric Encryption and Decryption of an Envelope]]&lt;br /&gt;
* [[EVP Signing and Verifying]]&lt;br /&gt;
* [[EVP Message Digests]]&lt;br /&gt;
* [[EVP Key Agreement]]&lt;br /&gt;
* [[EVP Key and Parameter Generation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Crypto API]]&lt;br /&gt;
[[Category:C level]]&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Authenticated_Encryption_and_Decryption&amp;diff=2785</id>
		<title>EVP Authenticated Encryption and Decryption</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Authenticated_Encryption_and_Decryption&amp;diff=2785"/>
		<updated>2019-06-05T04:48:04Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add additional information.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DocInclude&lt;br /&gt;
|Name=Authenticated Encryption and Decryption&lt;br /&gt;
|Url=http://wiki.openssl.org/index.php/Manual:Evp(3)&lt;br /&gt;
|Include=evp.h}}&lt;br /&gt;
&lt;br /&gt;
The EVP interface supports the ability to perform authenticated encryption and decryption, as well as the option to attach unencrypted, associated data to the message. Such Authenticated-Encryption with Associated-Data (AEAD) schemes provide confidentiality by encrypting the data, and also provide authenticity assurances by creating a MAC tag over the encrypted data. The MAC tag will ensure the data is not accidentally altered or maliciously tampered during transmission and storage.&lt;br /&gt;
&lt;br /&gt;
There are a number of AEAD modes of operation. The modes include EAX, CCM and GCM mode. Using AEAD modes is nearly identical to using standard symmetric encryption modes like CBC, CFB and OFB modes.&lt;br /&gt;
&lt;br /&gt;
As with standard symmetric encryption you will need to know the following:&lt;br /&gt;
&lt;br /&gt;
* Algorithm (currently only AES is supported)&lt;br /&gt;
* Mode (currently only GCM and CCM are supported)&lt;br /&gt;
* Key&lt;br /&gt;
* Initialisation Vector (IV)&lt;br /&gt;
&lt;br /&gt;
In addition you can (optionally) provide some ''Additional Authenticated Data'' (AAD). The AAD data is not encrypted, and is typically passed to the recipient in plaintext along with the ciphertext. An example of AAD is the IP address and port number in a IP header used with IPsec.&lt;br /&gt;
&lt;br /&gt;
The output from the encryption operation will be the ciphertext, and a tag. The tag is subsequently used during the decryption operation to ensure that the ciphertext and AAD have not been tampered with.&lt;br /&gt;
&lt;br /&gt;
The OpenSSL manual describes the usage of the GCM and CCM modes here: [[Manual:EVP_EncryptInit(3)#GCM_Mode]].&lt;br /&gt;
&lt;br /&gt;
The complete source code of the following examples can be downloaded as [[Media:evp-gcm-encrypt.c|evp-gcm-encrypt.c]] resp.  [[Media:evp-ccm-encrypt.c|evp-ccm-encrypt.c]].&lt;br /&gt;
&lt;br /&gt;
==Authenticated Encryption using GCM mode==&lt;br /&gt;
&lt;br /&gt;
Encryption is performed in much the same way as for symmetric encryption as described [[EVP Symmetric Encryption and Decryption|here]]. The main differences are:&lt;br /&gt;
* You may optionally pass through an IV length using EVP_CIPHER_CTX_ctrl&lt;br /&gt;
* AAD data is passed through in zero or more calls to EVP_EncryptUpdate, with the output buffer set to NULL&lt;br /&gt;
* Once private data has been added using EVP_EncryptUpdate (non-NULL output buffer), you cannot add AAD data &lt;br /&gt;
* After the EVP_EncryptFinal_ex call a new call to EVP_CIPHER_CTX_ctrl retrieves the tag&lt;br /&gt;
&lt;br /&gt;
See the code below for an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int gcm_encrypt(unsigned char *plaintext, int plaintext_len,&lt;br /&gt;
                unsigned char *aad, int aad_len,&lt;br /&gt;
                unsigned char *key,&lt;br /&gt;
                unsigned char *iv, int iv_len,&lt;br /&gt;
                unsigned char *ciphertext,&lt;br /&gt;
                unsigned char *tag)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX *ctx;&lt;br /&gt;
&lt;br /&gt;
    int len;&lt;br /&gt;
&lt;br /&gt;
    int ciphertext_len;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    /* Create and initialise the context */&lt;br /&gt;
    if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise the encryption operation. */&lt;br /&gt;
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Set IV length if default 12 bytes (96 bits) is not appropriate&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise key and IV */&lt;br /&gt;
    if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide any AAD data. This can be called zero or more times as&lt;br /&gt;
     * required&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, NULL, &amp;amp;len, aad, aad_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide the message to be encrypted, and obtain the encrypted output.&lt;br /&gt;
     * EVP_EncryptUpdate can be called multiple times if necessary&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &amp;amp;len, plaintext, plaintext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    ciphertext_len = len;&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Finalise the encryption. Normally ciphertext bytes may be written at&lt;br /&gt;
     * this stage, but this does not occur in GCM mode&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &amp;amp;len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    ciphertext_len += len;&lt;br /&gt;
&lt;br /&gt;
    /* Get the tag */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Clean up */&lt;br /&gt;
    EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
&lt;br /&gt;
    return ciphertext_len;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Authenticated Decryption using GCM mode==&lt;br /&gt;
&lt;br /&gt;
Again, the decryption operation is much the same as for normal symmetric decryption as described [[EVP Symmetric Encryption and Decryption|here]]. The main differences are:&lt;br /&gt;
* You may optionally pass through an IV length using EVP_CIPHER_CTX_ctrl&lt;br /&gt;
* AAD data is passed through in zero or more calls to EVP_DecryptUpdate, with the output buffer set to NULL&lt;br /&gt;
* Prior to the EVP_DecryptFinal_ex call a new call to EVP_CIPHER_CTX_ctrl provides the tag&lt;br /&gt;
* A non positive return value from EVP_DecryptFinal_ex should be considered as a failure to authenticate ciphertext and/or AAD. It does not necessarily indicate a more serious error.&lt;br /&gt;
&lt;br /&gt;
See the code example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len,&lt;br /&gt;
                unsigned char *aad, int aad_len,&lt;br /&gt;
                unsigned char *tag,&lt;br /&gt;
                unsigned char *key,&lt;br /&gt;
                unsigned char *iv, int iv_len,&lt;br /&gt;
                unsigned char *plaintext)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX *ctx;&lt;br /&gt;
    int len;&lt;br /&gt;
    int plaintext_len;&lt;br /&gt;
    int ret;&lt;br /&gt;
&lt;br /&gt;
    /* Create and initialise the context */&lt;br /&gt;
    if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise the decryption operation. */&lt;br /&gt;
    if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Set IV length. Not necessary if this is 12 bytes (96 bits) */&lt;br /&gt;
    if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise key and IV */&lt;br /&gt;
    if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide any AAD data. This can be called zero or more times as&lt;br /&gt;
     * required&lt;br /&gt;
     */&lt;br /&gt;
    if(!EVP_DecryptUpdate(ctx, NULL, &amp;amp;len, aad, aad_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide the message to be decrypted, and obtain the plaintext output.&lt;br /&gt;
     * EVP_DecryptUpdate can be called multiple times if necessary&lt;br /&gt;
     */&lt;br /&gt;
    if(!EVP_DecryptUpdate(ctx, plaintext, &amp;amp;len, ciphertext, ciphertext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    plaintext_len = len;&lt;br /&gt;
&lt;br /&gt;
    /* Set expected tag value. Works in OpenSSL 1.0.1d and later */&lt;br /&gt;
    if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Finalise the decryption. A positive return value indicates success,&lt;br /&gt;
     * anything else is a failure - the plaintext is not trustworthy.&lt;br /&gt;
     */&lt;br /&gt;
    ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &amp;amp;len);&lt;br /&gt;
&lt;br /&gt;
    /* Clean up */&lt;br /&gt;
    EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
&lt;br /&gt;
    if(ret &amp;gt; 0) {&lt;br /&gt;
        /* Success */&lt;br /&gt;
        plaintext_len += len;&lt;br /&gt;
        return plaintext_len;&lt;br /&gt;
    } else {&lt;br /&gt;
        /* Verify failed */&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Authenticated Encryption using CCM mode==&lt;br /&gt;
&lt;br /&gt;
Encryption with CCM mode is much the same as for encryption with GCM but with some additional things to bear in mind.&lt;br /&gt;
* you can only call EVP_EncryptUpdate once for AAD and once for the plaintext.&lt;br /&gt;
* The total plaintext length must be passed to EVP_EncryptUpdate (only needed if AAD is passed)&lt;br /&gt;
* Optionally the tag and IV length can also be passed. If they are not then the defaults are used (12 bytes for AES tags, and 7 bytes for AES IVs)&lt;br /&gt;
&lt;br /&gt;
See the code below for an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int ccm_encrypt(unsigned char *plaintext, int plaintext_len,&lt;br /&gt;
                unsigned char *aad, int aad_len,&lt;br /&gt;
                unsigned char *key,&lt;br /&gt;
                unsigned char *iv,&lt;br /&gt;
                unsigned char *ciphertext,&lt;br /&gt;
                unsigned char *tag)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX *ctx;&lt;br /&gt;
&lt;br /&gt;
    int len;&lt;br /&gt;
&lt;br /&gt;
    int ciphertext_len;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    /* Create and initialise the context */&lt;br /&gt;
    if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise the encryption operation. */&lt;br /&gt;
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Setting IV len to 7. Not strictly necessary as this is the default&lt;br /&gt;
     * but shown here for the purposes of this example.&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, 7, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Set tag length */&lt;br /&gt;
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, 14, NULL);&lt;br /&gt;
&lt;br /&gt;
    /* Initialise key and IV */&lt;br /&gt;
    if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Provide the total plaintext length */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, NULL, &amp;amp;len, NULL, plaintext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Provide any AAD data. This can be called zero or one times as required */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, NULL, &amp;amp;len, aad, aad_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide the message to be encrypted, and obtain the encrypted output.&lt;br /&gt;
     * EVP_EncryptUpdate can only be called once for this.&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &amp;amp;len, plaintext, plaintext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    ciphertext_len = len;&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Finalise the encryption. Normally ciphertext bytes may be written at&lt;br /&gt;
     * this stage, but this does not occur in CCM mode.&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &amp;amp;len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    ciphertext_len += len;&lt;br /&gt;
&lt;br /&gt;
    /* Get the tag */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, 14, tag))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Clean up */&lt;br /&gt;
    EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
&lt;br /&gt;
    return ciphertext_len;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Authenticated Decryption using CCM mode==&lt;br /&gt;
&lt;br /&gt;
Decryption with CCM mode is much the same as for decryption with CCM but with some additional things to bear in mind.&lt;br /&gt;
* you can only call EVP_DecryptUpdate once for AAD and once for the plaintext.&lt;br /&gt;
* The total ciphertext length must be passed to EVP_DecryptUpdate (only needed if AAD is passed)&lt;br /&gt;
* Optionally the tag and IV length can also be passed. If they are not then the defaults are used (12 bytes for AES tags, and 7 bytes for AES IVs)&lt;br /&gt;
* The tag verify is performed when you call the final EVP_DecryptUpdate and is reflected by the return value: there is no call to EVP_DecryptFinal.&lt;br /&gt;
&lt;br /&gt;
See the code below for an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int ccm_decrypt(unsigned char *ciphertext, int ciphertext_len,&lt;br /&gt;
                unsigned char *aad, int aad_len,&lt;br /&gt;
                unsigned char *tag,&lt;br /&gt;
                unsigned char *key,&lt;br /&gt;
                unsigned char *iv,&lt;br /&gt;
                unsigned char *plaintext)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX *ctx;&lt;br /&gt;
    int len;&lt;br /&gt;
    int plaintext_len;&lt;br /&gt;
    int ret;&lt;br /&gt;
&lt;br /&gt;
    /* Create and initialise the context */&lt;br /&gt;
    if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise the decryption operation. */&lt;br /&gt;
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Setting IV len to 7. Not strictly necessary as this is the default&lt;br /&gt;
     * but shown here for the purposes of this example */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, 7, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Set expected tag value. */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, 14, tag))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise key and IV */&lt;br /&gt;
    if(1 != EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    /* Provide the total ciphertext length */&lt;br /&gt;
    if(1 != EVP_DecryptUpdate(ctx, NULL, &amp;amp;len, NULL, ciphertext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Provide any AAD data. This can be called zero or more times as required */&lt;br /&gt;
    if(1 != EVP_DecryptUpdate(ctx, NULL, &amp;amp;len, aad, aad_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide the message to be decrypted, and obtain the plaintext output.&lt;br /&gt;
     * EVP_DecryptUpdate can be called multiple times if necessary&lt;br /&gt;
     */&lt;br /&gt;
    ret = EVP_DecryptUpdate(ctx, plaintext, &amp;amp;len, ciphertext, ciphertext_len);&lt;br /&gt;
&lt;br /&gt;
    plaintext_len = len;&lt;br /&gt;
&lt;br /&gt;
    /* Clean up */&lt;br /&gt;
    EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
&lt;br /&gt;
    if(ret &amp;gt; 0) {&lt;br /&gt;
        /* Success */&lt;br /&gt;
        return plaintext_len;&lt;br /&gt;
    } else {&lt;br /&gt;
        /* Verify failed */&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Potential Issue in AES/GCM ==&lt;br /&gt;
&lt;br /&gt;
Early versions of the authenticated encryption interface required using a 0-sized array (not a NULL array) to arrive at the proper authentication tag '''''when''''' the authentication tag size was ''not'' a multiple of the block size (for example, an authentication tag size of 20 bytes). For more information on the issue and the work-arounds, see [http://rt.openssl.org/Ticket/Display.html?id=2859 Issue #2859: Possible bug in AES GCM mode] and [http://groups.google.com/d/msg/mailing.openssl.users/idg9Z22MYZs/Jqlo8dA-2tMJ Possible bug in GCM/GMAC with (just) AAD of size unequal to block size].&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[EVP]]&lt;br /&gt;
* [[Libcrypto API]]&lt;br /&gt;
* [[EVP Symmetric Encryption and Decryption]]&lt;br /&gt;
* [[EVP Asymmetric Encryption and Decryption of an Envelope]]&lt;br /&gt;
* [[EVP Signing and Verifying]]&lt;br /&gt;
* [[EVP Message Digests]]&lt;br /&gt;
* [[EVP Key Agreement]]&lt;br /&gt;
* [[EVP Key and Parameter Generation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Crypto API]]&lt;br /&gt;
[[Category:C level]]&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=EVP_Authenticated_Encryption_and_Decryption&amp;diff=2784</id>
		<title>EVP Authenticated Encryption and Decryption</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=EVP_Authenticated_Encryption_and_Decryption&amp;diff=2784"/>
		<updated>2019-06-05T04:46:58Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Add additional information.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DocInclude&lt;br /&gt;
|Name=Authenticated Encryption and Decryption&lt;br /&gt;
|Url=http://wiki.openssl.org/index.php/Manual:Evp(3)&lt;br /&gt;
|Include=evp.h}}&lt;br /&gt;
&lt;br /&gt;
The EVP interface supports the ability to perform authenticated encryption and decryption, as well as the option to attach unencrypted, associated data to the message. Such Authenticated-Encryption with Associated-Data (AEAD) schemes provide confidentiality by encrypting the data, and also provide authenticity assurances by creating a MAC tag over the encrypted data. The MAC tag will ensure the data is not accidentally altered or maliciously tampered during transmission and storage.&lt;br /&gt;
&lt;br /&gt;
There are a number of AEAD modes of operation. The modes include EAX, CCM and GCM mode. Using AEAD modes is nearly identical to using standard symmetric encryption modes like CBC, CFB and OFB modes.&lt;br /&gt;
&lt;br /&gt;
As with standard symmetric encryption you will need to know the following:&lt;br /&gt;
&lt;br /&gt;
* Algorithm (currently only AES is supported)&lt;br /&gt;
* Mode (currently only GCM and CCM are supported)&lt;br /&gt;
* Key&lt;br /&gt;
* Initialisation Vector (IV)&lt;br /&gt;
&lt;br /&gt;
In addition you can (optionally) provide some ''Additional Authenticated Data'' (AAD). The AAD data is not encrypted, and is typically passed to the recipient in plaintext along with the ciphertext. An example of AAD is the IP address and port number in a IP header used with IPsec.&lt;br /&gt;
&lt;br /&gt;
The output from the encryption operation will be the ciphertext, and a tag. The tag is subsequently used during the decryption operation to ensure that the ciphertext and AAD have not been tampered with.&lt;br /&gt;
&lt;br /&gt;
The OpenSSL manual describes the usage of the GCM and CCM modes here: [[Manual:EVP_EncryptInit(3)#GCM_Mode]].&lt;br /&gt;
&lt;br /&gt;
The complete source code of the following examples can be downloaded as [[Media:evp-gcm-encrypt.c|evp-gcm-encrypt.c]] resp.  [[Media:evp-ccm-encrypt.c|evp-ccm-encrypt.c]].&lt;br /&gt;
&lt;br /&gt;
==Authenticated Encryption using GCM mode==&lt;br /&gt;
&lt;br /&gt;
Encryption is performed in much the same way as for symmetric encryption as described [[EVP Symmetric Encryption and Decryption|here]]. The main differences are:&lt;br /&gt;
* You may optionally pass through an IV length using EVP_CIPHER_CTX_ctrl&lt;br /&gt;
* AAD data is passed through in zero or more calls to EVP_EncryptUpdate, with the output buffer set to NULL&lt;br /&gt;
* Once private data has been added, you cannot add AAD data &lt;br /&gt;
* After the EVP_EncryptFinal_ex call a new call to EVP_CIPHER_CTX_ctrl retrieves the tag&lt;br /&gt;
&lt;br /&gt;
See the code below for an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int gcm_encrypt(unsigned char *plaintext, int plaintext_len,&lt;br /&gt;
                unsigned char *aad, int aad_len,&lt;br /&gt;
                unsigned char *key,&lt;br /&gt;
                unsigned char *iv, int iv_len,&lt;br /&gt;
                unsigned char *ciphertext,&lt;br /&gt;
                unsigned char *tag)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX *ctx;&lt;br /&gt;
&lt;br /&gt;
    int len;&lt;br /&gt;
&lt;br /&gt;
    int ciphertext_len;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    /* Create and initialise the context */&lt;br /&gt;
    if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise the encryption operation. */&lt;br /&gt;
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Set IV length if default 12 bytes (96 bits) is not appropriate&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise key and IV */&lt;br /&gt;
    if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide any AAD data. This can be called zero or more times as&lt;br /&gt;
     * required&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, NULL, &amp;amp;len, aad, aad_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide the message to be encrypted, and obtain the encrypted output.&lt;br /&gt;
     * EVP_EncryptUpdate can be called multiple times if necessary&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &amp;amp;len, plaintext, plaintext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    ciphertext_len = len;&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Finalise the encryption. Normally ciphertext bytes may be written at&lt;br /&gt;
     * this stage, but this does not occur in GCM mode&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &amp;amp;len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    ciphertext_len += len;&lt;br /&gt;
&lt;br /&gt;
    /* Get the tag */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Clean up */&lt;br /&gt;
    EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
&lt;br /&gt;
    return ciphertext_len;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Authenticated Decryption using GCM mode==&lt;br /&gt;
&lt;br /&gt;
Again, the decryption operation is much the same as for normal symmetric decryption as described [[EVP Symmetric Encryption and Decryption|here]]. The main differences are:&lt;br /&gt;
* You may optionally pass through an IV length using EVP_CIPHER_CTX_ctrl&lt;br /&gt;
* AAD data is passed through in zero or more calls to EVP_DecryptUpdate, with the output buffer set to NULL&lt;br /&gt;
* Prior to the EVP_DecryptFinal_ex call a new call to EVP_CIPHER_CTX_ctrl provides the tag&lt;br /&gt;
* A non positive return value from EVP_DecryptFinal_ex should be considered as a failure to authenticate ciphertext and/or AAD. It does not necessarily indicate a more serious error.&lt;br /&gt;
&lt;br /&gt;
See the code example below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len,&lt;br /&gt;
                unsigned char *aad, int aad_len,&lt;br /&gt;
                unsigned char *tag,&lt;br /&gt;
                unsigned char *key,&lt;br /&gt;
                unsigned char *iv, int iv_len,&lt;br /&gt;
                unsigned char *plaintext)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX *ctx;&lt;br /&gt;
    int len;&lt;br /&gt;
    int plaintext_len;&lt;br /&gt;
    int ret;&lt;br /&gt;
&lt;br /&gt;
    /* Create and initialise the context */&lt;br /&gt;
    if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise the decryption operation. */&lt;br /&gt;
    if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Set IV length. Not necessary if this is 12 bytes (96 bits) */&lt;br /&gt;
    if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise key and IV */&lt;br /&gt;
    if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide any AAD data. This can be called zero or more times as&lt;br /&gt;
     * required&lt;br /&gt;
     */&lt;br /&gt;
    if(!EVP_DecryptUpdate(ctx, NULL, &amp;amp;len, aad, aad_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide the message to be decrypted, and obtain the plaintext output.&lt;br /&gt;
     * EVP_DecryptUpdate can be called multiple times if necessary&lt;br /&gt;
     */&lt;br /&gt;
    if(!EVP_DecryptUpdate(ctx, plaintext, &amp;amp;len, ciphertext, ciphertext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    plaintext_len = len;&lt;br /&gt;
&lt;br /&gt;
    /* Set expected tag value. Works in OpenSSL 1.0.1d and later */&lt;br /&gt;
    if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Finalise the decryption. A positive return value indicates success,&lt;br /&gt;
     * anything else is a failure - the plaintext is not trustworthy.&lt;br /&gt;
     */&lt;br /&gt;
    ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &amp;amp;len);&lt;br /&gt;
&lt;br /&gt;
    /* Clean up */&lt;br /&gt;
    EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
&lt;br /&gt;
    if(ret &amp;gt; 0) {&lt;br /&gt;
        /* Success */&lt;br /&gt;
        plaintext_len += len;&lt;br /&gt;
        return plaintext_len;&lt;br /&gt;
    } else {&lt;br /&gt;
        /* Verify failed */&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Authenticated Encryption using CCM mode==&lt;br /&gt;
&lt;br /&gt;
Encryption with CCM mode is much the same as for encryption with GCM but with some additional things to bear in mind.&lt;br /&gt;
* you can only call EVP_EncryptUpdate once for AAD and once for the plaintext.&lt;br /&gt;
* The total plaintext length must be passed to EVP_EncryptUpdate (only needed if AAD is passed)&lt;br /&gt;
* Optionally the tag and IV length can also be passed. If they are not then the defaults are used (12 bytes for AES tags, and 7 bytes for AES IVs)&lt;br /&gt;
&lt;br /&gt;
See the code below for an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int ccm_encrypt(unsigned char *plaintext, int plaintext_len,&lt;br /&gt;
                unsigned char *aad, int aad_len,&lt;br /&gt;
                unsigned char *key,&lt;br /&gt;
                unsigned char *iv,&lt;br /&gt;
                unsigned char *ciphertext,&lt;br /&gt;
                unsigned char *tag)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX *ctx;&lt;br /&gt;
&lt;br /&gt;
    int len;&lt;br /&gt;
&lt;br /&gt;
    int ciphertext_len;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    /* Create and initialise the context */&lt;br /&gt;
    if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise the encryption operation. */&lt;br /&gt;
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Setting IV len to 7. Not strictly necessary as this is the default&lt;br /&gt;
     * but shown here for the purposes of this example.&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, 7, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Set tag length */&lt;br /&gt;
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, 14, NULL);&lt;br /&gt;
&lt;br /&gt;
    /* Initialise key and IV */&lt;br /&gt;
    if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Provide the total plaintext length */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, NULL, &amp;amp;len, NULL, plaintext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Provide any AAD data. This can be called zero or one times as required */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, NULL, &amp;amp;len, aad, aad_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide the message to be encrypted, and obtain the encrypted output.&lt;br /&gt;
     * EVP_EncryptUpdate can only be called once for this.&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &amp;amp;len, plaintext, plaintext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    ciphertext_len = len;&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Finalise the encryption. Normally ciphertext bytes may be written at&lt;br /&gt;
     * this stage, but this does not occur in CCM mode.&lt;br /&gt;
     */&lt;br /&gt;
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &amp;amp;len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
    ciphertext_len += len;&lt;br /&gt;
&lt;br /&gt;
    /* Get the tag */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, 14, tag))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Clean up */&lt;br /&gt;
    EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
&lt;br /&gt;
    return ciphertext_len;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Authenticated Decryption using CCM mode==&lt;br /&gt;
&lt;br /&gt;
Decryption with CCM mode is much the same as for decryption with CCM but with some additional things to bear in mind.&lt;br /&gt;
* you can only call EVP_DecryptUpdate once for AAD and once for the plaintext.&lt;br /&gt;
* The total ciphertext length must be passed to EVP_DecryptUpdate (only needed if AAD is passed)&lt;br /&gt;
* Optionally the tag and IV length can also be passed. If they are not then the defaults are used (12 bytes for AES tags, and 7 bytes for AES IVs)&lt;br /&gt;
* The tag verify is performed when you call the final EVP_DecryptUpdate and is reflected by the return value: there is no call to EVP_DecryptFinal.&lt;br /&gt;
&lt;br /&gt;
See the code below for an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int ccm_decrypt(unsigned char *ciphertext, int ciphertext_len,&lt;br /&gt;
                unsigned char *aad, int aad_len,&lt;br /&gt;
                unsigned char *tag,&lt;br /&gt;
                unsigned char *key,&lt;br /&gt;
                unsigned char *iv,&lt;br /&gt;
                unsigned char *plaintext)&lt;br /&gt;
{&lt;br /&gt;
    EVP_CIPHER_CTX *ctx;&lt;br /&gt;
    int len;&lt;br /&gt;
    int plaintext_len;&lt;br /&gt;
    int ret;&lt;br /&gt;
&lt;br /&gt;
    /* Create and initialise the context */&lt;br /&gt;
    if(!(ctx = EVP_CIPHER_CTX_new()))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise the decryption operation. */&lt;br /&gt;
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Setting IV len to 7. Not strictly necessary as this is the default&lt;br /&gt;
     * but shown here for the purposes of this example */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, 7, NULL))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Set expected tag value. */&lt;br /&gt;
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, 14, tag))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Initialise key and IV */&lt;br /&gt;
    if(1 != EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    /* Provide the total ciphertext length */&lt;br /&gt;
    if(1 != EVP_DecryptUpdate(ctx, NULL, &amp;amp;len, NULL, ciphertext_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /* Provide any AAD data. This can be called zero or more times as required */&lt;br /&gt;
    if(1 != EVP_DecryptUpdate(ctx, NULL, &amp;amp;len, aad, aad_len))&lt;br /&gt;
        handleErrors();&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
     * Provide the message to be decrypted, and obtain the plaintext output.&lt;br /&gt;
     * EVP_DecryptUpdate can be called multiple times if necessary&lt;br /&gt;
     */&lt;br /&gt;
    ret = EVP_DecryptUpdate(ctx, plaintext, &amp;amp;len, ciphertext, ciphertext_len);&lt;br /&gt;
&lt;br /&gt;
    plaintext_len = len;&lt;br /&gt;
&lt;br /&gt;
    /* Clean up */&lt;br /&gt;
    EVP_CIPHER_CTX_free(ctx);&lt;br /&gt;
&lt;br /&gt;
    if(ret &amp;gt; 0) {&lt;br /&gt;
        /* Success */&lt;br /&gt;
        return plaintext_len;&lt;br /&gt;
    } else {&lt;br /&gt;
        /* Verify failed */&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Potential Issue in AES/GCM ==&lt;br /&gt;
&lt;br /&gt;
Early versions of the authenticated encryption interface required using a 0-sized array (not a NULL array) to arrive at the proper authentication tag '''''when''''' the authentication tag size was ''not'' a multiple of the block size (for example, an authentication tag size of 20 bytes). For more information on the issue and the work-arounds, see [http://rt.openssl.org/Ticket/Display.html?id=2859 Issue #2859: Possible bug in AES GCM mode] and [http://groups.google.com/d/msg/mailing.openssl.users/idg9Z22MYZs/Jqlo8dA-2tMJ Possible bug in GCM/GMAC with (just) AAD of size unequal to block size].&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[EVP]]&lt;br /&gt;
* [[Libcrypto API]]&lt;br /&gt;
* [[EVP Symmetric Encryption and Decryption]]&lt;br /&gt;
* [[EVP Asymmetric Encryption and Decryption of an Envelope]]&lt;br /&gt;
* [[EVP Signing and Verifying]]&lt;br /&gt;
* [[EVP Message Digests]]&lt;br /&gt;
* [[EVP Key Agreement]]&lt;br /&gt;
* [[EVP Key and Parameter Generation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Crypto API]]&lt;br /&gt;
[[Category:C level]]&lt;br /&gt;
[[Category:Examples]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
	<entry>
		<id>https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=2782</id>
		<title>Cryptogams AES</title>
		<link rel="alternate" type="text/html" href="https://wiki.openssl.org/index.php?title=Cryptogams_AES&amp;diff=2782"/>
		<updated>2019-05-25T14:33:21Z</updated>

		<summary type="html">&lt;p&gt;Jwalton: Remove alignment from discussion. Alignment is handled by the module.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.openssl.org/~appro/cryptogams/ Cryptogams] is Andy Polyakov's project used to develop high speed cryptographic primitives and share them with other developers. This wiki article will show you how to use Cryptogams ARMv4 AES implementation. According to the head notes the ARMv4 implementation runs around 22 to 40 cycles per byte (cpb). Typical C/C++ implementations run around 50 to 80 cpb and Andy's routines should outperform all of them.&lt;br /&gt;
&lt;br /&gt;
Andy's Cryptogam implementations are provided by OpenSSL, but they are also available stand alone under a BSD license. The BSD style license is permissive and allows developers to use Andy's high speed cryptography without an OpenSSL dependency or licensing terms.&lt;br /&gt;
&lt;br /&gt;
There are 6 steps to the process. The first step obtains the sources. The second step creates an ASM source file. The third step compiles and assembles the source file into an object file. The fourth steps determines the API. The fifth step creates a C header file. The final step integrates the object file into a program. Once you create the files &amp;lt;tt&amp;gt;aes-armv4.h&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; you can use &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; to restore symbols back to their Cryptogams name with &amp;lt;tt&amp;gt;sed -i 's|OPENSSL|CRYPTOGAMS|g' aes-armv4.h aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few cautions before you begin. First, you are going to examine undocumented features of the OpenSSL library to learn how to work with the Cryptogam's sources. The Cryptogam sources are stable but things could change over time. Second, the ARMv4 implementation operates in ECB mode and encrypts or decrypts full AES blocks. You are responsible for things like padding and side channel counter-measures.&lt;br /&gt;
&lt;br /&gt;
At the moment Clang is miscompiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Also see [https://bugs.llvm.org/show_bug.cgi?id=38133 LLVM Issue 38133]. You can work around the problem by compiling &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;-mthumb&amp;lt;/tt&amp;gt;, but all data must be aligned. If you don't use aligned buffers then a &amp;lt;tt&amp;gt;SIGBUS&amp;lt;/tt&amp;gt; could occur.&lt;br /&gt;
&lt;br /&gt;
==Obtain Source Files==&lt;br /&gt;
&lt;br /&gt;
There are two source files you need for Cryptogams AES. The first is [https://github.com/openssl/openssl/blob/master/crypto/perlasm/arm-xlate.pl &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;] and the second is [https://github.com/openssl/openssl/blob/master/crypto/aes/asm/aes-armv4.pl &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt;]. They are available in the OpenSSL sources. The following commands fetch OpenSSL and then peels off the two Cryptogams files of interest.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Clone OpenSSL for the latest Cryptogams sources&lt;br /&gt;
git clone https://github.com/openssl/openssl.git&lt;br /&gt;
&lt;br /&gt;
mkdir cryptogams/&lt;br /&gt;
&lt;br /&gt;
cp ./openssl/crypto/perlasm/arm-xlate.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/aes/asm/aes-armv4.pl ./cryptogams/&lt;br /&gt;
cp ./openssl/crypto/arm_arch.h cryptogams/&lt;br /&gt;
&lt;br /&gt;
cd cryptogams/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create ASM File==&lt;br /&gt;
&lt;br /&gt;
The second step is to run &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; to produce an assembly language source file that can be consumed by GCC. &amp;lt;tt&amp;gt;aes-armv4.pl&amp;lt;/tt&amp;gt; internally calls &amp;lt;tt&amp;gt;arm-xlate.pl&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;linux32&amp;lt;/tt&amp;gt; is the flavor used by the translate program. &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is the output filename. In the command below note the &amp;lt;tt&amp;gt;*.S&amp;lt;/tt&amp;gt; file extension, which is a capitol '''''S'''''. Do not use a lowercase '''''s''''' because GCC must drive the compile and assemble step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;perl aes-armv4.pl linux32 aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GCC is needed to drive the process because there are C macros in the source file. Some Cryptogam source files have this requirement, while some others do not. &amp;lt;tt&amp;gt;aes-armv4&amp;lt;/tt&amp;gt; happens to have the requirement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat aes-armv4.S&lt;br /&gt;
@ Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#ifndef __KERNEL__&lt;br /&gt;
# include &amp;quot;arm_arch.h&amp;quot;&lt;br /&gt;
#else&lt;br /&gt;
# define __ARM_ARCH__ __LINUX_ARM_ARCH__&lt;br /&gt;
#endif&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point there is an ASM file but it needs two small fixups. First, &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; is an OpenSSL source file so the dependency must be removed. Second, GCC defines &amp;lt;tt&amp;gt;__ARM_ARCH&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;__ARM_ARCH__&amp;lt;/tt&amp;gt; so a &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; is needed.&lt;br /&gt;
&lt;br /&gt;
To fixup the source files execute the following two commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Remove OpenSSL include&lt;br /&gt;
sed -i 's/# include &amp;quot;arm_arch.h&amp;quot;//g' aes-armv4.S&lt;br /&gt;
&lt;br /&gt;
# Fix GCC defines&lt;br /&gt;
sed -i 's/__ARM_ARCH__/__ARM_ARCH/g' aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately, instead of the two &amp;lt;tt&amp;gt;sed's&amp;lt;/tt&amp;gt;, you can open &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt;, copy the defines and paste them directly into &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;. Take care when using &amp;lt;tt&amp;gt;arm_arch.h&amp;lt;/tt&amp;gt; as it carries the OpenSSL license.&lt;br /&gt;
&lt;br /&gt;
After the two fixups &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; is ready to be compiled by GCC.&lt;br /&gt;
&lt;br /&gt;
==Compile Source File==&lt;br /&gt;
&lt;br /&gt;
The source file is ready to be compiled and assembled. At this point there are two choices. First, you can use ARMv5t or higher which includes Thumb instructions. The following compiles the source file with ARMv5t.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second choice uses ARMv4 and avoids Thumb instructions. If you want to avoid Thumb then add &amp;lt;tt&amp;gt;-marm&amp;lt;/tt&amp;gt; to you compile command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv4 -marm -c aes-armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using ARMv5t as an example you now have an object file with the following symbols. Symbols with a capitol '''''T''''' are public and exported. Symbols with a lower '''''t''''' are private and should not be used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv5t -c aes-armv4.S&lt;br /&gt;
$ nm aes-armv4.o&lt;br /&gt;
000011c0 T AES_decrypt&lt;br /&gt;
00000540 T AES_encrypt&lt;br /&gt;
00000b60 T AES_set_decrypt_key&lt;br /&gt;
00000b80 T AES_set_enc2dec_key&lt;br /&gt;
00000820 T AES_set_encrypt_key&lt;br /&gt;
00000cc0 t AES_Td&lt;br /&gt;
00000000 t AES_Te&lt;br /&gt;
000012c0 t _armv4_AES_decrypt&lt;br /&gt;
00000640 t _armv4_AES_encrypt&lt;br /&gt;
00000b80 t _armv4_AES_set_enc2dec_key&lt;br /&gt;
00000820 t _armv4_AES_set_encrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can inspect the generated code with &amp;lt;tt&amp;gt;objdump&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ objdump --disassemble aes-armv4.o&lt;br /&gt;
aes-armv4.o:     file format elf32-littlearm&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
00000b60 &amp;lt;AES_set_decrypt_key&amp;gt;:&lt;br /&gt;
     b60:       e52de004        push    {lr}            ; (str lr, [sp, #-4]!)&lt;br /&gt;
     b64:       ebffff2d        bl      820 &amp;lt;AES_set_encrypt_key&amp;gt;&lt;br /&gt;
     b68:       e3300000        teq     r0, #0&lt;br /&gt;
     b6c:       e49de004        pop     {lr}            ; (ldr lr, [sp], #4)&lt;br /&gt;
     b70:       1afffff9        bne     b5c &amp;lt;AES_set_encrypt_key+0x33c&amp;gt;&lt;br /&gt;
     b74:       e1a00002        mov     r0, r2&lt;br /&gt;
     b78:       e1a01002        mov     r1, r2&lt;br /&gt;
     b7c:       eaffffff        b       b80 &amp;lt;AES_set_enc2dec_key&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And trace it back to the source code in &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;.globl  AES_set_decrypt_key&lt;br /&gt;
.type   AES_set_decrypt_key,%function&lt;br /&gt;
.align  5&lt;br /&gt;
AES_set_decrypt_key:&lt;br /&gt;
        str     lr,[sp,#-4]!            @ push lr&lt;br /&gt;
        bl      _armv4_AES_set_encrypt_key&lt;br /&gt;
        teq     r0,#0&lt;br /&gt;
        ldr     lr,[sp],#4              @ pop lr&lt;br /&gt;
        bne     .Labrt&lt;br /&gt;
&lt;br /&gt;
        mov     r0,r2                   @ AES_set_encrypt_key preserves r2,&lt;br /&gt;
        mov     r1,r2                   @ which is AES_KEY *key&lt;br /&gt;
        b       _armv4_AES_set_enc2dec_key&lt;br /&gt;
.size   AES_set_decrypt_key,.-AES_set_decrypt_key&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Determine API==&lt;br /&gt;
&lt;br /&gt;
The next step is determine the API so you can call it from a C program. Unfortunately the API is not documented and you have to dig around the OpenSSL sources. The functions of interest are &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; of OpenSSL sources reveals the following for &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_set_encrypt_key | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:632:int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examining &amp;lt;tt&amp;gt;aes_core.c:632&amp;lt;/tt&amp;gt; reveals the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   632  int AES_set_encrypt_key(const unsigned char *userKey, const int bits,&lt;br /&gt;
   633                          AES_KEY *key)&lt;br /&gt;
   634  {&lt;br /&gt;
            ...&lt;br /&gt;
   728      return 0;&lt;br /&gt;
   729  }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next piece of information to discover is &amp;lt;tt&amp;gt;AES_KEY&amp;lt;/tt&amp;gt;. Again a quick &amp;lt;tt&amp;gt;grep&amp;lt;/tt&amp;gt; leads you to &amp;lt;tt&amp;gt;aes_key_st&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_KEY | grep typedef&lt;br /&gt;
include/openssl/aes.h:39:typedef struct aes_key_st AES_KEY;&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n include/openssl/aes.h&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    31  struct aes_key_st {&lt;br /&gt;
    32  # ifdef AES_LONG&lt;br /&gt;
    33      unsigned long rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    34  # else&lt;br /&gt;
    35      unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    36  # endif&lt;br /&gt;
    37      int rounds;&lt;br /&gt;
    38  };&lt;br /&gt;
    39  typedef struct aes_key_st AES_KEY;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, you need &amp;lt;tt&amp;gt;AES_MAXNR&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;aes.h&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -IR AES_MAXNR | grep define&lt;br /&gt;
include/openssl/aes.h:# define AES_MAXNR 14&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lather, rinse repeat for &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;AES_encrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;crypto/aes/aes_core.c:787&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_encrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:787:void AES_encrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
...&lt;br /&gt;
   783  /*&lt;br /&gt;
   784   * Encrypt a single block&lt;br /&gt;
   785   * in and out can overlap&lt;br /&gt;
   786   */&lt;br /&gt;
   787  void AES_encrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   788                   const AES_KEY *key) {&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And &amp;lt;tt&amp;gt;AES_decrypt&amp;lt;/tt&amp;gt; can be found at &amp;lt;tt&amp;gt;aes_core.c:978&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;openssl$ grep -nIR AES_decrypt | grep '\.c'&lt;br /&gt;
...&lt;br /&gt;
crypto/aes/aes_core.c:978:void AES_decrypt(...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
openssl$ cat -n crypto/aes/aes_core.c&lt;br /&gt;
&lt;br /&gt;
   974  /*&lt;br /&gt;
   975   * Decrypt a single block&lt;br /&gt;
   976   * in and out can overlap&lt;br /&gt;
   977   */&lt;br /&gt;
   978  void AES_decrypt(const unsigned char *in, unsigned char *out,&lt;br /&gt;
   979                   const AES_KEY *key)&lt;br /&gt;
   980  {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create C Header==&lt;br /&gt;
&lt;br /&gt;
The fifth step creates a C header file based on information from [[#Determine_API|Determine API]]. The header file is needed for two reasons. First, it removes the OpenSSL dependency from your project. Second, it avoids OpenSSL licensing violations.&lt;br /&gt;
&lt;br /&gt;
Below is the C Header file you can use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/* Header file for use with Cryptogam's ARMv4 AES.     */&lt;br /&gt;
/* Also see http://www.openssl.org/~appro/cryptogams/  */&lt;br /&gt;
/* https://wiki.openssl.org/index.php/Cryptogams_AES.  */&lt;br /&gt;
&lt;br /&gt;
#ifndef CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
#define CRYPTOGAMS_AES_ARMV4_H&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define AES_MAXNR 14&lt;br /&gt;
&lt;br /&gt;
typedef struct AES_KEY_st {&lt;br /&gt;
    unsigned int rd_key[4 * (AES_MAXNR + 1)];&lt;br /&gt;
    int rounds;&lt;br /&gt;
} AES_KEY;&lt;br /&gt;
&lt;br /&gt;
int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);&lt;br /&gt;
void AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
void AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);&lt;br /&gt;
&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
}&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif  /* CRYPTOGAMS_AES_ARMV4_H */&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Test Program==&lt;br /&gt;
&lt;br /&gt;
The final step is to test the integration of Cryptogam's AES with your program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -std=c99 aes-armv4-test.c ./aes-armv4.o -o aes-armv4-test.exe&lt;br /&gt;
$ ./aes-armv4-test.exe&lt;br /&gt;
Encrypted plaintext!&lt;br /&gt;
Decrypted ciphertext!&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the test program is shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    /* Test key from FIPS 197 */&lt;br /&gt;
    const uint8_t kb[] = {&lt;br /&gt;
        0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,&lt;br /&gt;
        0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t pb[] = {&lt;br /&gt;
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,&lt;br /&gt;
        0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    const uint8_t cb[] = {&lt;br /&gt;
        0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, &lt;br /&gt;
        0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    /* Scratch */&lt;br /&gt;
    uint8_t buf[16];&lt;br /&gt;
    int result;&lt;br /&gt;
    &lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    result = AES_set_encrypt_key(kb, sizeof(kb)*8, &amp;amp; ekey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_encrypt(pb, buf, &amp;amp;ekey);&lt;br /&gt;
    if (memcmp(cb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Encrypted plaintext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to encrypt plaintext!\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    /********************************************/&lt;br /&gt;
&lt;br /&gt;
    AES_KEY dkey;&lt;br /&gt;
    result = AES_set_decrypt_key(kb, sizeof(kb)*8, &amp;amp; dkey);&lt;br /&gt;
    assert(result == 0);&lt;br /&gt;
&lt;br /&gt;
    AES_decrypt(cb, buf, &amp;amp;dkey);&lt;br /&gt;
    if (memcmp(pb, buf, 16) == 0)&lt;br /&gt;
        printf(&amp;quot;Decrypted ciphertext!\n&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
        printf(&amp;quot;Failed to decrypt ciphertext!\n&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Symbol Names==&lt;br /&gt;
&lt;br /&gt;
The article used the same names as they appeared in the Cryptogams source code. For example, &amp;lt;tt&amp;gt;AES_set_encrypt_key&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;AES_set_decrypt_key&amp;lt;/tt&amp;gt; are the names of two functions in the source code, and they will show up in the object file and when compiled and the library when linked.&lt;br /&gt;
&lt;br /&gt;
It is possible the function and date names will collide if you also link to OpenSSL, either directly or indirectly. If you plan on using Cryptogams code in a shared object then you should rename all symbols to avoid collisions. To rename symbols for AES you should rename all &amp;lt;tt&amp;gt;AES_*&amp;lt;/tt&amp;gt; names. Assuming you are using &amp;lt;tt&amp;gt;MYLIB&amp;lt;/tt&amp;gt; as a prefix the following &amp;lt;tt&amp;gt;sed&amp;lt;/tt&amp;gt; should do the job.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sed -i 's/OPENSSL/MYLIB/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_decrypt/MYLIB_AES_decrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_encrypt/MYLIB_AES_encrypt/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_decrypt_key/MYLIB_AES_set_decrypt_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_enc2dec_key/MYLIB_AES_set_enc2dec_key/g' aes_armv4.h aes_armv4.S&lt;br /&gt;
sed -i 's/AES_set_encrypt_key/MYLIB_AES_set_encrypt_key/g' aes_armv4.h aes_armv4.S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can verify public symbols were renamed with &amp;lt;tt&amp;gt;nm aes-armv4.o&amp;lt;/tt&amp;gt;. Generally speaking, all symbols with capitol letters like &amp;lt;tt&amp;gt;T&amp;lt;/tt&amp;gt; (public function), &amp;lt;tt&amp;gt;B&amp;lt;/tt&amp;gt; (uninitialized data), &amp;lt;tt&amp;gt;C&amp;lt;/tt&amp;gt; (common data), &amp;lt;tt&amp;gt;D&amp;lt;/tt&amp;gt; (initialized data), and &amp;lt;tt&amp;gt;R&amp;lt;/tt&amp;gt; (read-only data) should be renamed.&lt;br /&gt;
&lt;br /&gt;
==Benchmarks==&lt;br /&gt;
&lt;br /&gt;
You can perform a rough benchmark using the code shown below. Prior to executing the benchmark program you should move the CPU from &amp;lt;tt&amp;gt;on-demand&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;powersave&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;performance&amp;lt;/tt&amp;gt; mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;aes-armv4.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
typedef unsigned char byte;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    const unsigned int STEPS = 128;&lt;br /&gt;
    byte* buf = (byte*)malloc(STEPS*16+16);&lt;br /&gt;
    memset(buf, 0x00, 16);&lt;br /&gt;
&lt;br /&gt;
    AES_KEY ekey;&lt;br /&gt;
    (void)AES_set_encrypt_key(buf, 16*8, &amp;amp;ekey);&lt;br /&gt;
&lt;br /&gt;
    double elapsed = 0.0;&lt;br /&gt;
    size_t total = 0;&lt;br /&gt;
&lt;br /&gt;
    struct timespec start, end;&lt;br /&gt;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;start);&lt;br /&gt;
&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        size_t idx = 0;&lt;br /&gt;
        for (unsigned int i=0; i&amp;lt;STEPS; ++i)&lt;br /&gt;
            AES_encrypt(&amp;amp;buf[idx+i], &amp;amp;buf[idx+i+1], &amp;amp;ekey);&lt;br /&gt;
        total += 16*STEPS;&lt;br /&gt;
        &lt;br /&gt;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &amp;amp;end);&lt;br /&gt;
        elapsed = (end.tv_sec-start.tv_sec);&lt;br /&gt;
    }&lt;br /&gt;
    while (elapsed &amp;lt; 3 /* seconds */);&lt;br /&gt;
&lt;br /&gt;
    /* Increase precision of elapsed time */&lt;br /&gt;
    elapsed = ((double)end.tv_sec-start.tv_sec) +&lt;br /&gt;
              ((double)end.tv_nsec-start.tv_nsec) / 1000 / 1000 / 1000;&lt;br /&gt;
&lt;br /&gt;
    /* CPU freq of 950 MHz */&lt;br /&gt;
    const double cpuFreq = 950.0*1000*1000;&lt;br /&gt;
&lt;br /&gt;
    const double bytes = total;&lt;br /&gt;
    const double ghz = cpuFreq / 1000 / 1000 / 1000;&lt;br /&gt;
    const double mbs = bytes / elapsed / 1024 / 1024;&lt;br /&gt;
    const double cpb = elapsed * cpuFreq / bytes;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;%.0f bytes\n&amp;quot;, bytes);&lt;br /&gt;
    printf(&amp;quot;%.02f mbs\n&amp;quot;, mbs);&lt;br /&gt;
    printf(&amp;quot;%.02f cpb\n&amp;quot;, cpb);&lt;br /&gt;
    &lt;br /&gt;
    free(buf);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The results below are from a BananaPi with a Cortex-A7 Sun7i SoC running at 950 MHz. A C/C++ AES implementation runs about 65 cpb on the dev-board. Notice &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; was compiled with &amp;lt;tt&amp;gt;-march=armv7&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ gcc -march=armv7 -c aes-armv4.S -o aes-armv7.o&lt;br /&gt;
$ gcc -O3 -std=c99 aes-armv7-test.c aes-armv7.o -o aes-armv7-test.exe&lt;br /&gt;
$ ./aes-armv7-test.exe&lt;br /&gt;
78426112 bytes&lt;br /&gt;
24.93 mbs&lt;br /&gt;
36.34 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the following is from a Wandboard Dual with a NXP i.MX6 Cortex-A9 running at 1 GHz.  A C/C++ implementation runs around 40 cpb.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ ./aes-armv7-test.exe&lt;br /&gt;
106029056 bytes&lt;br /&gt;
33.80 mbs&lt;br /&gt;
26.80 cpb&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Autotools ==&lt;br /&gt;
&lt;br /&gt;
If you are using Autotools you can add the following to &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; to conditionally compile &amp;lt;tt&amp;gt;aes-armv4.S&amp;lt;/tt&amp;gt; for A-32 platforms. You will need to detect ARM A-32 and set &amp;lt;tt&amp;gt;IS_ARM32&amp;lt;/tt&amp;gt; to non-0. Also see [https://www.gnu.org/software/automake/manual/html_node/Assembly-Support.html Automake Assembly Support] in section 8.13 of the manual.&lt;br /&gt;
&lt;br /&gt;
First, the &amp;lt;tt&amp;gt;configure.ac&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# Set ASM tools&lt;br /&gt;
AC_SUBST([CCAS], [$CC])&lt;br /&gt;
AC_SUBST([CCASFLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
# Used by Makefile.am to compile aes-armv4.S&lt;br /&gt;
if test &amp;quot;$IS_ARM32&amp;quot; != &amp;quot;0&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
   ## Save CFLAGS&lt;br /&gt;
   SAVED_CFLAGS=&amp;quot;$CFLAGS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   CFLAGS=&amp;quot;-march=armv7-a -Wa,--noexecstack&amp;quot;&lt;br /&gt;
   AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
   AC_COMPILE_IFELSE(&lt;br /&gt;
      [AC_LANG_PROGRAM([])],&lt;br /&gt;
      [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
      [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
   )&lt;br /&gt;
&lt;br /&gt;
   if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
&lt;br /&gt;
      AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
      AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
&lt;br /&gt;
   else&lt;br /&gt;
&lt;br /&gt;
      CFLAGS=&amp;quot;-march=armv7-a&amp;quot;&lt;br /&gt;
      AC_MSG_CHECKING([if $CC supports $CFLAGS])&lt;br /&gt;
      AC_COMPILE_IFELSE(&lt;br /&gt;
         [AC_LANG_PROGRAM([])],&lt;br /&gt;
         [AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],&lt;br /&gt;
         [AC_MSG_RESULT([no]);  AC_SUBST([tr_RESULT], [0])]&lt;br /&gt;
      )&lt;br /&gt;
&lt;br /&gt;
      if test &amp;quot;$tr_RESULT&amp;quot; = &amp;quot;1&amp;quot;; then&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [true])&lt;br /&gt;
         AC_SUBST([CRYPTOPGAMS_FLAGS], [$CFLAGS])&lt;br /&gt;
      else&lt;br /&gt;
         AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
      fi&lt;br /&gt;
   fi&lt;br /&gt;
&lt;br /&gt;
   ## Restore CFLAGS&lt;br /&gt;
   CFLAGS=&amp;quot;$SAVED_CFLAGS&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
   # Required for other platforms&lt;br /&gt;
   AM_CONDITIONAL([CRYPTOGAMS_AES], [false])&lt;br /&gt;
fi&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second, the &amp;lt;tt&amp;gt;Makefile.am&amp;lt;/tt&amp;gt; recipe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if CRYPTOGAMS_AES&lt;br /&gt;
&lt;br /&gt;
  aes_armv4_la_SOURCES = aes-armv4.S&lt;br /&gt;
  aes_armv4_la_CCASFLAGS = $(AM_CFLAGS) $(CRYPTOGAMS_AES)&lt;br /&gt;
&lt;br /&gt;
  pkginclude_HEADERS += aes-armv4.h&lt;br /&gt;
&lt;br /&gt;
endif&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Cryptogams]]&lt;/div&gt;</summary>
		<author><name>Jwalton</name></author>
	</entry>
</feed>