https://wiki.openssl.org/api.php?action=feedcontributions&user=Rschmicker&feedformat=atomOpenSSLWiki - User contributions [en]2024-03-29T13:20:21ZUser contributionsMediaWiki 1.35.6https://wiki.openssl.org/index.php?title=Main_Page&diff=2592Main Page2017-05-23T14:59:09Z<p>Rschmicker: /* Internals and Development */</p>
<hr />
<div>This is the OpenSSL wiki. The main site is https://www.openssl.org . If this is your first visit or to get an account please see the [[Welcome]] page. Your participation and [[Contributions]] are valued.<br />
<br />
This wiki is intended as a place for collecting, organizing, and refining useful information about OpenSSL that is currently strewn among multiple locations and formats.<br />
<br />
== OpenSSL Quick Links ==<br />
<br />
<TABLE border=0><br />
<TR><br />
<TD>[[OpenSSL Overview]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[Compilation and Installation]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[Internals]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[Mailing Lists]] </TD><br />
</TR><br />
<TR><br />
<TD>[[libcrypto API]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[libssl API]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[Examples]] </TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[Documentation Index|Index of all API functions]]</TD><br />
</TR><br />
<TR><br />
<TD>[[License]] </TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[Command Line Utilities]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[Related Links]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[Binaries]]</TD><br />
</TR><br />
<TR><br />
<TD>[[SSL and TLS Protocols]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[1.1 API Changes]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
<TD>[[FIPS modules]]</TD><br />
<TD>[[Image:HTAB.png]][[Image:HTAB.png]]</TD><br />
</TR><br />
</TABLE><br />
<br />
== Administrivia ==<br />
Site guidelines, legal and admininstrative issues.<br />
:* [[Basic rules]], [[Commercial Product Disclaimer]], [[Contributions]], [[Copyright]], [[License]]<br />
:* Using This Wiki<br />
:: [http://meta.wikimedia.org/wiki/Help:Contents Wiki User's Guide], [http://www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list], [http://www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ], [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki Mailing List]<br />
<br />
== Reference ==<br />
This section contains the automagically generated man pages from the OpenSSL git repository, and similar "man" style reference documentation. The man pages are automatically imported from the OpenSSL git repository and local wiki modifications are submitted as patches.<br />
:* OpenSSL Manual Pages<br />
::* [[Manual:Openssl(1)]], [[Manual:Ssl(3)]], [[Manual:Crypto(3)]], [[Documentation Index]]<br />
:: If you wish to edit any of the Manual page content please refer to the [[Guidelines for Manual Page Authors]] page.<br />
:* [[API]], [[Libcrypto API]], [[Libssl API]]<br />
:* [[FIPS mode()]], [[FIPS_mode_set()]]<br />
<br />
== Usage and Programming ==<br />
This section has discussions of practical issues in using OpenSSL<br />
:* Building from Source<br />
:: Where to find it, the different versions, how to build and install it.<br />
:* [[OpenSSL Overview]]<br />
:* [[Versioning]]<br />
:* [[Compilation and Installation]]<br />
:* [[EVP]]<br />
:: Programming techniques and example code<br />
:: Use of EVP is preferred for most applications and circumstances<br />
::* [[EVP Asymmetric Encryption and Decryption of an Envelope]]<br />
::* [[EVP Authenticated Encryption and Decryption]]<br />
::* [[EVP Symmetric Encryption and Decryption]]<br />
::* [[EVP Key and Parameter Generation]]<br />
::* [[EVP Key Agreement]]<br />
::* [[EVP Message Digests]]<br />
::* [[EVP Key Derivation]]<br />
::* [[EVP Signing and Verifying|EVP Signing and Verifying (including MAC codes)]]<br />
:* [[STACK API]]<br />
:* Low Level APIs<br />
::[[Creating an OpenSSL Engine to use indigenous ECDH ECDSA and HASH Algorithms]]<br />
:: More specialized non-EVP usage<br />
::* [[Diffie-Hellman parameters]]<br />
:* [[FIPS Mode]]<br />
:* [[Simple TLS Server]]<br />
<br />
== Concepts and Theory ==<br />
Discussions of basic cryptographic theory and concepts<br />
Discussions of common operational issues<br />
:* [[Base64]]<br />
:* [http://wiki.openssl.org/index.php/Category:FIPS_140 FIPS 140-2]<br />
:* [[Random Numbers]]<br />
:* [[Diffie Hellman]]<br />
:* [[Elliptic Curve Diffie Hellman]]<br />
:* [[Elliptic Curve Cryptography]]<br />
<br />
== Security Advisories ==<br />
:* [https://www.openssl.org/policies/secpolicy.html OpenSSL Security Policy]<br />
:* [https://www.openssl.org/news/vulnerabilities.html OpenSSL Vulnerabilities List]<br />
:* [[Security_Advisories|Security Advisories Additional Information]]<br />
<br />
== Feedback and Contributions ==<br />
:* [https://www.openssl.org/support/faq.html#BUILD18 How to notify us of suspected security vulnerabilities]<br />
:* [https://www.openssl.org/community/#bugs How to report bugs, other than for suspected vulnerabilities]<br />
:* [[Contributions|General background on source and documentation contributions - '''must read''']]<br />
:* Contributing code fixes, other than for suspected vulnerabilities, as well as fixes and other improvements to manual pages:<br />
::* If you are unsure as to whether a feature will be useful for the general OpenSSL community please discuss it on the [https://www.openssl.org/support/community.html openssl-dev mailing list] first. Someone may be already working on the same thing or there may be a good reason as to why that feature isn't implemented.<br />
::* Follow the [[Use of Git#Use_of_Git_with_OpenSSL_source_tree|instructions for accessing source code]] in the appropriate branches. Note that manual pages and the FAQ are maintained with the source code.<br />
::* Submit a pull request for each separate fix (also documented [[Use of Git#Use_of_Git_with_OpenSSL_source_tree|there]])<br />
::* Submit a bug report (see second bullet, above) and reference the pull request. Or you can attach the patch to the ticket.<br />
:* Contributing fixes and other improvements to the web site<br />
::* Follow the [[Use_of_Git#Use_of_Git_with_the_OpenSSL_web_site|instructions for accessing web site sources]]<br />
::* Create a patch (also documented [[Use_of_Git#Use_of_Git_with_the_OpenSSL_web_site|there]])<br />
::* Submit a bug report and add the patch as an attachment<br />
:* [[Developing For OpenSSL]]<br />
:* [[KnownPatches|Known patches not part of OpenSSL]]<br />
:* [[Welcome|Contributing to this wiki]]<br />
<br />
== Internals and Development ==<br />
This section is for internal details of primary interest to OpenSSL maintainers and power users<br />
:* [[Code reformatting]]<br />
<br />
:* [[Internals]]<br />
:* [[Code Quality]]<br />
:* [[Static and Dynamic Analysis]]<br />
:* [[OCB|OCB Licence details]]<br />
:* [[Defect and Feature Review Process]]<br />
:* [[Unit Testing]] (includes other automated testing information)<br />
:* [[How to Integrate a Symmetric Cipher]]</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_Symmetric_Cipher&diff=2591How to Integrate Symmetric Cipher2017-05-23T14:56:47Z<p>Rschmicker: Rschmicker moved page How to Integrate Symmetric Cipher to How to Integrate a Symmetric Cipher: missing "a"</p>
<hr />
<div>#REDIRECT [[How to Integrate a Symmetric Cipher]]</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2590How to Integrate a Symmetric Cipher2017-05-23T14:56:47Z<p>Rschmicker: Rschmicker moved page How to Integrate Symmetric Cipher to How to Integrate a Symmetric Cipher: missing "a"</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. <br />
<br />
=== Error/Reason Codes ===<br />
<br />
Error codes are handled dynamically in OpenSSL by using make update. make update will, in part, call make errors which will later execute util/mkerr.pl recursively on crypto/*.c, crypto/*/*.c, ssl/*.c, and apps/*.c. This script will scan for error and function codes and automatically add them as error/reason codes in the library. Essentially, it will look for strings that "look like" function or reason codes: basically anything consisting of all upper case and numerics which has _F_ or _R_ in it and which has the name of an error library at the start. For example, EVP_F_ARIA_INIT_KEY and EVP_R_ARIA_KEY_SETUP_FAILED. For more detailed documentation please view crypto/err/README and util/mkerr.pl.<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained in the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2589How to Integrate a Symmetric Cipher2017-05-23T04:10:48Z<p>Rschmicker: /* Error/Reason Codes */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. <br />
<br />
=== Error/Reason Codes ===<br />
<br />
Error codes are handled dynamically in OpenSSL by using make update. make update will, in part, call make errors which will later execute util/mkerr.pl recursively on crypto/*.c, crypto/*/*.c, ssl/*.c, and apps/*.c. This script will scan for error and function codes and automatically add them as error/reason codes in the library. Essentially, it will look for strings that "look like" function or reason codes: basically anything consisting of all upper case and numerics which has _F_ or _R_ in it and which has the name of an error library at the start. For example, EVP_F_ARIA_INIT_KEY and EVP_R_ARIA_KEY_SETUP_FAILED. For more detailed documentation please view crypto/err/README and util/mkerr.pl.<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained in the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2588How to Integrate a Symmetric Cipher2017-05-23T04:07:37Z<p>Rschmicker: </p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. <br />
<br />
=== Error/Reason Codes ===<br />
<br />
Error codes are handled dynamically in OpenSSL by using make update. make update will, in part, call make errors which will later execute util/mkerr.pl recursively on crypto/*.c, crypto/*/*.c, ssl/*.c, and apps/*.c. This script will scan for error and function codes and automatically add them as error/reason codes in the library. Essentially, it will look for strings that "look like" function or reason codes: basically anything consisting of all upper case and numerics which has _F_ or _R_ in it and which has the name of an error library at the start. For example,<br />
<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
will list the function name and<br />
<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
will give the reason for the error. For more detailed documentation please view crypto/err/README and util/mkerr.pl.<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained in the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2587How to Integrate a Symmetric Cipher2017-05-08T23:15:43Z<p>Rschmicker: /* Speed Test */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained in the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2586How to Integrate a Symmetric Cipher2017-05-08T23:14:04Z<p>Rschmicker: /* Cipher Initialization Function */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained in the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2585How to Integrate a Symmetric Cipher2017-05-08T23:13:35Z<p>Rschmicker: /* Key Initialization Function */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained in the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2584How to Integrate a Symmetric Cipher2017-05-08T23:10:28Z<p>Rschmicker: /* Speed Test */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained in the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2583How to Integrate a Symmetric Cipher2017-05-08T23:08:45Z<p>Rschmicker: </p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained the the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2582How to Integrate a Symmetric Cipher2017-05-08T23:07:05Z<p>Rschmicker: /* Speed Test */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained the the TLS section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2581How to Integrate a Symmetric Cipher2017-05-08T23:06:51Z<p>Rschmicker: /* Speed Test */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained the the [TLS] section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2580How to Integrate a Symmetric Cipher2017-05-08T23:05:50Z<p>Rschmicker: /* Speed Test */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
Just as it was explained the the [[TLS]] section, the speed test integration is optional and only needs to be implemented if desired. That being said, it is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2579How to Integrate a Symmetric Cipher2017-05-08T23:04:22Z<p>Rschmicker: /* TLS */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== TLS ==<br />
<br />
At this point the cipher has now been implemented into the OpenSSL library and the following TLS section is optional. This section is only necessary if the cipher must be implemented as a TLS ciphersuite. <br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2578How to Integrate a Symmetric Cipher2017-05-08T23:01:15Z<p>Rschmicker: /* Update Headers */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
== TLS ==<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2577How to Integrate a Symmetric Cipher2017-05-08T23:00:55Z<p>Rschmicker: /* TLS */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
== TLS ==<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2576How to Integrate a Symmetric Cipher2017-05-08T22:59:40Z<p>Rschmicker: /* Speed Test */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
== TLS ==<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM&&async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2575How to Integrate a Symmetric Cipher2017-05-08T22:57:57Z<p>Rschmicker: /* Key Initialization Function */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode==EVP_CIPH_CFB_MODE||mode==EVP_CIPH_OFB_MODE||enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
== TLS ==<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2574How to Integrate a Symmetric Cipher2017-05-08T20:07:43Z<p>Rschmicker: /* Building */</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE || enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
== TLS ==<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything. Note the enable-aria to include it in the building of OpenSSL:<br />
<br />
./config enable-aria &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with aria disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2573How to Integrate a Symmetric Cipher2017-05-08T20:05:08Z<p>Rschmicker: </p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer in this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE || enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
== TLS ==<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything:<br />
<br />
./config &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with the feature disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2572How to Integrate a Symmetric Cipher2017-05-08T20:00:07Z<p>Rschmicker: </p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer into this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE || enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
== TLS ==<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything:<br />
<br />
./config &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with the feature disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmickerhttps://wiki.openssl.org/index.php?title=How_to_Integrate_a_Symmetric_Cipher&diff=2571How to Integrate a Symmetric Cipher2017-05-05T19:53:18Z<p>Rschmicker: Created page with "This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for b..."</p>
<hr />
<div>This page serves to provide a guideline on how to integrate a symmetric block cipher into OpenSSL 1.1.1. This integration procedure will cover all aspects of integration for both [[Libcrypto API|libcrypto]] and [[Libssl API|libssl]]. ARIA will be used as the example cipher throughout. ARIA is a basic C implementation without the extra complexity of assembly optimization and lacking support for some of the more complex chaining modes.<br />
<br />
== Create the Cipher ==<br />
All cryptographic functions are stored within the crypto/ directory and this is where ARIA's cipher will be implemented. To begin, create the directory.<br />
<br />
mkdir crypto/aria<br />
<br />
Now that the directory is created, the creation of the cipher can begin by opening:<br />
<br />
vi crypto/aria/aria.c<br />
<br />
You need to define two functions to do the lowest level encryption and decryption, although for ARIA they are both the same and only the first was actually defined:<br />
<br />
void ARIA_encrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
void ARIA_decrypt(const unsigned char *in, unsigned char *out,<br />
const ARIA_KEY *key)<br />
<br />
Secondly, in the case of ARIA, you must also provide functions to set the encryption and decryption keys:<br />
<br />
int ARIA_set_encrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
int ARIA_set_decrypt_key(const unsigned char *userKey, const int bits,<br />
ARIA_KEY *key)<br />
<br />
To prototype these functions you may create an aria_locl.h within crypto/aria/, however, the current preferred method is to prototype these functions in crypto/include/internal/aria.h. The prototyped functions contained within crypto/include/internal/aria.h can then be included by:<br />
<br />
#include "internal/aria.h"<br />
<br />
The last step in ARIA's low level implementation is to create a build.info file. This tells the Configure file in the root directory of OpenSSL on how to compile the files in ARIA's directory and configure the OpenSSL's library Makefile. The following is a simple example:<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
aria.c<br />
<br />
In short, this tells Configure that the code contained within aria.c, relies on code contained within the rest of the [[Libcrypto API|libcrypto]] library and include ARIA in [[Libcrypto API|libcrypto]]. For further guidance on creating more complex build.info files please view the README file contained within the Configurations directory or view other cipher's implementations. For assembly optimized versions, there is a lot more involved and is beyond the scope of this guide. This impacts not only the cryptographic implementation but also the EVP layer.<br />
<br />
<br />
== Changes to the Configuration ==<br />
At this point the low level interface for ARIA has been implemented but we still need to modify the config and Configure files. This is necessary to have Configure recognize the build.info file previously created and the ability to detect an enable-aria flag.<br />
<br />
=== Changes to config ===<br />
The config file requires the ability to detect an enable-aria flag which is done by adding aria to the argument of a for loop:<br />
<br />
for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha<br />
do<br />
if [ ! -d $THERE/crypto/$i ]<br />
then<br />
options="$options no-$i"<br />
fi<br />
done<br />
<br />
=== Changes to Configure ===<br />
The following will include ARIA when Configure searches for a build.info file.<br />
<br />
$config{sdirs} = [<br />
"objects",<br />
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",<br />
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "chacha", "modes",<br />
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",<br />
"buffer", "bio", "stack", "lhash", "rand", "err",<br />
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",<br />
"cms", "ts", "srp", "cmac", "ct", "async", "kdf"<br />
];<br />
<br />
The following steps are optional if you would like to have the cipher be disabled, should someone compiling choose to do so. Start by including ARIA to the disables table.<br />
<br />
my @disablables = (<br />
"afalgeng",<br />
"aria",<br />
"asan",<br />
"asm",<br />
"async",<br />
<br />
Then, have ARIA disabled by default:<br />
our %disabled = ( # "what" => "comment"<br />
"aria" => "default",<br />
"asan" => "default",<br />
"crypto-mdebug" => "default",<br />
<br />
== EVP Interface Integration ==<br />
In short, the [[EVP]] provides a programmer with a high level interface to easily interact with low level OpenSSL cryptographic functions. A crypto/evp/e_aria.c file must be created to branch the gap between the high level EVP and the newly created ARIA cipher. At the bare minimum the file will include:<br />
* Key struct<br />
* EVP_CIPHER struct<br />
* Naming the EVP_CIPHER<br />
* Key Initialization Function<br />
* Cipher Initialization Function<br />
<br />
=== Key Structure ===<br />
The structure of the key is up to the developer implementing the cipher. <br />
<br />
/* ARIA subkey Structure */<br />
typedef struct {<br />
ARIA_KEY ks;<br />
} EVP_ARIA_KEY;<br />
<br />
This is a very simple example but this structure will include all necessary key material for both the encrypt and decrypt functions. It is also possible to include a function pointer into this struct to control whether the key is being used for encryption or decryption. This will be further explained below. <br />
<br />
=== EVP_CIPHER struct ===<br />
The following is the definition of an EVP_CIPHER struct found in crypto/crypto/include/internal/evp_int.h:<br />
<br />
struct evp_cipher_st {<br />
int nid;<br />
int block_size;<br />
/* Default value for variable length ciphers */<br />
int key_len;<br />
int iv_len;<br />
/* Various flags */<br />
unsigned long flags;<br />
/* init key */<br />
int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc);<br />
/* encrypt/decrypt data */<br />
int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl);<br />
/* cleanup ctx */<br />
int (*cleanup) (EVP_CIPHER_CTX *);<br />
/* how big ctx->cipher_data needs to be */<br />
int ctx_size;<br />
/* Populate a ASN1_TYPE with parameters */<br />
int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Get parameters from a ASN1_TYPE */<br />
int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *);<br />
/* Miscellaneous operations */<br />
int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);<br />
/* Application data */<br />
void *app_data;<br />
} /* EVP_CIPHER */ ;<br />
<br />
The ARIA EVP_CIPHER struct uses C preprocessor techniques to dynamically create the EVP_CIPHER struct and is outside the scope of this guide. Instead, the RC4 EVP_CIPHER struct is much easier to follow and mimic.<br />
<br />
static const EVP_CIPHER r4_cipher = {<br />
NID_rc4,<br />
1, EVP_RC4_KEY_SIZE, 0,<br />
EVP_CIPH_VARIABLE_LENGTH,<br />
rc4_init_key,<br />
rc4_cipher,<br />
NULL,<br />
sizeof(EVP_RC4_KEY),<br />
NULL,<br />
NULL,<br />
NULL,<br />
NULL<br />
};<br />
<br />
Notice the function pointers rc4_init_key and rc4_cipher as these are the functions to create the key and run the cipher respectively.<br />
<br />
=== Naming the EVP_CIPHER ===<br />
Again, since ARIA uses C preprocessor techniques to dynamically create the names of each of the modes of operation, we will take a look at RC4's implmentation as it is very easy to understand.<br />
<br />
const EVP_CIPHER *EVP_rc4(void)<br />
{<br />
return (&r4_cipher);<br />
}<br />
<br />
Notice the name in this example is EVP_rc4() and r4_cipher is the name of the cipher initialization function.<br />
<br />
=== Key Initialization Function ===<br />
<br />
The following initializes the key for ARIA depending on the mode the user requests through the EVP interface.<br />
<br />
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
int ret;<br />
int mode = EVP_CIPHER_CTX_mode(ctx);<br />
if (mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE || enc)<br />
ret = ARIA_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
else<br />
ret = ARIA_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,<br />
EVP_CIPHER_CTX_get_cipher_data(ctx));<br />
if(ret < 0) {<br />
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);<br />
return 0;<br />
}<br />
return 1; <br />
}<br />
<br />
An alternative approach is to use the enc parameter to determine whether the key is being used for encryption or decryption. The value of 1 for enc is encryption and 0 for decryption.<br />
<br />
=== Cipher Initialization Function ===<br />
Once the key has been created, the EVP will then call the cipher initialization function assigned in the EVP_CIPHER struct. This function will pass the parameters to the low level implementation of ARIA. <br />
<br />
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,<br />
size_t len, const ARIA_KEY *key,<br />
unsigned char *ivec, const int enc)<br />
{<br />
if (enc)<br />
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
else<br />
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,<br />
(block128_f) aria_encrypt);<br />
}<br />
<br />
Another approach is to assign a function pointer in the creation of the key as to whether an encrypt or decrypt routine is about to happen using the enc parameter. <br />
<br />
/* EVP_CIPHER struct */<br />
typedef struct {<br />
MYKEY k;<br />
union {<br />
void (*cipher) (MYKEY *k, size_t len, const unsigned char *in,<br />
unsigned char *out);<br />
} stream;<br />
} EVP_MYCIPHER_KEY;<br />
<br />
/* Key Initialization Function */<br />
static int mycipher_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,<br />
const unsigned char *iv, int enc)<br />
{<br />
enc ? mycipher_enc_set_key(&data(ctx)->k) : <br />
mycipher_dec_set_key(&data(ctx)->k);<br />
data(ctx)->stream.cipher = enc ? encrypt_mycipher : decrypt_mycipher;<br />
return 1;<br />
}<br />
<br />
/* Cipher Initialization Function */<br />
static int mycipher(EVP_CIPHER_CTX *ctx, unsigned char *out,<br />
const unsigned char *in, size_t inl)<br />
{<br />
(*data(ctx)->stream.cipher) (&data(ctx)->k, inl, in, out);<br />
return 1;<br />
}<br />
<br />
Once completed, add e_aria.c into crypto/evp's build.info file.<br />
<br />
LIBS=../../libcrypto<br />
SOURCE[../../libcrypto]=\<br />
encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \<br />
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\<br />
e_rc4.c e_aes.c names.c e_seed.c e_aria.c \<br />
<br />
Now that e_aria.c has been built, we have to register it with the EVP subsystem. Modify crypto/evp/c_allc.c to register ARIA.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_ecb());<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_128_cfb());<br />
EVP_add_cipher(EVP_aria_128_cfb1());<br />
EVP_add_cipher(EVP_aria_128_cfb8());<br />
EVP_add_cipher(EVP_aria_128_ofb());<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "ARIA128");<br />
EVP_add_cipher_alias(SN_aria_128_cbc, "aria128");<br />
EVP_add_cipher(EVP_aria_192_ecb());<br />
EVP_add_cipher(EVP_aria_192_cbc());<br />
EVP_add_cipher(EVP_aria_192_cfb());<br />
EVP_add_cipher(EVP_aria_192_cfb1());<br />
EVP_add_cipher(EVP_aria_192_cfb8());<br />
EVP_add_cipher(EVP_aria_192_ofb());<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher_alias(SN_aria_192_cbc,<br />
EVP_add_cipher(EVP_aria_256_ecb());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
EVP_add_cipher(EVP_aria_256_cfb());<br />
EVP_add_cipher(EVP_aria_256_cfb1());<br />
EVP_add_cipher(EVP_aria_256_cfb8());<br />
EVP_add_cipher(EVP_aria_256_ofb());<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
EVP_add_cipher_alias(SN_aria_256_cbc,<br />
#endif<br />
<br />
This adds all of the cipher chaining modes that were provided by the e_aria.c files except for CTR mode. It also includes some aliases for the CBC modes. ARIA also has some optional but recommended custom error messages. These are added to the crypto/evp/evp_err.c file:<br />
<br />
static ERR_STRING_DATA EVP_str_functs[] = {<br />
...<br />
{ERR_FUNC(EVP_F_ARIA_INIT_KEY), "aria_init_key"},<br />
<br />
and<br />
<br />
static ERR_STRING_DATA EVP_str_reasons[] = {<br />
...<br />
{ERR_REASON(EVP_R_ARIA_KEY_SETUP_FAILED), "aria key setup failed"},<br />
<br />
== Crypto Objects ==<br />
Crypto object IDs are used to map a name to a given ARIA cipher mode. To add object Ids for the ARIA suite, the crypto/objects/objects.txt file must be modified:<br />
<br />
!Alias aria 1 2 410 200046 1 1<br />
aria 1 : ARIA-128-ECB : aria-128-ecb<br />
aria 2 : ARIA-128-CBC : aria-128-cbc<br />
!Cname aria-128-cfb128<br />
aria 3 : ARIA-128-CFB : aria-128-cfb<br />
!Cname aria-128-ofb128<br />
aria 4 : ARIA-128-OFB : aria-128-ofb<br />
aria 5 : ARIA-128-CTR : aria-128-ctr<br />
<br />
aria 6 : ARIA-192-ECB : aria-192-ecb<br />
aria 7 : ARIA-192-CBC : aria-192-cbc<br />
!Cname aria-192-cfb128<br />
aria 8 : ARIA-192-CFB : aria-192-cfb<br />
!Cname aria-192-ofb128<br />
aria 9 : ARIA-192-OFB : aria-192-ofb<br />
aria 10 : ARIA-192-CTR : aria-192-ctr <br />
<br />
aria 11 : ARIA-256-ECB : aria-256-ecb<br />
aria 12 : ARIA-256-CBC : aria-256-cbc<br />
!Cname aria-256-cfb128<br />
aria 13 : ARIA-256-CFB : aria-256-cfb<br />
!Cname aria-256-ofb128<br />
aria 14 : ARIA-256-OFB : aria-256-ofb<br />
aria 15 : ARIA-256-CTR : aria-256-ctr<br />
<br />
# There are no OIDs for these ARIA modes...<br />
: ARIA-128-CFB1 : aria-128-cfb1<br />
: ARIA-192-CFB1 : aria-192-cfb1<br />
: ARIA-256-CFB1 : aria-256-cfb1<br />
: ARIA-128-CFB8 : aria-128-cfb8<br />
: ARIA-192-CFB8 : aria-192-cfb8<br />
: ARIA-256-CFB8 : aria-256-cfb8<br />
<br />
For more elaborate documentation inserting entries into crypto/objects/objects.txt, view the README file under crypto/objects/. Note that you must also run make update to automatically generate crypto/objects/obj_dat.h and crypto/objects/obj_mac.num. <br />
<br />
== Update Headers ==<br />
=== evp.h ===<br />
To begin, the include/openssl/evp.h header requires three changes. Firstly, ARIA's modes must be added:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
const EVP_CIPHER *EVP_aria_128_ecb(void);<br />
const EVP_CIPHER *EVP_aria_128_cbc(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb1(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb8(void);<br />
const EVP_CIPHER *EVP_aria_128_cfb128(void);<br />
# define EVP_aria_128_cfb EVP_aria_128_cfb128<br />
const EVP_CIPHER *EVP_aria_128_ofb(void);<br />
<br />
...<br />
<br />
const EVP_CIPHER *EVP_aria_256_ofb(void);<br />
# endif<br />
<br />
This is the name of the EVP_CIPHER created in e_aria.c. Secondly, we must add in the optional but recommended failure and reason codes:<br />
<br />
# define EVP_F_ARIA_INIT_KEY 168<br />
<br />
and<br />
<br />
# define EVP_R_ARIA_KEY_SETUP_FAILED 163<br />
<br />
=== ssl.h ===<br />
/include/openssl/ssl.h needs the string names to be later used in the ARIA cipher suites.<br />
<br />
# define SSL_TXT_ARIA128 "ARIA128"<br />
# define SSL_TXT_ARIA256 "ARIA256"<br />
# define SSL_TXT_ARIA "ARIA"<br />
<br />
=== tls1.h ===<br />
/include/openssl/tls1.h is where ARIA's cipher suite signatures will be defined. These come directly from RFC6209:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256 0x0300C03C<br />
# define TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384 0x0300C03D<br />
<br />
...<br />
<br />
# define TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0x0300C071<br />
<br />
It is important to note that this is where the key exchange, authentication, and MAC algorithms can be chosen by name and later implemented in s3_lib.c. Once the signatures are defined, the text representations need to be defined:<br />
<br />
/* ARIA based ciphersuites from RFC6209 */<br />
# define TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256 "ARIA128-CBC-SHA256" <br />
# define TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384 "ARIA256-CBC-SHA384"<br />
<br />
...<br />
<br />
# define TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 "ECDHE-PSK-ARIA256-CBC-SHA384"<br />
<br />
== TLS ==<br />
=== s3_lib.c ===<br />
To use ARIA with TLS, it is necessary to define the suite combinations that are legal as per the various standards. These are defined in the ssl/s3_lib.c file. In all cases the security level is considered high, the suite is not a default, and is supported only in TLS 1.2.<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_128_CBC_SHA256,<br />
TLS1_CK_RSA_WITH_ARIA_128_CBC_SHA256,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA128,<br />
SSL_SHA256,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,<br />
128,<br />
128,<br />
},<br />
{<br />
1,<br />
TLS1_TXT_RSA_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_RSA_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kRSA,<br />
SSL_aRSA,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
<br />
...<br />
<br />
{<br />
1,<br />
TLS1_TXT_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
TLS1_CK_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,<br />
SSL_kECDHEPSK,<br />
SSL_aPSK,<br />
SSL_ARIA256,<br />
SSL_SHA384,<br />
TLS1_2_VERSION, TLS1_2_VERSION,<br />
DTLS1_2_VERSION, DTLS1_2_VERSION,<br />
SSL_NOT_DEFAULT | SSL_HIGH,<br />
SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,<br />
256,<br />
256,<br />
},<br />
# endif /* OPENSSL_NO_EC */<br />
# endif /* OPENSSL_NO_PSK */<br />
#endif /* OPENSSL_NO_ARIA */<br />
<br />
It is critical to note that if the cipher suite implementation uses eliptical curve (EC) for instance, that the cipher suite implementation is inside the OPENSSL_NO_EC preprocessor directives.<br />
<br />
=== ssl_ciph.c ===<br />
The ssl/ssl_ciph.c file needs indices for the ARIA ciphers available from TLS. In the initial table of #defines:<br />
<br />
#define SSL_ENC_ARIA128_IDX 20<br />
#define SSL_ENC_ARIA256_IDX 21<br />
#define SSL_ENC_NUM_IDX 22<br />
<br />
Later in the ssl_cipher_table_cipher table of NIDs for each cipher:<br />
<br />
{SSL_ARIA128, NID_aria_128_cbc}, /* SSL_ENC_ARIA128_IDX 20 */<br />
{SSL_ARIA256, NID_aria_256_cbc} /* SSL_ENC_ARIA256_IDX 21 */<br />
<br />
This maps libssl's request of ARIA to ARIA's respective NID value which will later be looked up to dive into ARIA's implementation within libcrypto. This can be seen as bridging the gap between libssl and libcrypto. To continue, alias's must be created for the cipher suite:<br />
<br />
{0, SSL_TXT_ARIA128, 0, 0, 0, SSL_ARIA128, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA256, 0, 0, 0, SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
{0, SSL_TXT_ARIA, 0, 0, 0, SSL_ARIA128 | SSL_ARIA256, 0, 0, 0, 0, 0, 0},<br />
<br />
Lastly, add ARIA's description into the switch statement within the SSL_CIPHER_description function:<br />
<br />
case SSL_ARIA128:<br />
enc = "ARIA(128)";<br />
break;<br />
case SSL_ARIA256:<br />
enc = "ARIA(256)";<br />
break;<br />
<br />
=== ssl/ssl_init.c ===<br />
The ssl/ssl_init.c function needs to conditionally register the ARIA ciphers and can be inserted along with the other ciphers:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
EVP_add_cipher(EVP_aria_128_cbc());<br />
EVP_add_cipher(EVP_aria_256_cbc());<br />
#endif<br />
#ifndef OPENSSL_NO_DES<br />
EVP_add_cipher(EVP_des_cbc());<br />
EVP_add_cipher(EVP_des_ede3_cbc());<br />
#endif<br />
<br />
=== ssl/ssl_locl.h ===<br />
This file contains the bits for SSL_ARIA as well as the group definition:<br />
<br />
# define SSL_ARIA128 0x00100000L<br />
# define SSL_ARIA256 0x00200000L<br />
# define SSL_ARIA (SSL_ARIA128|SSL_ARIA256)<br />
<br />
=== ssl/t1_trce.c ===<br />
Finally, the ssl/t1_trce.c file contains a table of the protocol numbers and text descriptions for all legal TLS protocols. If your cipher suites are not already present in this file, they should be added to it. This step proved unnecessary for ARIA because the required definitions were already present.<br />
<br />
== Unit Testing ==<br />
OpenSSL has a built in test suite that can be leveraged for ARIA. The test/evptests.txt unit test vectors for ARIA need to be added:<br />
<br />
# ARIA test vectors from RFC5794<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-128-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = d718fbd6ab644c739da95f3be6451778<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-192-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f1011121314151617<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = 26449c1805dbe7aa25a468ce263a9e79<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = ENCRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
Cipher = ARIA-256-ECB<br />
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f<br />
Operation = DECRYPT<br />
Plaintext = 00112233445566778899aabbccddeeff<br />
Ciphertext = f92bd7c79fb72e2f2b8f80c1972d24fc<br />
<br />
These values are pulled from ARIA'a RFC and others can be added if desired. Once the integration is complete with the remaining steps below, the test suite can be ran with make test.<br />
<br />
== Utilities ==<br />
In util/mkdir.pl ARIA must be added to the list of known_algorithms and the include path to the ARIA header file added (unless no_aria) is defined:<br />
<br />
$crypto.=" include/openssl/aria.h" ; # unless $no_aria;<br />
<br />
== Applications ==<br />
The apps/openssl.c needs to be able to print that it does not support ARIA via the list_disabled function:<br />
<br />
#ifdef OPENSSL_NO_ARIA<br />
BIO_puts(bio_out, "ARIA\n");<br />
#endif<br />
<br />
The apps/progs.h needs the available cipher definitions included in the functions array:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-128-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-192-ecb", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-cbc", enc_main, enc_options },<br />
#endif<br />
#ifndef OPENSSL_NO_ARIA<br />
{ FT_cipher, "aria-256-ecb", enc_main, enc_options },<br />
#endif<br />
<br />
The apps/progs.pl program needs to know about the ARIA cipher:<br />
<br />
"aria-128-cbc", "aria-128-ecb",<br />
"aria-192-cbc", "aria-192-ecb",<br />
"aria-256-cbc", "aria-256-ecb",<br />
<br />
=== Speed Test ===<br />
It is possible to natively integrate ARIA into OpenSSL's built in speed test, however, once a cipher is integrated into the EVP the speed test can access the cipher using the -evp flag. For completeness sake, the following steps are necessary to manually integrated ARIA into OpenSSL's speedtest.<br />
<br />
First the ARIA header file needs to be conditionally included:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
# include <openssl/aria.h><br />
#endif<br />
<br />
The number of algorithms increased:<br />
<br />
#define ALGOR_NUM 33<br />
<br />
The algorithms themselves defined in the names array:<br />
<br />
"aria-128 cbc", "aria-192 cbc", "aria-256 cbc"<br />
<br />
The speed_options indicies defined:<br />
<br />
#define D_CBC_128_ARIA 30<br />
#define D_CBC_192_ARIA 31<br />
#define D_CBC_256_ARIA 32<br />
<br />
The doit_choices text mapping defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
{"aria-128-cbc", D_CBC_128_ARIA},<br />
{"aria-192-cbc", D_CBC_192_ARIA},<br />
{"aria-256-cbc", D_CBC_256_ARIA},<br />
#endif<br />
<br />
The initialisation key vectors defined:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
static const unsigned char akey24[24] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34<br />
};<br />
static const unsigned char akey32[32] = {<br />
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,<br />
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,<br />
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,<br />
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56<br />
};<br />
ARIA_KEY aria_ks1, aria_ks2, aria_ks3;<br />
#endif<br />
<br />
The command line processing adjusted:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
if (strcmp(*argv, "aria") == 0) {<br />
doit[D_CBC_128_ARIA] = doit[D_CBC_192_ARIA] =<br />
doit[D_CBC_256_ARIA] = 1;<br />
continue; <br />
}<br />
# endif<br />
<br />
Keys are set:<br />
<br />
# ifndef OPENSSL_NO_ARIA<br />
ARIA_set_encrypt_key(key16, 128, &aria_ks1);<br />
ARIA_set_encrypt_key(akey24, 192, &aria_ks2);<br />
ARIA_set_encrypt_key(akey32, 256, &aria_ks3);<br />
# endif<br />
<br />
Counts initialized:<br />
<br />
c[D_CBC_128_ARIA][0] = count;<br />
c[D_CBC_192_ARIA][0] = count;<br />
c[D_CBC_256_ARIA][0] = count;<br />
<br />
and adjusted:<br />
<br />
c[D_CBC_128_ARIA][i] = c[D_CBC_128_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_192_ARIA][i] = c[D_CBC_192_ARIA][i - 1] * l0 / l1;<br />
c[D_CBC_256_ARIA][i] = c[D_CBC_256_ARIA][i - 1] * l0 / l1;<br />
<br />
Finally, the actual speed testing code:<br />
<br />
#ifndef OPENSSL_NO_ARIA<br />
if (doit[D_CBC_128_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_128_ARIA]);<br />
doit[D_CBC_128_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_128_ARIA], c[D_CBC_128_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_128_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks1,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_128_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_192_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_192_ARIA]);<br />
doit[D_CBC_192_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_192_ARIA], c[D_CBC_192_ARIA][testnum],<br />
lengths[testnum]);<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported, exiting...");<br />
exit(1);<br />
}<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_192_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks2,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_192_ARIA, testnum, count, d);<br />
}<br />
}<br />
if (doit[D_CBC_256_ARIA]) {<br />
if (async_jobs > 0) {<br />
BIO_printf(bio_err, "Async mode is not supported with %s\n",<br />
names[D_CBC_256_ARIA]);<br />
doit[D_CBC_256_ARIA] = 0;<br />
}<br />
for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {<br />
print_message(names[D_CBC_256_ARIA], c[D_CBC_256_ARIA][testnum],<br />
lengths[testnum]);<br />
Time_F(START);<br />
for (count = 0, run = 1; COND(c[D_CBC_256_ARIA][testnum]); count++)<br />
ARIA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,<br />
(size_t)lengths[testnum], &aria_ks3,<br />
iv, ARIA_ENCRYPT);<br />
d = Time_F(STOP);<br />
print_result(D_CBC_256_ARIA, testnum, count, d);<br />
<br />
} <br />
}<br />
#endif<br />
<br />
== Manual Pages ==<br />
OpenSSL has the strong philosophy of containing documentation and manual pages for all code. The relevant manual pages require updating because they will gain automatic support for ARIA. Many of these pages require the same automatic change. These are doc/man1/dsa.pod, doc/man1/gendsa.pod, doc/man1/genrsa.pod and doc/man1/rsa.pod. The new command line options need to be added to the documentation:<br />
<br />
[B<-aria128>]<br />
[B<-aria192>]<br />
[B<-aria256>] <br />
<br />
and updating the brief description line:<br />
<br />
=item B<-aes128|-aes192|-aes256|-aria128|-aria192|-aria256|-camellia128|- camellia192|-camellia256|-des|-des3|-idea><br />
<br />
The doc/man1/pkcs12.pod requires that the new ciphers are added to the command line options:<br />
<br />
[B<-des | -des3 | -idea | -aes128 | -aes192 | -aes256 | -aria128 | -aria192 | -aria256 | -camellia128 | -camellia192 | -camellia256 | -nodes>]<br />
<br />
and a description is added in the body of the text:<br />
<br />
=item B<-aria128>, B<-aria192>, B<-aria256><br />
<br />
use ARIA to encrypt private keys before outputting.<br />
<br />
The doc/man1/ciphers.pod file requires a section describing the new cipher:<br />
<br />
=item B<ARIA128>, B<ARIA256>, B<ARIA><br />
<br />
cipher suites using 128 bit ARIA, 256 bit ARIA or either 128 or 256 bit ARIA.<br />
<br />
And an update to the cipher suites that are supported:<br />
<br />
=head2 ARIA cipher suites from RFC6209, extending TLS v1.2<br />
<br />
TLS_RSA_WITH_ARIA_128_CBC_SHA256 ARIA128-CBC-SHA256<br />
TLS_RSA_WITH_ARIA_256_CBC_SHA384 ARIA256-CBC-SHA384<br />
TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 DHE-DSS-ARIA128-CBC-SHA256<br />
TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 DHE-DSS-ARIA256-CBC-SHA384<br />
TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 DHE-RSA-ARIA128-CBC-SHA256<br />
TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 DHE-RSA-ARIA256-CBC-SHA384<br />
TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 DH-anon-ARIA128-CBC-SHA256<br />
TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 DH-anon-ARIA256-CBC-SHA384<br />
TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 ECDHE-ECDSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 ECDHE-ECDSA-ARIA256-CBC-SHA384<br />
TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 ECDHE-RSA-ARIA128-CBC-SHA256<br />
TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 ECDHE-RSA-ARIA256-CBC-SHA384<br />
<br />
== Building ==<br />
There are a number of commands to build and test everything:<br />
<br />
./config &&<br />
make &&<br />
make update &&<br />
make test &&<br />
LD_LIBRARY_PATH=. apps/openssl speed aria<br />
<br />
Also try a build with the feature disabled:<br />
<br />
./config no-aria &&<br />
make &&<br />
make test &&<br />
<br />
Both sequences should work and the tests should all pass.</div>Rschmicker