Introduction to OpenSSL
OpenSSL is a rich and self-contained open-source security toolbox. It provides the following main functions: SSL protocol implementation (including SSLv2, SSLv3 and tlsv1), a large number of soft algorithms (symmetric/asymmetric/abstract), big number calculation, asymmetric algorithm key generation, ASN.1 codec library, certificate request (pkcs10) encoding/decoding, digital certificate encoding/decoding, CRL encoding/decoding, OCSP protocol, digital certificate verification, pkcs7 standard implementation, and PKCS12 individual Digital Certificate Format implementation.
OpenSSL uses C language as the development language, which makes it have excellent cross-platform performance. OpenSSL supports Linux, UNIX, windows, Mac, and other platforms. The latest version of OpenSSL is openssl-1.0.1i.
For more information, see Official and unofficial documents. How to add a new algorithm to OpenSSL today.
Problem description
Although OpenSSL integrates many classic algorithms, such as symmetric algorithms, asymmetric algorithms, and digest algorithms, sometimes we need to use custom algorithms, such as implementing a custom Digest algorithm, it must be implemented using the large-number libraries of OpenSSL, and you also want to encapsulate your own algorithms into OpenSSL for unified calling or convenient project transformation and replacement. The most practical case is the transformation of sm2. In this example, the Digest algorithm Sm3 in the country secret is used as the Add object. Compile and debug the Digest algorithm in windows and only describe the Add step, therefore, the premise of this article is that the C language implementation of Sm3 Based on OpenSSL large data library has been completed. This article is only for the use of Huludao. To understand the principles, please read other materials or interpret the source code yourself, or wait for my next article.
Procedure
I. Preparations
1. Download OpenSSL source code, OpenSSL is currently the latest version of openssl-1.0.1i. :
2. Implementation of Sm3 in C language.
3. install and configure Perl and Vc in windows.
4. Familiar with OpenSSL compilation.
Ii. Sm3 code transformation [all files involved in this step are created to store directory relationships]
1. involved files:
1. [create a file] sm3.h
This is the most important header file, which defines the algorithm that can be exported, that is, each function declared in it will generate the corresponding libeay. num (which will be detailed in chapter 5) can be exported to the DLL for external calls. Several major statements are as follows:
Define the digest length of Sm3:
# Define sm3_digest_length 32/* Sm3 digest length is 256-bit 32-byte, MD5 Digest length is 128-bit not sure */
Defines sm3_ctx. This structure corresponds to the md_data of evp_md_ctx In the EVP encapsulation:
typedef struct SM3state_st{unsigned long long total_length;unsigned char message_buffer[64];size_t message_buffer_position;size_t V_i[8];size_t V_i_1[8];size_t T_j[64];} SM3_CTX;
Declare functions, including init, update, and final. These functions will be called internally during encapsulation. Of course, if they are exported in the DLL, they can also be called externally:
int SM3_Init(SM3_CTX*c);intSM3_Update(SM3_CTX *c, const void *data, size_t len);intSM3_Final(unsigned char *md, SM3_CTX *c);unsignedchar *SM3(unsigned char *d, size_t n, unsigned char *md);
2. [create a file] sm3_locl.h
This header file contains some macro definitions to be used. It mainly defines the internal functions required for the implementation of this algorithm and cannot be exported to the DLL for external calls.
Macro definition:
# Ifndefrotate # definerotate (A, n) (a) <(N) | (a) & 0 xffffffff)> (32-(N) # endif # define EE (B, c, d) (B & C) | ((~ B) & D) # define ff (B, c, d) (c) ^ (D) & (B) ^ (d )) # define Gg (B, c, d) (B) & (c) | (B) & (d) | (c) & (d) # define HH (B, c, d) (B) ^ (c) ^ (D) # define HH1 () (A ^ (rotate (A, 9) ^ (rotate (A, 17) # define HH2 (A) (a ^ (rotate (A, 15 )) ^ (rotate (A, 23) internal function: voidinit_t_j (size_t * t_j); voidinit_v_ I (size_t * V_ I); voidcf (size_t * t_j, size_t * V_ I, unsigned char * B _ I, size_t * v_ I _1 );
3. [create a file] sm3_dgst.c
Implement the functions declared in sm3.h and sm3_locl except Sm3 (which will be implemented in sm3_one.c ).
4. [create a file] sm3_one.c
Implement the Sm3 function declared in sm3.h.
5. [create a file] sm3.c
Abstract The file, such as using OpenSSL as a command line tool, and using the file name and digest algorithm name as option parameters to abstract the file.
6. [create a file] sm3test. c
Algorithm test file.
7. [new file] makefile
Makefile. It describes the roles, compilation processes, dependencies, and other aspects of the above files during compilation.
Iii. EVP encapsulation code
1. Four files involved:
2. [manually modify] EVP. h
EVP is mainly used for encapsulation in OpenSSL. Therefore, first add the new algorithm Sm3 in the EVP. h header file:
#ifndef OPENSSL_NO_SM3const EVP_MD *EVP_sm3(void);#endif
Note: The evp_sm3 () function returns the evp_md structure of Sm3, which is defined in m_sm3.c as well as the evp_sm3 () function.
3. [create a file] m_sm3.c
This is an important file for the new algorithm in the EVP directory. It defines the evp_md structure of sm3. the evp_md structure prototype is in EVP. h:
The evp_md structure of Sm3:
Static const evp_md sm3_md = {nid_sm3, // This must be defined after the oId is generated. This step is described in Chapter 4. Nid_sm3withrsaencryption, // in this region, sm3withrsa only serves as the digest length of the sample sm3_digest_length, // SM3, and defines 0, // flaginit, // The init function in the structure in sm3.h, point to sm3_initupdate in sm3.h, // same as final, // same as null, null, evp_pkey_rsa_method, // same as above, and only use sm3_cblock as an example, // declare sizeof (evp_md *) + sizeof (sm3_ctx) in sm3.h ),};
4. [manually modify] c_alld.c
After the OpenSSL algorithm is encapsulated, You need to load the algorithm to add Sm3:
#ifndefOPENSSL_NO_SM3EVP_add_digest(EVP_sm3());#endif
5. [manually modify] makefile
Add the new Sm3 algorithm to libsrc and libobj during compilation, and add dependencies between various Sm3 header files.
Iv. OID generation
1. involved files:
2. manually modify objects.txt
Add the oId of Sm3. Note: This example is used only. The actual OID of Sm3 is:
rsadsi 2 12 :SM3 : sm3
Add sm3withrsaencryption, which corresponds to PKCS1, only to make the evp_md structure of Sm3 have a value fill, the actual intention of adding Sm3 is not used for RSA, here is only for example.
pkcs1 15 : RSA-SM3 : sm3WithRSAEncryption
3. [Execute Command auto update] obj_mac.h and obj_mac.num
Open CMD and switch to the directory where \ crypto \ Objects \ of the source code is located,
Run the following command: Perl objects. pl objects.txt obj_mac.num obj_mac.h.
Both obj_mac.hand obj_mac.numfiles are updated due to changes to objects.txt. The added content is as follows:
4. [manually modify] objects. h
Synchronize the added content in obj_mac.h to objects. h. (In fact, this step is not affected, because this file is not used to generate obj_dat.h later. The content of objects. H is not comprehensive and does not contain obj_mac.h. It is correct that objects. h cannot be used for obj_dat.h. Remember, blood lessons !)
5. [execute the command to automatically update] obj_dat.h
Run the command: Perl obj_dat.pl obj_mac.h obj_dat.h
The file obj_dat.h will be automatically updated. The new content is as follows:
See the last two rows in the figure.
Line 4672: 921,/* OBJ_sm3 1 2 840 113549 2 12 */Line 4843: 920,/* OBJ_sm3WithRSAEncryption 1 2 840 113549 1 1 15 */
The last string of numbers is the algorithm's OID. This is not a real OID because it is not in step 2 objects.txt. For example only.
6. manually modify 】obj_xref.txt
Add:
sm3WithRSAEncryptionsm3rsaEncryption
7. [Execute Command auto update] obj_xref.h
Run the command: Perl objxref. pl obj_xref.txt obj_xref.h.
The added content after obj_xref.h is as follows:
V. Make settings
1. involved files \ util:
2. [manually modify] mkfiles. pl
Add:
"crypto/sm3",
Add the directory containing the Sm3 algorithm source code, which contains the MAKEFILE file of sm3. Then it will be compiled according to makefile.
3. [manually modify] mkdef. pl
Add content
With the header file of the new algorithm, you can export the Algorithm functions in the DLL.
4. [execute the command to automatically update] libeay. Num
Run the command: Perl util/mkdef. pl crypto update
The added content after libeay. Num is updated is as follows:
5. [manually modify] mk1mf. pl
Add content as follows:
6. [manual modification] sp-diff.pl
Add content as follows:
7. involved files \ crypto:
8. Manual modification crypto-lib.com
Add content as follows:
9. Manual modification install-crypto.com
Add content as follows:
10. The involved file root directory \ contains five:
11. [manual modification]
Add makefile, makefile. Bak, makefile.org, makevms.com, and install. VMS.
At this point, the source code needs to be added and modified, and compilation and testing will be introduced below.
6. Compile
1. In cmd, first set the VC environment and run the vcvars32.bat file under the VC directory, for example:
2. Upload the directory of the opensslsource code, which is compiled by the following command ]:
1) execute the command: Perl configure VC-WIN32 no-ASM
2) execute the command: Ms \ do_ms
3) execute the command: nmake-F Ms \ NTDLL. mak: this is a dynamic library: If the compilation is successful, the final output is under the out32dll directory, including the executable file, two DLL files, and two lib files [nmake-FMS \ nt. mak
This is the compilation command of the static library, and the output is under the out32 directory ]. Compiled successfully
4) execute the command: nmake-FMS \ NTDLL. Mak Test
5) execute the command: nmake-F Ms \ NTDLL. Mak install
VII. Test
1. Test API programming. Create a project in Vs and upload libeay32.dll and libeay32.lib under the out32dll folder generated under the OpenSSL directory to the project.
2. Set the additional library and additional include directory of the project:
Right-click the project and choose Properties> C/C ++> General> Add a directory
Right-click the project and choose Properties> linker> General> additional library directory.
3. The source code of sm3test. C is as follows:
Sm3test. c
# Include <stdio. h> # include <OpenSSL/EVP. h ># include <OpenSSL/sm3.h> # pragma comment (Lib, "libeay32.lib") Static size_t hash [8] = {0}; void out_hex (size_t * list1) {size_t I = 0; for (I = 0; I <8; I ++) {printf ("% 08x", list1 [I]);} printf ("\ r \ n");} Main (INT argc, char * argv []) {evp_md_ctx mdctx; const evp_md * md; char mess1 [] = "ABC "; char mess2 [] = "ABC"; unsigned char md_value [evp_max_md_size]; int md_len, I; // make E Vp_digest Functions Support all valid information summarization algorithms openssl_add_all_digests (); argv [1] = "Sm3"; if (! Argv [1]) {printf ("Usage: mdtest digestname \ n"); exit (1 );} // obtain the evp_md algorithm structure based on the name of the input information Summary function. md = evp_get_digestbyname (argv [1]); // MD = evp_sm3 (); If (! MD) {printf ("unknown message digest % s \ n", argv [1]); exit (1) ;}// initialize the information Summary structure mdctx, this is required when calling the evp_digestinit_ex function. Evp_md_ctx_init (& mdctx); // use the MD algorithm structure to set the mdctx structure. If impl is null, the default implementation algorithm is used (the information digest algorithm provided by OpenSSL) evp_digestinit_ex (& mdctx, MD, null); // you can call this function multiple times to process more data, evp_digestupdate (& mdctx, mess1, strlen (mess1); // evp_digestupdate (& mdctx, mess2, strlen (mess2 )); // complete the summary calculation process. The summary information is stored in md_value, And the length information is stored in md_len evp_digestfinal_ex (& mdctx, md_value, & md_len ); // use this function to release resources occupied by mdctx. If the _ ex series functions are used, this is required. Evp_md_ctx_cleanup (& mdctx); printf ("digest is:"); for (I = 0; I <md_len; I ++) printf ("% 02x ", md_value [I]); printf ("\ n"); // Sm3 ("ABC", 3, hash); // out_hex (hash ); system ("pause");} int main1 (INT argc, char * argv []) {sm3_ctx * c = (sm3_ctx *) malloc (sizeof (sm3_ctx )); sm3_init (c); // sm3_final_dword (hash, c); sm3_update (C, "ABC", 3); sm3_final (hash, c); out_hex (hash ); // 66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b release (c); sm3_update (C, "release", 64);/* for (I = 0; I <16; I ++) {sm3_update (C, "ABCD", 4);} */sm3_final (hash, c); out_hex (hash ); // debe9ff9 limit 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c01_32 // Sm3 ("ABC", 3, hash); // out_hex (hash); System ("pause "); return 0 ;}
4. Result After sm3test. C is run and "ABC" is summarized using the Sm3 Algorithm
The examples in the appendix of the Chinese National Standard are the same:
VIII. Summary
In this example, the Digest algorithm is used as an example to introduce how to add a new algorithm in OpenSSL by directly adding source code, rather than the engine method. Of course, if the engine method is more convenient, ignore this article. This article only describes how to do it, but does not explain why. For example, the encapsulation mechanism of OpenSSL requires that the source code be interpreted to better understand why those steps are required in the above text. Because these steps are complicated enough, the interpretation of the source code will start with another article. This article is only for the use of Huludao. To understand the principles, please read other materials or interpret the source code yourself, or wait for my next article.
Please contact me if you have any questions or correct me. Thank you!
Thank you! Good luck!
Complete steps for adding a new algorithm to OpenSSL by using the source code method (example: Digest algorithm Sm3) [non-engine method]