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