简单例子
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
int main(int arc, char *argv[])
{
/* Load the human readable error strings for libcrypto */
ERR_load_crypto_strings();
/* Load all digest and cipher algorithms */
OpenSSL_add_all_algorithms();//#1
/* Load config file, and other important initialisation */
OPENSSL_config(NULL);
/* ... Do some crypto stuff here ... */
/* Clean up */
/* Removes all digests and ciphers */
EVP_cleanup();
/* if you omit the next, a small leak may be left when you make use of the BIO (low level API) for e.g. base64 transformations */
CRYPTO_cleanup_all_ex_data();
/* Remove error strings */
ERR_free_strings();
return 0;
}
上层接口
又称EVP接口,即封装的接口
提供了一套包括对称和非对称的加密解密函数,签名验签,生成哈希和MAC编码的方法。
底层接口
直接接触独立的算法,但是在FIPS模式下运行时,底层接口不可用。
应答码
成功返回1,失败返回0
if(1 != EVP_xxx()) goto err;
if(1 != EVP_yyy()) goto err;
/* ... do some stuff ... */
err:
ERR_print_errors_fp(stderr);
但是并不是所有的都这样,避免粗心的方法是这么写
if (1 != some_openssl_function())
/* handle error */
线程安全性
目前openssl默认是线程不安全的。
调用者需要提供各种回调方法来加锁,原子整数加法和线程Id检测。
可以使用CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK)和CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK) 来设置有threadid,,dynlock和add_lock的回调。
未来,openssl调本地线程将是自初始化线程安全的。
Fork安全性
目前openssl的库函数方法并不都是异步信号安全的。
因此,不要在signal handlers中调用openssl函数;
不要在fork方法(exec或者_exit)的子进程中调用openssl函数;
不要在pthread_atfork() handlers中调用openssl函数(fork自身是而且必须是异步信号安全的)。
初始化方法
# define OpenSSL_add_all_algorithms() \
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
| OPENSSL_INIT_ADD_ALL_DIGESTS \
| OPENSSL_INIT_LOAD_CONFIG, NULL)
/*
* If this function is called with a non NULL settings value then it must be
* called prior to any threads making calls to any OpenSSL functions,
* i.e. passing a non-null settings value is assumed to be single-threaded.
*/
int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)来自init.c
{
static int stoperrset = 0;
if (stopped) {
if (!stoperrset) {
/*
* We only ever set this once to avoid getting into an infinite
* loop where the error system keeps trying to init and fails so
* sets an error etc
*/
stoperrset = 1;
CRYPTOerr(CRYPTO_F_OPENSSL_INIT_CRYPTO, ERR_R_INIT_FAIL);
}
return 0;
}
if (!base_inited && !RUN_ONCE(&base, ossl_init_base))
return 0;
if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS)
&& !RUN_ONCE(&load_crypto_strings,
ossl_init_no_load_crypto_strings))
return 0;
if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
&& !RUN_ONCE(&load_crypto_strings, ossl_init_load_crypto_strings))
return 0;
if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS)
&& !RUN_ONCE(&add_all_ciphers, ossl_init_no_add_algs))
return 0;
if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS)
&& !RUN_ONCE(&add_all_ciphers, ossl_init_add_all_ciphers))
return 0;
if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS)
&& !RUN_ONCE(&add_all_digests, ossl_init_no_add_algs))
return 0;
if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS)
&& !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests))
return 0;
if ((opts & OPENSSL_INIT_ATFORK)
&& !openssl_init_fork_handlers())
return 0;
if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG)
&& !RUN_ONCE(&config, ossl_init_no_config))
return 0;
if (opts & OPENSSL_INIT_LOAD_CONFIG) {
int ret;
CRYPTO_THREAD_write_lock(init_lock);
appname = (settings == NULL) ? NULL : settings->appname;
ret = RUN_ONCE(&config, ossl_init_config);
CRYPTO_THREAD_unlock(init_lock);
if (!ret)
return 0;
}
if ((opts & OPENSSL_INIT_ASYNC)
&& !RUN_ONCE(&async, ossl_init_async))
return 0;
#ifndef OPENSSL_NO_ENGINE
if ((opts & OPENSSL_INIT_ENGINE_OPENSSL)
&& !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl))
return 0;
# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG)
if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
&& !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
return 0;
# endif
# ifndef OPENSSL_NO_RDRAND
if ((opts & OPENSSL_INIT_ENGINE_RDRAND)
&& !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand))
return 0;
# endif
if ((opts & OPENSSL_INIT_ENGINE_DYNAMIC)
&& !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic))
return 0;
# ifndef OPENSSL_NO_STATIC_ENGINE
# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
if ((opts & OPENSSL_INIT_ENGINE_PADLOCK)
&& !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock))
return 0;
# endif
# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
if ((opts & OPENSSL_INIT_ENGINE_CAPI)
&& !RUN_ONCE(&engine_capi, ossl_init_engine_capi))
return 0;
# endif
# if !defined(OPENSSL_NO_AFALGENG)
if ((opts & OPENSSL_INIT_ENGINE_AFALG)
&& !RUN_ONCE(&engine_afalg, ossl_init_engine_afalg))
return 0;
# endif
# endif
if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN
| OPENSSL_INIT_ENGINE_OPENSSL
| OPENSSL_INIT_ENGINE_AFALG)) {
ENGINE_register_all_complete();
}
#endif
#ifndef OPENSSL_NO_COMP
if ((opts & OPENSSL_INIT_ZLIB)
&& !RUN_ONCE(&zlib, ossl_init_zlib))
return 0;
#endif
return 1;
}
在openssl源码中提供了一些demo可以看一下如何使用的。
cms_comp.c
cms_ddec.c
cms_dec.c
cms_denc.c
cms_enc.c
cms_sign.c
cms_sign2.c
cms_uncomp.c
cms_ver.c
pkread.c
pkwrite.c
smdec.c
smenc.c
smsign.c
smsign2.c
smver.c