lsquic_crypto.c revision e0197994
150aadb33SDmitri Tikhonov/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */ 250aadb33SDmitri Tikhonov#include <assert.h> 350aadb33SDmitri Tikhonov#include <string.h> 450aadb33SDmitri Tikhonov 550aadb33SDmitri Tikhonov#include <openssl/ssl.h> 650aadb33SDmitri Tikhonov#include <openssl/crypto.h> 750aadb33SDmitri Tikhonov#include <openssl/stack.h> 850aadb33SDmitri Tikhonov#include <openssl/x509.h> 950aadb33SDmitri Tikhonov#include <openssl/rand.h> 1050aadb33SDmitri Tikhonov#include <openssl/curve25519.h> 11e0197994SDmitri Tikhonov#include <openssl/hmac.h> 1250aadb33SDmitri Tikhonov 1350aadb33SDmitri Tikhonov#include <zlib.h> 1450aadb33SDmitri Tikhonov 1550aadb33SDmitri Tikhonov#include "lsquic_types.h" 1650aadb33SDmitri Tikhonov#include "lsquic_crypto.h" 1750aadb33SDmitri Tikhonov#include "lsquic_alarmset.h" 1850aadb33SDmitri Tikhonov#include "lsquic_parse.h" 1950aadb33SDmitri Tikhonov#include "lsquic_util.h" 2050aadb33SDmitri Tikhonov#include "lsquic_str.h" 2150aadb33SDmitri Tikhonov 2250aadb33SDmitri Tikhonov#define LSQUIC_LOGGER_MODULE LSQLM_CRYPTO 2350aadb33SDmitri Tikhonov#include "lsquic_logger.h" 2450aadb33SDmitri Tikhonov 2550aadb33SDmitri Tikhonov 2650aadb33SDmitri Tikhonovstatic const char s_hs_signature[] = "QUIC CHLO and server config signature"; 2750aadb33SDmitri Tikhonovstatic int crypto_inited = 0; 2850aadb33SDmitri Tikhonov 2950aadb33SDmitri Tikhonov 3050aadb33SDmitri Tikhonovvoid rand_bytes(void *data, int len) 3150aadb33SDmitri Tikhonov{ 3250aadb33SDmitri Tikhonov RAND_bytes(data, len); 3350aadb33SDmitri Tikhonov} 3450aadb33SDmitri Tikhonov 3550aadb33SDmitri Tikhonov 3650aadb33SDmitri Tikhonovuint64_t fnv1a_64(const uint8_t * data, int len) 3750aadb33SDmitri Tikhonov{ 3850aadb33SDmitri Tikhonov uint64_t hash = UINT64_C(14695981039346656037); 3950aadb33SDmitri Tikhonov const uint8_t *end = data + len; 4050aadb33SDmitri Tikhonov while(data < end) 4150aadb33SDmitri Tikhonov { 4250aadb33SDmitri Tikhonov hash ^= *data; 4350aadb33SDmitri Tikhonov hash *= UINT64_C(1099511628211); 4450aadb33SDmitri Tikhonov ++data; 4550aadb33SDmitri Tikhonov } 4650aadb33SDmitri Tikhonov return hash; 4750aadb33SDmitri Tikhonov} 4850aadb33SDmitri Tikhonov 4950aadb33SDmitri Tikhonov 5050aadb33SDmitri Tikhonovvoid fnv1a_64_s(const uint8_t * data, int len, char *md) 5150aadb33SDmitri Tikhonov{ 5250aadb33SDmitri Tikhonov uint64_t hash = fnv1a_64(data, len); 5350aadb33SDmitri Tikhonov memcpy(md, (void *)&hash, 8); 5450aadb33SDmitri Tikhonov} 5550aadb33SDmitri Tikhonov 5650aadb33SDmitri Tikhonov 5750aadb33SDmitri Tikhonov#if defined( __x86_64 )||defined( __x86_64__ ) 5850aadb33SDmitri Tikhonov 5950aadb33SDmitri Tikhonovstatic uint128 s_prime; 6050aadb33SDmitri Tikhonovstatic uint128 s_init_hash; 6150aadb33SDmitri Tikhonov 6250aadb33SDmitri Tikhonov 6350aadb33SDmitri Tikhonovstatic inline void make_uint128(uint128 *v, uint64_t hi, uint64_t lo) 6450aadb33SDmitri Tikhonov{ 6550aadb33SDmitri Tikhonov *v = hi; 6650aadb33SDmitri Tikhonov *v <<= 64; 6750aadb33SDmitri Tikhonov *v += lo; 6850aadb33SDmitri Tikhonov} 6950aadb33SDmitri Tikhonov 7050aadb33SDmitri Tikhonov 7150aadb33SDmitri Tikhonovvoid fnv1a_inc(uint128 *hash, const uint8_t *data, int len) 7250aadb33SDmitri Tikhonov{ 7350aadb33SDmitri Tikhonov const uint8_t* end = data + len; 7450aadb33SDmitri Tikhonov while(data < end) 7550aadb33SDmitri Tikhonov { 7650aadb33SDmitri Tikhonov *hash = (*hash ^ (*data)) * s_prime; 7750aadb33SDmitri Tikhonov ++data; 7850aadb33SDmitri Tikhonov } 7950aadb33SDmitri Tikhonov} 8050aadb33SDmitri Tikhonov 8150aadb33SDmitri Tikhonovuint128 fnv1a_128_2(const uint8_t * data1, int len1, const uint8_t *data2, int len2) 8250aadb33SDmitri Tikhonov{ 8350aadb33SDmitri Tikhonov uint128 hash; 8450aadb33SDmitri Tikhonov memcpy(&hash, &s_init_hash, 16); 8550aadb33SDmitri Tikhonov 8650aadb33SDmitri Tikhonov fnv1a_inc(&hash, data1, len1); 8750aadb33SDmitri Tikhonov if (data2) 8850aadb33SDmitri Tikhonov fnv1a_inc(&hash, data2, len2); 8950aadb33SDmitri Tikhonov return hash; 9050aadb33SDmitri Tikhonov} 9150aadb33SDmitri Tikhonov 9250aadb33SDmitri Tikhonovuint128 fnv1a_128_3(const uint8_t *data1, int len1, 9350aadb33SDmitri Tikhonov const uint8_t *data2, int len2, 9450aadb33SDmitri Tikhonov const uint8_t *data3, int len3) 9550aadb33SDmitri Tikhonov{ 9650aadb33SDmitri Tikhonov uint128 hash; 9750aadb33SDmitri Tikhonov memcpy(&hash, &s_init_hash, 16); 9850aadb33SDmitri Tikhonov 9950aadb33SDmitri Tikhonov fnv1a_inc(&hash, data1, len1); 10050aadb33SDmitri Tikhonov fnv1a_inc(&hash, data2, len2); 10150aadb33SDmitri Tikhonov fnv1a_inc(&hash, data3, len3); 10250aadb33SDmitri Tikhonov return hash; 10350aadb33SDmitri Tikhonov} 10450aadb33SDmitri Tikhonov 10550aadb33SDmitri Tikhonovvoid fnv1a_128_2_s(const uint8_t * data1, int len1, const uint8_t * data2, int len2, uint8_t *md) 10650aadb33SDmitri Tikhonov{ 10750aadb33SDmitri Tikhonov uint128 hash = fnv1a_128_2(data1, len1, data2, len2); 10850aadb33SDmitri Tikhonov memcpy(md, (void *)&hash, 16); 10950aadb33SDmitri Tikhonov} 11050aadb33SDmitri Tikhonov 11150aadb33SDmitri Tikhonov/* HS_PKT_HASH_LENGTH bytes of md */ 11250aadb33SDmitri Tikhonovvoid serialize_fnv128_short(uint128 v, uint8_t *md) 11350aadb33SDmitri Tikhonov{ 11450aadb33SDmitri Tikhonov memcpy(md, (void *)&v, 12); 11550aadb33SDmitri Tikhonov} 11650aadb33SDmitri Tikhonov 11750aadb33SDmitri Tikhonov#else 11850aadb33SDmitri Tikhonovuint128 *uint128_times(uint128 *v, const uint128 *factor) 11950aadb33SDmitri Tikhonov{ 12050aadb33SDmitri Tikhonov uint64_t a96 = v->hi_ >> 32; 12150aadb33SDmitri Tikhonov uint64_t a64 = v->hi_ & 0xffffffffu; 12250aadb33SDmitri Tikhonov uint64_t a32 = v->lo_ >> 32; 12350aadb33SDmitri Tikhonov uint64_t a00 = v->lo_ & 0xffffffffu; 12450aadb33SDmitri Tikhonov uint64_t b96 = factor->hi_ >> 32; 12550aadb33SDmitri Tikhonov uint64_t b64 = factor->hi_ & 0xffffffffu; 12650aadb33SDmitri Tikhonov uint64_t b32 = factor->lo_ >> 32; 12750aadb33SDmitri Tikhonov uint64_t b00 = factor->lo_ & 0xffffffffu; 12850aadb33SDmitri Tikhonov uint64_t tmp, lolo; 12950aadb33SDmitri Tikhonov // multiply [a96 .. a00] x [b96 .. b00] 13050aadb33SDmitri Tikhonov // terms higher than c96 disappear off the high side 13150aadb33SDmitri Tikhonov // terms c96 and c64 are safe to ignore carry bit 13250aadb33SDmitri Tikhonov uint64_t c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96; 13350aadb33SDmitri Tikhonov uint64_t c64 = a64 * b00 + a32 * b32 + a00 * b64; 13450aadb33SDmitri Tikhonov v->hi_ = (c96 << 32) + c64; 13550aadb33SDmitri Tikhonov v->lo_ = 0; 13650aadb33SDmitri Tikhonov 13750aadb33SDmitri Tikhonov tmp = a32 * b00; 13850aadb33SDmitri Tikhonov v->hi_ += tmp >> 32; 13950aadb33SDmitri Tikhonov v->lo_ += tmp << 32; 14050aadb33SDmitri Tikhonov 14150aadb33SDmitri Tikhonov tmp = a00 * b32; 14250aadb33SDmitri Tikhonov v->hi_ += tmp >> 32; 14350aadb33SDmitri Tikhonov v->lo_ += tmp << 32; 14450aadb33SDmitri Tikhonov 14550aadb33SDmitri Tikhonov tmp = a00 * b00; 14650aadb33SDmitri Tikhonov lolo = v->lo_ + tmp; 14750aadb33SDmitri Tikhonov if (lolo < v->lo_) 14850aadb33SDmitri Tikhonov ++v->hi_; 14950aadb33SDmitri Tikhonov v->lo_ = lolo; 15050aadb33SDmitri Tikhonov 15150aadb33SDmitri Tikhonov return v; 15250aadb33SDmitri Tikhonov} 15350aadb33SDmitri Tikhonov 15450aadb33SDmitri Tikhonovvoid fnv1a_inc(uint128 *hash, const uint8_t * data, int len) 15550aadb33SDmitri Tikhonov{ 15650aadb33SDmitri Tikhonov static const uint128 kPrime = {16777216, 315}; 15750aadb33SDmitri Tikhonov const uint8_t* end = data + len; 15850aadb33SDmitri Tikhonov while(data < end) 15950aadb33SDmitri Tikhonov { 16050aadb33SDmitri Tikhonov hash->lo_ = (hash->lo_ ^ (uint64_t)*data); 16150aadb33SDmitri Tikhonov uint128_times(hash, &kPrime); 16250aadb33SDmitri Tikhonov ++data; 16350aadb33SDmitri Tikhonov } 16450aadb33SDmitri Tikhonov} 16550aadb33SDmitri Tikhonov 16650aadb33SDmitri Tikhonov 16750aadb33SDmitri Tikhonovuint128 fnv1a_128_2(const uint8_t * data1, int len1, const uint8_t * data2, int len2) 16850aadb33SDmitri Tikhonov{ 16950aadb33SDmitri Tikhonov uint128 hash = {UINT64_C(7809847782465536322), UINT64_C(7113472399480571277)}; 17050aadb33SDmitri Tikhonov fnv1a_inc(&hash, data1, len1); 17150aadb33SDmitri Tikhonov if (data2) 17250aadb33SDmitri Tikhonov fnv1a_inc(&hash, data2, len2); 17350aadb33SDmitri Tikhonov return hash; 17450aadb33SDmitri Tikhonov} 17550aadb33SDmitri Tikhonov 17650aadb33SDmitri Tikhonov 17750aadb33SDmitri Tikhonovuint128 fnv1a_128_3(const uint8_t * data1, int len1, 17850aadb33SDmitri Tikhonov const uint8_t * data2, int len2, 17950aadb33SDmitri Tikhonov const uint8_t * data3, int len3) 18050aadb33SDmitri Tikhonov{ 18150aadb33SDmitri Tikhonov uint128 hash = {UINT64_C(7809847782465536322), UINT64_C(7113472399480571277)}; 18250aadb33SDmitri Tikhonov fnv1a_inc(&hash, data1, len1); 18350aadb33SDmitri Tikhonov fnv1a_inc(&hash, data2, len2); 18450aadb33SDmitri Tikhonov fnv1a_inc(&hash, data3, len3); 18550aadb33SDmitri Tikhonov return hash; 18650aadb33SDmitri Tikhonov} 18750aadb33SDmitri Tikhonov 18850aadb33SDmitri Tikhonov 18950aadb33SDmitri Tikhonovvoid fnv1a_128_2_s(const uint8_t * data1, int len1, const uint8_t * data2, int len2, uint8_t *md) 19050aadb33SDmitri Tikhonov{ 19150aadb33SDmitri Tikhonov uint128 hash = fnv1a_128_2(data1, len1, data2, len2); 19250aadb33SDmitri Tikhonov memcpy(md, (void *)&hash.lo_, 8); 19350aadb33SDmitri Tikhonov memcpy(md + 8, (void *)&hash.hi_, 8); 19450aadb33SDmitri Tikhonov} 19550aadb33SDmitri Tikhonov 19650aadb33SDmitri Tikhonov/* HS_PKT_HASH_LENGTH bytes of md */ 19750aadb33SDmitri Tikhonovvoid serialize_fnv128_short(uint128 v, uint8_t *md) 19850aadb33SDmitri Tikhonov{ 19950aadb33SDmitri Tikhonov assert(HS_PKT_HASH_LENGTH == 8 + 4); 20050aadb33SDmitri Tikhonov memcpy(md, (void *)&v.lo_, 8); 20150aadb33SDmitri Tikhonov memcpy(md + 8, (void *)&v.hi_, 4); 20250aadb33SDmitri Tikhonov} 20350aadb33SDmitri Tikhonov 20450aadb33SDmitri Tikhonov#endif 20550aadb33SDmitri Tikhonov 20650aadb33SDmitri Tikhonovuint128 fnv1a_128(const uint8_t * data, int len) 20750aadb33SDmitri Tikhonov{ 20850aadb33SDmitri Tikhonov return fnv1a_128_2(data, len , NULL, 0); 20950aadb33SDmitri Tikhonov} 21050aadb33SDmitri Tikhonov 21150aadb33SDmitri Tikhonov 21250aadb33SDmitri Tikhonovvoid fnv1a_128_s(const uint8_t * data, int len, uint8_t *md) 21350aadb33SDmitri Tikhonov{ 21450aadb33SDmitri Tikhonov return fnv1a_128_2_s(data, len, NULL, 0, md); 21550aadb33SDmitri Tikhonov} 21650aadb33SDmitri Tikhonov 21750aadb33SDmitri Tikhonov 21850aadb33SDmitri Tikhonov/* packet data = header + MD + payload */ 21950aadb33SDmitri Tikhonov/* return 0 if OK */ 22050aadb33SDmitri Tikhonovint verify_hs_pkt(const uint8_t *pkg_data, size_t header_len, size_t pkg_len) 22150aadb33SDmitri Tikhonov{ 22250aadb33SDmitri Tikhonov uint8_t md[HS_PKT_HASH_LENGTH]; 22350aadb33SDmitri Tikhonov uint128 hash; 22450aadb33SDmitri Tikhonov if (pkg_len < header_len + HS_PKT_HASH_LENGTH) 22550aadb33SDmitri Tikhonov return -1; 22650aadb33SDmitri Tikhonov 22750aadb33SDmitri Tikhonov hash = fnv1a_128_2(pkg_data, header_len, pkg_data + header_len + HS_PKT_HASH_LENGTH, 22850aadb33SDmitri Tikhonov pkg_len - header_len - HS_PKT_HASH_LENGTH); 22950aadb33SDmitri Tikhonov serialize_fnv128_short(hash, md); 23050aadb33SDmitri Tikhonov return memcmp(md, pkg_data + header_len, HS_PKT_HASH_LENGTH); 23150aadb33SDmitri Tikhonov} 23250aadb33SDmitri Tikhonov 23350aadb33SDmitri Tikhonov/* packet data = header + MD + payload, update the MD part */ 23450aadb33SDmitri Tikhonovint update_hs_pkt_hash(uint8_t *pkg_data, int header_len, int pkg_len) 23550aadb33SDmitri Tikhonov{ 23650aadb33SDmitri Tikhonov uint8_t md[HS_PKT_HASH_LENGTH]; 23750aadb33SDmitri Tikhonov uint128 hash; 23850aadb33SDmitri Tikhonov if (pkg_len < header_len + HS_PKT_HASH_LENGTH) 23950aadb33SDmitri Tikhonov return -1; 24050aadb33SDmitri Tikhonov 24150aadb33SDmitri Tikhonov hash = fnv1a_128_2(pkg_data, header_len, pkg_data + header_len + HS_PKT_HASH_LENGTH, 24250aadb33SDmitri Tikhonov pkg_len - header_len - HS_PKT_HASH_LENGTH); 24350aadb33SDmitri Tikhonov serialize_fnv128_short(hash, md); 24450aadb33SDmitri Tikhonov memcpy(pkg_data + header_len, md, HS_PKT_HASH_LENGTH); 24550aadb33SDmitri Tikhonov return 0; 24650aadb33SDmitri Tikhonov} 24750aadb33SDmitri Tikhonov 24850aadb33SDmitri Tikhonovint get_hs_pkt_hash_len() 24950aadb33SDmitri Tikhonov{ 25050aadb33SDmitri Tikhonov return HS_PKT_HASH_LENGTH; 25150aadb33SDmitri Tikhonov} 25250aadb33SDmitri Tikhonov 25350aadb33SDmitri Tikhonov 25450aadb33SDmitri Tikhonovvoid sha256(const uint8_t *buf, int len, uint8_t *h) 25550aadb33SDmitri Tikhonov{ 25650aadb33SDmitri Tikhonov SHA256_CTX ctx; 25750aadb33SDmitri Tikhonov SHA256_Init(&ctx); 25850aadb33SDmitri Tikhonov SHA256_Update(&ctx, buf, len); 25950aadb33SDmitri Tikhonov SHA256_Final(h, &ctx); 26050aadb33SDmitri Tikhonov} 26150aadb33SDmitri Tikhonov 26250aadb33SDmitri Tikhonov 26350aadb33SDmitri Tikhonov/* base on rfc 5869 with sha256, prk is 32 bytes*/ 26450aadb33SDmitri Tikhonovvoid lshkdf_extract(const unsigned char *ikm, int ikm_len, const unsigned char *salt, 26550aadb33SDmitri Tikhonov int salt_len, unsigned char *prk) 26650aadb33SDmitri Tikhonov{ 26750aadb33SDmitri Tikhonov#ifndef NDEBUG 26850aadb33SDmitri Tikhonov unsigned char *out; 26950aadb33SDmitri Tikhonov unsigned int out_len; 27050aadb33SDmitri Tikhonov out = 27150aadb33SDmitri Tikhonov#endif 27250aadb33SDmitri Tikhonov HMAC(EVP_sha256(), salt, salt_len, ikm, ikm_len, prk, 27350aadb33SDmitri Tikhonov#ifndef NDEBUG 27450aadb33SDmitri Tikhonov &out_len 27550aadb33SDmitri Tikhonov#else 27650aadb33SDmitri Tikhonov NULL 27750aadb33SDmitri Tikhonov#endif 27850aadb33SDmitri Tikhonov ); 27950aadb33SDmitri Tikhonov assert(out); 28050aadb33SDmitri Tikhonov assert(out_len == 32); 28150aadb33SDmitri Tikhonov} 28250aadb33SDmitri Tikhonov 28350aadb33SDmitri Tikhonov 28450aadb33SDmitri Tikhonovint lshkdf_expand(const unsigned char *prk, const unsigned char *info, int info_len, 28550aadb33SDmitri Tikhonov uint16_t c_key_len, uint8_t *c_key, 28650aadb33SDmitri Tikhonov uint16_t s_key_len, uint8_t *s_key, 28750aadb33SDmitri Tikhonov uint16_t c_key_iv_len, uint8_t *c_key_iv, 28850aadb33SDmitri Tikhonov uint16_t s_key_iv_len, uint8_t *s_key_iv, 28950aadb33SDmitri Tikhonov uint16_t sub_key_len, uint8_t *sub_key) 29050aadb33SDmitri Tikhonov{ 29150aadb33SDmitri Tikhonov const int SHA256LEN = 32; 29250aadb33SDmitri Tikhonov int L = c_key_len + s_key_len + c_key_iv_len + s_key_iv_len + sub_key_len; 29350aadb33SDmitri Tikhonov int N = (L + SHA256LEN - 1) / SHA256LEN; 29450aadb33SDmitri Tikhonov unsigned char *p_org; 29550aadb33SDmitri Tikhonov uint8_t *buf; 29650aadb33SDmitri Tikhonov unsigned char *p; 29750aadb33SDmitri Tikhonov unsigned char T[SHA256LEN + 1]; 29850aadb33SDmitri Tikhonov int T_len = 0; 29950aadb33SDmitri Tikhonov int i; 30050aadb33SDmitri Tikhonov uint8_t *pb; 30150aadb33SDmitri Tikhonov 30250aadb33SDmitri Tikhonov p_org = malloc(N * SHA256LEN); 30350aadb33SDmitri Tikhonov if (!p_org) 30450aadb33SDmitri Tikhonov return -1; 30550aadb33SDmitri Tikhonov 30650aadb33SDmitri Tikhonov buf = malloc(SHA256LEN + info_len + 13); 30750aadb33SDmitri Tikhonov if (!buf) 30850aadb33SDmitri Tikhonov { 30950aadb33SDmitri Tikhonov free(p_org); 31050aadb33SDmitri Tikhonov return -1; 31150aadb33SDmitri Tikhonov } 31250aadb33SDmitri Tikhonov 31350aadb33SDmitri Tikhonov p = p_org; 31450aadb33SDmitri Tikhonov 31550aadb33SDmitri Tikhonov for (i = 1; i <= N; ++i) 31650aadb33SDmitri Tikhonov { 31750aadb33SDmitri Tikhonov pb = buf; 31850aadb33SDmitri Tikhonov if (T_len > 0) 31950aadb33SDmitri Tikhonov { 32050aadb33SDmitri Tikhonov memcpy(pb, T, T_len); 32150aadb33SDmitri Tikhonov pb += T_len; 32250aadb33SDmitri Tikhonov } 32350aadb33SDmitri Tikhonov 32450aadb33SDmitri Tikhonov memcpy(pb, info, info_len); 32550aadb33SDmitri Tikhonov pb += info_len; 32650aadb33SDmitri Tikhonov *pb = i; 32750aadb33SDmitri Tikhonov ++pb; 32850aadb33SDmitri Tikhonov 32950aadb33SDmitri Tikhonov HMAC(EVP_sha256(), prk, SHA256LEN, buf, pb - buf, T, NULL); 33050aadb33SDmitri Tikhonov if (i != N) 33150aadb33SDmitri Tikhonov T_len = SHA256LEN; 33250aadb33SDmitri Tikhonov else 33350aadb33SDmitri Tikhonov T_len = L - (N - 1) * SHA256LEN; 33450aadb33SDmitri Tikhonov 33550aadb33SDmitri Tikhonov memcpy(p, T, T_len); 33650aadb33SDmitri Tikhonov p += T_len; 33750aadb33SDmitri Tikhonov } 33850aadb33SDmitri Tikhonov 33950aadb33SDmitri Tikhonov free(buf); 34050aadb33SDmitri Tikhonov 34150aadb33SDmitri Tikhonov p = p_org; 34250aadb33SDmitri Tikhonov if (c_key_len) 34350aadb33SDmitri Tikhonov { 34450aadb33SDmitri Tikhonov memcpy(c_key, p, c_key_len); 34550aadb33SDmitri Tikhonov p += c_key_len; 34650aadb33SDmitri Tikhonov } 34750aadb33SDmitri Tikhonov if (s_key_len) 34850aadb33SDmitri Tikhonov { 34950aadb33SDmitri Tikhonov memcpy(s_key, p, s_key_len); 35050aadb33SDmitri Tikhonov p += s_key_len; 35150aadb33SDmitri Tikhonov } 35250aadb33SDmitri Tikhonov if (c_key_iv_len) 35350aadb33SDmitri Tikhonov { 35450aadb33SDmitri Tikhonov memcpy(c_key_iv, p, c_key_iv_len); 35550aadb33SDmitri Tikhonov p += c_key_iv_len; 35650aadb33SDmitri Tikhonov } 35750aadb33SDmitri Tikhonov if (s_key_iv_len) 35850aadb33SDmitri Tikhonov { 35950aadb33SDmitri Tikhonov memcpy(s_key_iv, p, s_key_iv_len); 36050aadb33SDmitri Tikhonov p += s_key_iv_len; 36150aadb33SDmitri Tikhonov } 36250aadb33SDmitri Tikhonov if (sub_key_len && sub_key) 36350aadb33SDmitri Tikhonov { 36450aadb33SDmitri Tikhonov memcpy(sub_key, p, sub_key_len); 36550aadb33SDmitri Tikhonov p += sub_key_len; 36650aadb33SDmitri Tikhonov } 36750aadb33SDmitri Tikhonov 36850aadb33SDmitri Tikhonov free(p_org); 36950aadb33SDmitri Tikhonov return 0; 37050aadb33SDmitri Tikhonov} 37150aadb33SDmitri Tikhonov 37250aadb33SDmitri Tikhonov 37350aadb33SDmitri Tikhonovint export_key_material_simple(unsigned char *ikm, uint32_t ikm_len, 37450aadb33SDmitri Tikhonov unsigned char *salt, int salt_len, 37550aadb33SDmitri Tikhonov char *label, uint32_t label_len, 37650aadb33SDmitri Tikhonov const uint8_t *context, uint32_t context_len, 37750aadb33SDmitri Tikhonov uint8_t *key, uint16_t key_len) 37850aadb33SDmitri Tikhonov{ 37950aadb33SDmitri Tikhonov unsigned char prk[32]; 38050aadb33SDmitri Tikhonov int info_len; 38150aadb33SDmitri Tikhonov uint8_t *info = NULL; 38250aadb33SDmitri Tikhonov info = (uint8_t *)malloc(label_len + 1 + sizeof(uint32_t) + context_len); 38350aadb33SDmitri Tikhonov if (!info) 38450aadb33SDmitri Tikhonov return -1; 38550aadb33SDmitri Tikhonov 38650aadb33SDmitri Tikhonov lshkdf_extract(ikm, ikm_len, salt, salt_len, prk); 38750aadb33SDmitri Tikhonov memcpy(info, label, label_len); 38850aadb33SDmitri Tikhonov info[label_len] = 0x00; 38950aadb33SDmitri Tikhonov info_len = label_len + 1; 39050aadb33SDmitri Tikhonov memcpy(info + info_len, &context_len, sizeof(uint32_t)); 39150aadb33SDmitri Tikhonov info_len += sizeof(uint32_t); 39250aadb33SDmitri Tikhonov memcpy(info + info_len, context, context_len); 39350aadb33SDmitri Tikhonov info_len += context_len; 39450aadb33SDmitri Tikhonov lshkdf_expand(prk, info, info_len, key_len, key, 39550aadb33SDmitri Tikhonov 0, NULL, 0, NULL,0, NULL, 0, NULL); 39650aadb33SDmitri Tikhonov free(info); 39750aadb33SDmitri Tikhonov return 0; 39850aadb33SDmitri Tikhonov} 39950aadb33SDmitri Tikhonov 40050aadb33SDmitri Tikhonov 40150aadb33SDmitri Tikhonovint export_key_material(const unsigned char *ikm, uint32_t ikm_len, 40250aadb33SDmitri Tikhonov const unsigned char *salt, int salt_len, 40350aadb33SDmitri Tikhonov const unsigned char *context, uint32_t context_len, 40450aadb33SDmitri Tikhonov uint16_t c_key_len, uint8_t *c_key, 40550aadb33SDmitri Tikhonov uint16_t s_key_len, uint8_t *s_key, 40650aadb33SDmitri Tikhonov uint16_t c_key_iv_len, uint8_t *c_key_iv, 40750aadb33SDmitri Tikhonov uint16_t s_key_iv_len, uint8_t *s_key_iv, 40850aadb33SDmitri Tikhonov uint8_t *sub_key) 40950aadb33SDmitri Tikhonov{ 41050aadb33SDmitri Tikhonov unsigned char prk[32]; 41150aadb33SDmitri Tikhonov uint16_t sub_key_len = ikm_len; 41250aadb33SDmitri Tikhonov 41350aadb33SDmitri Tikhonov lshkdf_extract(ikm, ikm_len, salt, salt_len, prk); 41450aadb33SDmitri Tikhonov lshkdf_expand(prk, context, context_len, c_key_len, c_key, 41550aadb33SDmitri Tikhonov s_key_len, s_key, c_key_iv_len, c_key_iv, s_key_iv_len, 41650aadb33SDmitri Tikhonov s_key_iv, sub_key_len, sub_key); 41750aadb33SDmitri Tikhonov return 0; 41850aadb33SDmitri Tikhonov} 41950aadb33SDmitri Tikhonov 42050aadb33SDmitri Tikhonovvoid c255_get_pub_key(unsigned char *priv_key, unsigned char pub_key[32]) 42150aadb33SDmitri Tikhonov{ 42250aadb33SDmitri Tikhonov X25519_public_from_private(pub_key, priv_key); 42350aadb33SDmitri Tikhonov} 42450aadb33SDmitri Tikhonov 42550aadb33SDmitri Tikhonov 42650aadb33SDmitri Tikhonovint c255_gen_share_key(unsigned char *priv_key, unsigned char *peer_pub_key, unsigned char *shared_key) 42750aadb33SDmitri Tikhonov{ 42850aadb33SDmitri Tikhonov return X25519(shared_key, priv_key, peer_pub_key); 42950aadb33SDmitri Tikhonov} 43050aadb33SDmitri Tikhonov 43150aadb33SDmitri Tikhonov 43250aadb33SDmitri Tikhonov 43350aadb33SDmitri Tikhonov/* AEAD nonce is always zero */ 43450aadb33SDmitri Tikhonov/* return 0 for OK */ 43550aadb33SDmitri Tikhonovint aes_aead_enc(EVP_AEAD_CTX *key, 43650aadb33SDmitri Tikhonov const uint8_t *ad, size_t ad_len, 43750aadb33SDmitri Tikhonov const uint8_t *nonce, size_t nonce_len, 43850aadb33SDmitri Tikhonov const uint8_t *plain, size_t plain_len, 43950aadb33SDmitri Tikhonov uint8_t *cypher, size_t *cypher_len) 44050aadb33SDmitri Tikhonov{ 44150aadb33SDmitri Tikhonov int ret = 0; 44250aadb33SDmitri Tikhonov size_t max_out_len; 44350aadb33SDmitri Tikhonov max_out_len = *cypher_len;//plain_len + EVP_AEAD_max_overhead(aead_); 44450aadb33SDmitri Tikhonov assert(*cypher_len >= max_out_len); 44550aadb33SDmitri Tikhonov 44650aadb33SDmitri Tikhonov LSQ_DEBUG("***aes_aead_enc data %s", get_bin_str(plain, plain_len, 40)); 44750aadb33SDmitri Tikhonov ret = EVP_AEAD_CTX_seal(key, cypher, cypher_len, max_out_len, 44850aadb33SDmitri Tikhonov nonce, nonce_len, plain, plain_len, ad, ad_len); 44950aadb33SDmitri Tikhonov// LSQ_DEBUG("***aes_aead_enc nonce: %s", get_bin_str(nonce, nonce_len)); 45050aadb33SDmitri Tikhonov// LSQ_DEBUG("***aes_aead_enc AD: %s", get_bin_str(ad, ad_len)); 45150aadb33SDmitri Tikhonov// LSQ_DEBUG("***aes_aead_enc return %d", (ret ? 0 : -1)); 45250aadb33SDmitri Tikhonov if (ret) 45350aadb33SDmitri Tikhonov { 45450aadb33SDmitri Tikhonov LSQ_DEBUG("***aes_aead_enc succeed, cypher content %s", 45550aadb33SDmitri Tikhonov get_bin_str(cypher, *cypher_len, 40)); 45650aadb33SDmitri Tikhonov return 0; 45750aadb33SDmitri Tikhonov } 45850aadb33SDmitri Tikhonov else 45950aadb33SDmitri Tikhonov { 46050aadb33SDmitri Tikhonov LSQ_DEBUG("***aes_aead_enc failed."); 46150aadb33SDmitri Tikhonov return -1; 46250aadb33SDmitri Tikhonov } 46350aadb33SDmitri Tikhonov} 46450aadb33SDmitri Tikhonov 46550aadb33SDmitri Tikhonov 46650aadb33SDmitri Tikhonov/* return 0 for OK */ 46750aadb33SDmitri Tikhonovint aes_aead_dec(EVP_AEAD_CTX *key, 46850aadb33SDmitri Tikhonov const uint8_t *ad, size_t ad_len, 46950aadb33SDmitri Tikhonov const uint8_t *nonce, size_t nonce_len, 47050aadb33SDmitri Tikhonov const uint8_t *cypher, size_t cypher_len, 47150aadb33SDmitri Tikhonov uint8_t *plain, size_t *plain_len) 47250aadb33SDmitri Tikhonov{ 47350aadb33SDmitri Tikhonov int ret = 0; 47450aadb33SDmitri Tikhonov size_t max_out_len = *plain_len; 47550aadb33SDmitri Tikhonov assert(max_out_len >= cypher_len); 47650aadb33SDmitri Tikhonov 47750aadb33SDmitri Tikhonov LSQ_DEBUG("***aes_aead_dec data %s", get_bin_str(cypher, cypher_len, 40)); 47850aadb33SDmitri Tikhonov 47950aadb33SDmitri Tikhonov 48050aadb33SDmitri Tikhonov ret = EVP_AEAD_CTX_open(key, plain, plain_len, max_out_len, 48150aadb33SDmitri Tikhonov nonce, nonce_len, cypher, cypher_len, ad, ad_len); 48250aadb33SDmitri Tikhonov 48350aadb33SDmitri Tikhonov// LSQ_DEBUG("***aes_aead_dec nonce: %s", get_bin_str(nonce, nonce_len)); 48450aadb33SDmitri Tikhonov// LSQ_DEBUG("***aes_aead_dec AD: %s", get_bin_str(ad, ad_len)); 48550aadb33SDmitri Tikhonov// LSQ_DEBUG("***aes_aead_dec return %d", (ret ? 0 : -1)); 48650aadb33SDmitri Tikhonov if (ret) 48750aadb33SDmitri Tikhonov { 48850aadb33SDmitri Tikhonov LSQ_DEBUG("***aes_aead_dec succeed, plain content %s", 48950aadb33SDmitri Tikhonov get_bin_str(plain, *plain_len, 20)); 49050aadb33SDmitri Tikhonov return 0; 49150aadb33SDmitri Tikhonov } 49250aadb33SDmitri Tikhonov else 49350aadb33SDmitri Tikhonov { 49450aadb33SDmitri Tikhonov LSQ_DEBUG("***aes_aead_dec failed."); 49550aadb33SDmitri Tikhonov return -1; 49650aadb33SDmitri Tikhonov } 49750aadb33SDmitri Tikhonov} 49850aadb33SDmitri Tikhonov 49950aadb33SDmitri Tikhonov/* aes 128, 16 bytes */ 50050aadb33SDmitri Tikhonovint aes_get_key_length() 50150aadb33SDmitri Tikhonov{ 50250aadb33SDmitri Tikhonov return 16; 50350aadb33SDmitri Tikhonov} 50450aadb33SDmitri Tikhonov 50550aadb33SDmitri Tikhonovvoid gen_nonce_s(char *buf, int length) 50650aadb33SDmitri Tikhonov{ 50750aadb33SDmitri Tikhonov rand_bytes(buf, length); 50850aadb33SDmitri Tikhonov} 50950aadb33SDmitri Tikhonov 51050aadb33SDmitri Tikhonov/* 32 bytes client nonce with 4 bytes tm, 8 bytes orbit */ 51150aadb33SDmitri Tikhonovvoid gen_nonce_c(unsigned char *buf, uint64_t orbit) 51250aadb33SDmitri Tikhonov{ 51350aadb33SDmitri Tikhonov time_t tm = time(NULL); 51450aadb33SDmitri Tikhonov unsigned char *p = buf; 51550aadb33SDmitri Tikhonov memcpy(p, &tm, 4); 51650aadb33SDmitri Tikhonov p += 4; 51750aadb33SDmitri Tikhonov memcpy(p, &orbit, 8); 51850aadb33SDmitri Tikhonov p += 8; 51950aadb33SDmitri Tikhonov rand_bytes(p, 20); 52050aadb33SDmitri Tikhonov p += 20; 52150aadb33SDmitri Tikhonov} 52250aadb33SDmitri Tikhonov 52350aadb33SDmitri Tikhonov 52450aadb33SDmitri TikhonovEVP_PKEY *PEM_to_key(const char *buf, int len) 52550aadb33SDmitri Tikhonov{ 52650aadb33SDmitri Tikhonov RSA *rsa = NULL; 52750aadb33SDmitri Tikhonov EVP_PKEY *key = EVP_PKEY_new(); 52850aadb33SDmitri Tikhonov BIO *bio = BIO_new_mem_buf(buf, len); 52950aadb33SDmitri Tikhonov if (!bio || !key) 53050aadb33SDmitri Tikhonov return NULL; 53150aadb33SDmitri Tikhonov 53250aadb33SDmitri Tikhonov rsa = PEM_read_bio_RSAPrivateKey(bio, &rsa, NULL, NULL); 53350aadb33SDmitri Tikhonov if (!rsa) 53450aadb33SDmitri Tikhonov return NULL; 53550aadb33SDmitri Tikhonov 53650aadb33SDmitri Tikhonov EVP_PKEY_assign_RSA(key, rsa); 53750aadb33SDmitri Tikhonov return key; 53850aadb33SDmitri Tikhonov} 53950aadb33SDmitri Tikhonov 54050aadb33SDmitri Tikhonov 54150aadb33SDmitri Tikhonov/* type 0 DER, 1: PEM */ 54250aadb33SDmitri TikhonovX509 *bio_to_crt(const void *buf, int len, int type) 54350aadb33SDmitri Tikhonov{ 54450aadb33SDmitri Tikhonov X509 *crt = NULL; 54550aadb33SDmitri Tikhonov BIO *bio = BIO_new_mem_buf(buf, len); 54650aadb33SDmitri Tikhonov if (bio == NULL) 54750aadb33SDmitri Tikhonov return NULL; 54850aadb33SDmitri Tikhonov 54950aadb33SDmitri Tikhonov if (type == 0) 55050aadb33SDmitri Tikhonov crt = d2i_X509_bio(bio, NULL); 55150aadb33SDmitri Tikhonov else 55250aadb33SDmitri Tikhonov crt = PEM_read_bio_X509(bio, &crt, 0 , NULL); 55350aadb33SDmitri Tikhonov BIO_free(bio); 55450aadb33SDmitri Tikhonov return crt; 55550aadb33SDmitri Tikhonov} 55650aadb33SDmitri Tikhonov 55750aadb33SDmitri Tikhonov 55850aadb33SDmitri Tikhonovint read_rsa_priv_key(const uint8_t *buf, int len, EVP_PKEY *pkey) 55950aadb33SDmitri Tikhonov{ 56050aadb33SDmitri Tikhonov 56150aadb33SDmitri Tikhonov RSA *rsa = RSA_private_key_from_bytes(buf, len); 56250aadb33SDmitri Tikhonov if (!rsa) 56350aadb33SDmitri Tikhonov return -1; 56450aadb33SDmitri Tikhonov 56550aadb33SDmitri Tikhonov return EVP_PKEY_assign_RSA(pkey, rsa); 56650aadb33SDmitri Tikhonov} 56750aadb33SDmitri Tikhonov 56850aadb33SDmitri Tikhonov 56950aadb33SDmitri Tikhonovint gen_prof(const uint8_t *chlo_data, size_t chlo_data_len, 57050aadb33SDmitri Tikhonov const uint8_t *scfg_data, uint32_t scfg_data_len, 57150aadb33SDmitri Tikhonov const EVP_PKEY *priv_key, uint8_t *buf, size_t *buf_len) 57250aadb33SDmitri Tikhonov{ 57350aadb33SDmitri Tikhonov uint8_t chlo_hash[32] = {0}; 57450aadb33SDmitri Tikhonov size_t chlo_hash_len = 32; /* SHA256 */ 57550aadb33SDmitri Tikhonov EVP_MD_CTX sign_context; 57650aadb33SDmitri Tikhonov EVP_PKEY_CTX* pkey_ctx = NULL; 57750aadb33SDmitri Tikhonov 57850aadb33SDmitri Tikhonov sha256(chlo_data, chlo_data_len, chlo_hash); 57950aadb33SDmitri Tikhonov EVP_MD_CTX_init(&sign_context); 58050aadb33SDmitri Tikhonov if (!EVP_DigestSignInit(&sign_context, &pkey_ctx, EVP_sha256(), NULL, (EVP_PKEY *)priv_key)) 58150aadb33SDmitri Tikhonov return -1; 58250aadb33SDmitri Tikhonov 58350aadb33SDmitri Tikhonov EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); 58450aadb33SDmitri Tikhonov EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1); 58550aadb33SDmitri Tikhonov 58650aadb33SDmitri Tikhonov if (!EVP_DigestSignUpdate(&sign_context, s_hs_signature, sizeof(s_hs_signature)) || 58750aadb33SDmitri Tikhonov !EVP_DigestSignUpdate(&sign_context, (const uint8_t*)(&chlo_hash_len), 4) || 58850aadb33SDmitri Tikhonov !EVP_DigestSignUpdate(&sign_context, chlo_hash, chlo_hash_len) || 58950aadb33SDmitri Tikhonov !EVP_DigestSignUpdate(&sign_context, scfg_data, scfg_data_len)) 59050aadb33SDmitri Tikhonov { 59150aadb33SDmitri Tikhonov return -1; 59250aadb33SDmitri Tikhonov } 59350aadb33SDmitri Tikhonov 59450aadb33SDmitri Tikhonov size_t len = 0; 59550aadb33SDmitri Tikhonov if (!EVP_DigestSignFinal(&sign_context, NULL, &len)) { 59650aadb33SDmitri Tikhonov return -1; 59750aadb33SDmitri Tikhonov } 59850aadb33SDmitri Tikhonov 59950aadb33SDmitri Tikhonov if (len > *buf_len) 60050aadb33SDmitri Tikhonov return -2; 60150aadb33SDmitri Tikhonov if (buf) 60250aadb33SDmitri Tikhonov EVP_DigestSignFinal(&sign_context, buf, buf_len); 60350aadb33SDmitri Tikhonov 60450aadb33SDmitri Tikhonov EVP_MD_CTX_cleanup(&sign_context); 60550aadb33SDmitri Tikhonov return 0; 60650aadb33SDmitri Tikhonov} 60750aadb33SDmitri Tikhonov 60850aadb33SDmitri Tikhonov 60950aadb33SDmitri Tikhonovint verify_cert(const char *buf, int len) 61050aadb33SDmitri Tikhonov{ 61150aadb33SDmitri Tikhonov //X509_verify_cert(); 61250aadb33SDmitri Tikhonov 61350aadb33SDmitri Tikhonov return 0; 61450aadb33SDmitri Tikhonov} 61550aadb33SDmitri Tikhonov 61650aadb33SDmitri Tikhonov 61750aadb33SDmitri Tikhonovint verify_prof(const uint8_t *chlo_data, size_t chlo_data_len, lsquic_str_t * scfg, 61850aadb33SDmitri Tikhonov const EVP_PKEY *pub_key, const uint8_t *buf, size_t len) 61950aadb33SDmitri Tikhonov{ 62050aadb33SDmitri Tikhonov return verify_prof0(chlo_data, chlo_data_len, 62150aadb33SDmitri Tikhonov (const uint8_t *)lsquic_str_buf(scfg), 62250aadb33SDmitri Tikhonov lsquic_str_len(scfg), pub_key, buf, len); 62350aadb33SDmitri Tikhonov} 62450aadb33SDmitri Tikhonov 62550aadb33SDmitri Tikhonov 62650aadb33SDmitri Tikhonov 62750aadb33SDmitri Tikhonov 62850aadb33SDmitri Tikhonov/* -3 internal error, -1: verify failed, 0: Success */ 62950aadb33SDmitri Tikhonovint verify_prof0(const uint8_t *chlo_data, size_t chlo_data_len, 63050aadb33SDmitri Tikhonov const uint8_t *scfg_data, uint32_t scfg_data_len, 63150aadb33SDmitri Tikhonov const EVP_PKEY *pub_key, const uint8_t *buf, size_t len) 63250aadb33SDmitri Tikhonov{ 63350aadb33SDmitri Tikhonov uint8_t chlo_hash[32] = {0}; 63450aadb33SDmitri Tikhonov size_t chlo_hash_len = 32; /* SHA256 */ 63550aadb33SDmitri Tikhonov EVP_MD_CTX sign_context; 63650aadb33SDmitri Tikhonov EVP_PKEY_CTX* pkey_ctx = NULL; 63750aadb33SDmitri Tikhonov int ret = 0; 63850aadb33SDmitri Tikhonov EVP_MD_CTX_init(&sign_context); 63950aadb33SDmitri Tikhonov sha256(chlo_data, chlo_data_len, chlo_hash); 64050aadb33SDmitri Tikhonov 64150aadb33SDmitri Tikhonov // discarding const below to quiet compiler warning on call to ssl library code 64250aadb33SDmitri Tikhonov if (!EVP_DigestVerifyInit(&sign_context, &pkey_ctx, EVP_sha256(), NULL, (EVP_PKEY *)pub_key)) 64350aadb33SDmitri Tikhonov return -4; 64450aadb33SDmitri Tikhonov 64550aadb33SDmitri Tikhonov EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); 64650aadb33SDmitri Tikhonov EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1); 64750aadb33SDmitri Tikhonov 64850aadb33SDmitri Tikhonov 64950aadb33SDmitri Tikhonov if (!EVP_DigestVerifyUpdate(&sign_context, s_hs_signature, sizeof(s_hs_signature)) || 65050aadb33SDmitri Tikhonov !EVP_DigestVerifyUpdate(&sign_context, (const uint8_t*)(&chlo_hash_len), 4) || 65150aadb33SDmitri Tikhonov !EVP_DigestVerifyUpdate(&sign_context, chlo_hash, chlo_hash_len) || 65250aadb33SDmitri Tikhonov !EVP_DigestVerifyUpdate(&sign_context, scfg_data, scfg_data_len)) 65350aadb33SDmitri Tikhonov { 65450aadb33SDmitri Tikhonov return -3; /* set to -3, to avoid same as "not enough data" -2 */ 65550aadb33SDmitri Tikhonov } 65650aadb33SDmitri Tikhonov 65750aadb33SDmitri Tikhonov ret = EVP_DigestVerifyFinal(&sign_context, buf, len); 65850aadb33SDmitri Tikhonov EVP_MD_CTX_cleanup(&sign_context); 65950aadb33SDmitri Tikhonov 66050aadb33SDmitri Tikhonov if (ret == 1) 66150aadb33SDmitri Tikhonov return 0; //OK 66250aadb33SDmitri Tikhonov else 66350aadb33SDmitri Tikhonov return -1; //failed 66450aadb33SDmitri Tikhonov} 66550aadb33SDmitri Tikhonov 66650aadb33SDmitri Tikhonov 66750aadb33SDmitri Tikhonovvoid crypto_init(void *seed, int seed_len) 66850aadb33SDmitri Tikhonov{ 66950aadb33SDmitri Tikhonov if (crypto_inited) 67050aadb33SDmitri Tikhonov return ; 67150aadb33SDmitri Tikhonov 67250aadb33SDmitri Tikhonov //SSL_library_init(); 67350aadb33SDmitri Tikhonov CRYPTO_library_init(); 67450aadb33SDmitri Tikhonov RAND_seed(seed, seed_len); 67550aadb33SDmitri Tikhonov 67650aadb33SDmitri Tikhonov#if defined( __x86_64 )||defined( __x86_64__ ) 67750aadb33SDmitri Tikhonov make_uint128(&s_prime, 16777216, 315); 67850aadb33SDmitri Tikhonov make_uint128(&s_init_hash, 7809847782465536322, 7113472399480571277); 67950aadb33SDmitri Tikhonov#endif 68050aadb33SDmitri Tikhonov 68150aadb33SDmitri Tikhonov /* MORE .... */ 68250aadb33SDmitri Tikhonov crypto_inited = 1; 68350aadb33SDmitri Tikhonov} 68450aadb33SDmitri Tikhonov 685