Merge pull request #46 from h2o/master

Get modular version of picotls
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ca5ec0b..85ee333 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@
 FIND_PACKAGE(PkgConfig REQUIRED)
 
 SET(CMAKE_C_FLAGS "-std=c99 -Wall -O2 -g ${CC_WARNING_FLAGS} ${CMAKE_C_FLAGS}")
-INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR} deps/cifra/src/ext deps/cifra/src deps/micro-ecc deps/picotest include)
+INCLUDE_DIRECTORIES(deps/cifra/src/ext deps/cifra/src deps/micro-ecc deps/picotest include)
 SET(MINICRYPTO_LIBRARY_FILES
     deps/micro-ecc/uECC.c
     deps/cifra/src/aes.c
@@ -39,9 +39,32 @@
 
 ADD_LIBRARY(picotls-core ${CORE_FILES})
 TARGET_LINK_LIBRARIES(picotls-core ${CORE_EXTRA_LIBS})
-ADD_LIBRARY(picotls-minicrypto ${MINICRYPTO_LIBRARY_FILES} lib/cifra.c lib/minicrypto-pem.c lib/uecc.c lib/asn1.c lib/ffx.c)
+ADD_LIBRARY(picotls-minicrypto
+    ${MINICRYPTO_LIBRARY_FILES}
+    lib/cifra.c
+    lib/cifra/x25519.c
+    lib/cifra/chacha20.c
+    lib/cifra/aes128.c
+    lib/cifra/aes256.c
+    lib/cifra/random.c
+    lib/minicrypto-pem.c
+    lib/uecc.c
+    lib/asn1.c
+    lib/ffx.c)
 TARGET_LINK_LIBRARIES(picotls-minicrypto picotls-core)
-ADD_EXECUTABLE(test-minicrypto.t ${MINICRYPTO_LIBRARY_FILES} deps/picotest/picotest.c t/picotls.c t/minicrypto.c lib/asn1.c lib/pembase64.c lib/ffx.c)
+ADD_EXECUTABLE(test-minicrypto.t
+    ${MINICRYPTO_LIBRARY_FILES}
+    deps/picotest/picotest.c
+    t/picotls.c
+    t/minicrypto.c
+    lib/asn1.c
+    lib/pembase64.c
+    lib/ffx.c
+    lib/cifra/x25519.c
+    lib/cifra/chacha20.c
+    lib/cifra/aes128.c
+    lib/cifra/aes256.c
+    lib/cifra/random.c)
 
 SET(TEST_EXES test-minicrypto.t)
 
@@ -56,7 +79,21 @@
     ADD_EXECUTABLE(picotls-esni src/esni.c)
     TARGET_LINK_LIBRARIES(picotls-esni picotls-openssl picotls-core ${OPENSSL_LIBRARIES} ${CMAKE_DL_LIBS})
 
-    ADD_EXECUTABLE(test-openssl.t ${MINICRYPTO_LIBRARY_FILES} lib/cifra.c lib/uecc.c lib/asn1.c lib/pembase64.c lib/ffx.c deps/picotest/picotest.c t/picotls.c t/openssl.c)
+    ADD_EXECUTABLE(test-openssl.t
+        ${MINICRYPTO_LIBRARY_FILES}
+        lib/cifra.c
+        lib/cifra/x25519.c
+        lib/cifra/chacha20.c
+        lib/cifra/aes128.c
+        lib/cifra/aes256.c
+        lib/cifra/random.c
+        lib/uecc.c
+        lib/asn1.c
+        lib/pembase64.c
+        lib/ffx.c
+        deps/picotest/picotest.c
+        t/picotls.c
+        t/openssl.c)
     SET_TARGET_PROPERTIES(test-openssl.t PROPERTIES COMPILE_FLAGS "-DPTLS_MEMORY_DEBUG=1")
     TARGET_LINK_LIBRARIES(test-openssl.t ${OPENSSL_LIBRARIES} ${CMAKE_DL_LIBS})
 
@@ -78,7 +115,7 @@
 ENDIF ()
 
 FIND_LIBRARY(LIBC_RESOLV_LIB "resolv")
-IF (LIBC_RESOLV_LIB)
+IF (OPENSSL_FOUND AND LIBC_RESOLV_LIB)
     TARGET_LINK_LIBRARIES(cli ${LIBC_RESOLV_LIB})
 ENDIF ()
 
diff --git a/deps/micro-ecc/uECC.c b/deps/micro-ecc/uECC.c
index daa144a..461f713 100644
--- a/deps/micro-ecc/uECC.c
+++ b/deps/micro-ecc/uECC.c
@@ -307,7 +307,7 @@
     uECC_word_t tmp[uECC_MAX_WORDS];
     uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
     uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
-    return (!equal - 2 * neg);
+    return (cmpresult_t)(!equal - 2 * neg);
 }
 
 /* Computes vli = vli >> 1. */
@@ -957,7 +957,7 @@
     wordcount_t i;
     for (i = 0; i < num_bytes; ++i) {
         unsigned b = num_bytes - 1 - i;
-        bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
+        bytes[i] = (uint8_t)(native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)));
     }
 }
 
diff --git a/include/picotls.h b/include/picotls.h
index 1054879..0fdc7c6 100644
--- a/include/picotls.h
+++ b/include/picotls.h
@@ -26,10 +26,16 @@
 extern "C" {
 #endif
 
+#ifdef _WINDOWS
+#include "wincompat.h"
+#endif
+
 #include <assert.h>
 #include <inttypes.h>
 #include <sys/types.h>
 
+
+
 #ifndef PTLS_FUZZ_HANDSHAKE
 #define PTLS_FUZZ_HANDSHAKE 0
 #endif
diff --git a/lib/cifra.c b/lib/cifra.c
index 8bb93d1..b41d3bc 100644
--- a/lib/cifra.c
+++ b/lib/cifra.c
@@ -19,598 +19,9 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  * IN THE SOFTWARE.
  */
-#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef _WINDOWS
-#include "wincompat.h"
-#else
-#include <unistd.h>
-#endif
-#include "aes.h"
-#include "bitops.h"
-#include "drbg.h"
-#include "curve25519.h"
-#include "../deps/cifra/src/ext/handy.h"
-#include "modes.h"
-#include "poly1305.h"
-#include "salsa20.h"
-#include "sha2.h"
+#include <stddef.h>
 #include "picotls.h"
 #include "picotls/minicrypto.h"
 
-#ifdef _WINDOWS
-#ifdef _WINDOWS_XP
- /* The modern BCrypt API is only available on Windows Vista and later versions.
-  * If compiling on Windows XP, we need to use the olded "wincrypt" API */
-#include <wincrypt.h>
-
-static void read_entropy(uint8_t *entropy, size_t size)
-{
-    HCRYPTPROV hCryptProv = 0;
-    BOOL ret = FALSE;
-
-    if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
-        ret = CryptGenRandom(hCryptProv, (DWORD)size, entropy);
-        (void)CryptReleaseContext(hCryptProv, 0);
-    }
-
-    if (ret == FALSE) {
-        perror("ptls_minicrypto_random_bytes: could not use CryptGenRandom");
-        abort();
-    }
-}
-#else
- /* The old "Wincrypt" API requires access to default security containers.
-  * This can cause access control errors on some systems. We prefer
-  * to use the modern BCrypt API when available */
-#include <bcrypt.h>
-
- static void read_entropy(uint8_t *entropy, size_t size)
- {
-    NTSTATUS nts = 0;
-    BCRYPT_ALG_HANDLE hAlgorithm = 0;
-
-    nts = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_RNG_ALGORITHM, NULL, 0);
-
-    if (BCRYPT_SUCCESS(nts)) {
-        nts = BCryptGenRandom(hAlgorithm, (PUCHAR)entropy, (ULONG)size, 0);
-
-        (void)BCryptCloseAlgorithmProvider(hAlgorithm, 0); 
-    } 
-
-    if (!BCRYPT_SUCCESS(nts)) {
-        perror("ptls_minicrypto_random_bytes: could not open BCrypt RNG Algorithm");
-        abort();
-    }
-}
-#endif
-#else
-static void read_entropy(uint8_t *entropy, size_t size)
-{
-    int fd;
-
-    if ((fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC)) == -1) {
-        if ((fd = open("/dev/random", O_RDONLY | O_CLOEXEC)) == -1) {
-            perror("ptls_minicrypto_random_bytes: could not open neither /dev/random or /dev/urandom");
-            abort();
-        }
-    }
-
-    while (size != 0) {
-        ssize_t rret;
-        while ((rret = read(fd, entropy, size)) == -1 && errno == EINTR)
-            ;
-        if (rret < 0) {
-            perror("ptls_minicrypto_random_bytes");
-            abort();
-        }
-        entropy += rret;
-        size -= rret;
-    }
-
-    close(fd);
-}
-#endif
-
-void ptls_minicrypto_random_bytes(void *buf, size_t len)
-{
-#ifdef _WINDOWS
-    static __declspec(thread) cf_hash_drbg_sha256 ctx;
-#else
-    static __thread cf_hash_drbg_sha256 ctx;
-#endif
-
-    if (cf_hash_drbg_sha256_needs_reseed(&ctx)) {
-        uint8_t entropy[256];
-        read_entropy(entropy, sizeof(entropy));
-        cf_hash_drbg_sha256_init(&ctx, entropy, sizeof(entropy) / 2, entropy + sizeof(entropy) / 2, sizeof(entropy) / 2, "ptls", 4);
-    }
-    cf_hash_drbg_sha256_gen(&ctx, buf, len);
-}
-
-#define X25519_KEY_SIZE 32
-
-struct st_x25519_key_exchange_t {
-    ptls_key_exchange_context_t super;
-    uint8_t priv[X25519_KEY_SIZE];
-    uint8_t pub[X25519_KEY_SIZE];
-};
-
-static void x25519_create_keypair(uint8_t *priv, uint8_t *pub)
-{
-    ptls_minicrypto_random_bytes(priv, X25519_KEY_SIZE);
-    cf_curve25519_mul_base(pub, priv);
-}
-
-static int x25519_derive_secret(ptls_iovec_t *secret, const uint8_t *clientpriv, const uint8_t *clientpub,
-                                const uint8_t *serverpriv, const uint8_t *serverpub)
-{
-    if ((secret->base = malloc(X25519_KEY_SIZE)) == NULL)
-        return PTLS_ERROR_NO_MEMORY;
-
-    cf_curve25519_mul(secret->base, clientpriv != NULL ? clientpriv : serverpriv, clientpriv != NULL ? serverpub : clientpub);
-    secret->len = X25519_KEY_SIZE;
-    return 0;
-}
-
-static int x25519_on_exchange(ptls_key_exchange_context_t **_ctx, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey)
-{
-    struct st_x25519_key_exchange_t *ctx = (struct st_x25519_key_exchange_t *)*_ctx;
-    int ret;
-
-    if (secret == NULL) {
-        ret = 0;
-        goto Exit;
-    }
-
-    if (peerkey.len != X25519_KEY_SIZE) {
-        ret = PTLS_ALERT_DECRYPT_ERROR;
-        goto Exit;
-    }
-    ret = x25519_derive_secret(secret, ctx->priv, ctx->pub, NULL, peerkey.base);
-
-Exit:
-    if (release) {
-        ptls_clear_memory(ctx->priv, sizeof(ctx->priv));
-        free(ctx);
-        *_ctx = NULL;
-    }
-    return ret;
-}
-
-static int x25519_create_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **_ctx)
-{
-    struct st_x25519_key_exchange_t *ctx;
-
-    if ((ctx = (struct st_x25519_key_exchange_t *)malloc(sizeof(*ctx))) == NULL)
-        return PTLS_ERROR_NO_MEMORY;
-    ctx->super = (ptls_key_exchange_context_t){algo, ptls_iovec_init(ctx->pub, sizeof(ctx->pub)), x25519_on_exchange};
-    x25519_create_keypair(ctx->priv, ctx->pub);
-
-    *_ctx = &ctx->super;
-    return 0;
-}
-
-static int x25519_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret,
-                               ptls_iovec_t peerkey)
-{
-    uint8_t priv[X25519_KEY_SIZE], *pub = NULL;
-    int ret;
-
-    if (peerkey.len != X25519_KEY_SIZE) {
-        ret = PTLS_ALERT_DECRYPT_ERROR;
-        goto Exit;
-    }
-    if ((pub = malloc(X25519_KEY_SIZE)) == NULL) {
-        ret = PTLS_ERROR_NO_MEMORY;
-        goto Exit;
-    }
-
-    x25519_create_keypair(priv, pub);
-    if ((ret = x25519_derive_secret(secret, NULL, peerkey.base, priv, pub)) != 0)
-        goto Exit;
-
-    *pubkey = ptls_iovec_init(pub, X25519_KEY_SIZE);
-    ret = 0;
-
-Exit:
-    ptls_clear_memory(priv, sizeof(priv));
-    if (pub != NULL && ret != 0)
-        ptls_clear_memory(pub, X25519_KEY_SIZE);
-    return ret;
-}
-
-struct aesecb_context_t {
-    ptls_cipher_context_t super;
-    cf_aes_context aes;
-};
-
-static void aesecb_dispose(ptls_cipher_context_t *_ctx)
-{
-    struct aesecb_context_t *ctx = (struct aesecb_context_t *)_ctx;
-    ptls_clear_memory(ctx, sizeof(*ctx));
-}
-
-static void aesecb_encrypt(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
-{
-    struct aesecb_context_t *ctx = (struct aesecb_context_t *)_ctx;
-    assert(len % AES_BLOCKSZ == 0);
-    cf_aes_encrypt(&ctx->aes, input, output);
-}
-
-static void aesecb_decrypt(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
-{
-    struct aesecb_context_t *ctx = (struct aesecb_context_t *)_ctx;
-    assert(len % AES_BLOCKSZ == 0);
-    cf_aes_decrypt(&ctx->aes, input, output);
-}
-
-static int aesecb_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key, size_t key_size)
-{
-    struct aesecb_context_t *ctx = (struct aesecb_context_t *)_ctx;
-    ctx->super.do_dispose = aesecb_dispose;
-    ctx->super.do_init = NULL;
-    ctx->super.do_transform = is_enc ? aesecb_encrypt : aesecb_decrypt;
-    cf_aes_init(&ctx->aes, key, key_size);
-    return 0;
-}
-
-static int aes128ecb_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
-{
-    return aesecb_setup_crypto(ctx, is_enc, key, PTLS_AES128_KEY_SIZE);
-}
-
-static int aes256ecb_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
-{
-    return aesecb_setup_crypto(ctx, is_enc, key, PTLS_AES256_KEY_SIZE);
-}
-
-struct aesctr_context_t {
-    ptls_cipher_context_t super;
-    cf_aes_context aes;
-    cf_ctr ctr;
-};
-
-static void aesctr_dispose(ptls_cipher_context_t *_ctx)
-{
-    struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
-    ptls_clear_memory(ctx, sizeof(*ctx));
-}
-
-static void aesctr_init(ptls_cipher_context_t *_ctx, const void *iv)
-{
-    struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
-    cf_ctr_init(&ctx->ctr, &cf_aes, &ctx->aes, iv);
-}
-
-static void aesctr_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
-{
-    struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
-    cf_ctr_cipher(&ctx->ctr, input, output, len);
-}
-
-static int aesctr_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key, size_t key_size)
-{
-    struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
-    ctx->super.do_dispose = aesctr_dispose;
-    ctx->super.do_init = aesctr_init;
-    ctx->super.do_transform = aesctr_transform;
-    cf_aes_init(&ctx->aes, key, key_size);
-    return 0;
-}
-
-static int aes128ctr_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
-{
-    return aesctr_setup_crypto(ctx, is_enc, key, PTLS_AES128_KEY_SIZE);
-}
-
-static int aes256ctr_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
-{
-    return aesctr_setup_crypto(ctx, is_enc, key, PTLS_AES256_KEY_SIZE);
-}
-
-struct aesgcm_context_t {
-    ptls_aead_context_t super;
-    cf_aes_context aes;
-    cf_gcm_ctx gcm;
-};
-
-static void aesgcm_dispose_crypto(ptls_aead_context_t *_ctx)
-{
-    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
-
-    /* clear all memory except super */
-    ptls_clear_memory((uint8_t *)ctx + sizeof(ctx->super), sizeof(*ctx) - sizeof(ctx->super));
-}
-
-static void aesgcm_encrypt_init(ptls_aead_context_t *_ctx, const void *iv, const void *aad, size_t aadlen)
-{
-    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
-
-    cf_gcm_encrypt_init(&cf_aes, &ctx->aes, &ctx->gcm, aad, aadlen, iv, PTLS_AESGCM_IV_SIZE);
-}
-
-static size_t aesgcm_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
-{
-    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
-
-    cf_gcm_encrypt_update(&ctx->gcm, input, inlen, output);
-    return inlen;
-}
-
-static size_t aesgcm_encrypt_final(ptls_aead_context_t *_ctx, void *output)
-{
-    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
-
-    cf_gcm_encrypt_final(&ctx->gcm, output, PTLS_AESGCM_TAG_SIZE);
-    return PTLS_AESGCM_TAG_SIZE;
-}
-
-static size_t aesgcm_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, const void *iv,
-                             const void *aad, size_t aadlen)
-{
-    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
-
-    if (inlen < PTLS_AESGCM_TAG_SIZE)
-        return SIZE_MAX;
-    size_t tag_offset = inlen - PTLS_AESGCM_TAG_SIZE;
-
-    if (cf_gcm_decrypt(&cf_aes, &ctx->aes, input, tag_offset, aad, aadlen, iv, PTLS_AESGCM_IV_SIZE, (uint8_t *)input + tag_offset,
-                       PTLS_AESGCM_TAG_SIZE, output) != 0)
-        return SIZE_MAX;
-
-    return tag_offset;
-}
-
-static int aead_aesgcm_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, size_t key_size)
-{
-    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
-
-    ctx->super.dispose_crypto = aesgcm_dispose_crypto;
-    if (is_enc) {
-        ctx->super.do_encrypt_init = aesgcm_encrypt_init;
-        ctx->super.do_encrypt_update = aesgcm_encrypt_update;
-        ctx->super.do_encrypt_final = aesgcm_encrypt_final;
-        ctx->super.do_decrypt = NULL;
-    } else {
-        ctx->super.do_encrypt_init = NULL;
-        ctx->super.do_encrypt_update = NULL;
-        ctx->super.do_encrypt_final = NULL;
-        ctx->super.do_decrypt = aesgcm_decrypt;
-    }
-
-    cf_aes_init(&ctx->aes, key, key_size);
-    return 0;
-}
-
-static int aead_aes128gcm_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
-{
-    return aead_aesgcm_setup_crypto(ctx, is_enc, key, PTLS_AES128_KEY_SIZE);
-}
-
-static int aead_aes256gcm_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
-{
-    return aead_aesgcm_setup_crypto(ctx, is_enc, key, PTLS_AES256_KEY_SIZE);
-}
-
-struct chacha20_context_t {
-    ptls_cipher_context_t super;
-    cf_chacha20_ctx chacha;
-    uint8_t key[PTLS_CHACHA20_KEY_SIZE];
-};
-
-static void chacha20_dispose(ptls_cipher_context_t *_ctx)
-{
-    struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
-    ptls_clear_memory(ctx, sizeof(*ctx));
-}
-
-static void chacha20_init(ptls_cipher_context_t *_ctx, const void *iv)
-{
-    struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
-    ctx->chacha.nblock = 0;
-    ctx->chacha.ncounter = 0;
-    memcpy(ctx->chacha.nonce, iv, sizeof ctx->chacha.nonce);
-}
-
-static void chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
-{
-    struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
-    cf_chacha20_cipher(&ctx->chacha, input, output, len);
-}
-
-static int chacha20_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key)
-{
-    struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
-    ctx->super.do_dispose = chacha20_dispose;
-    ctx->super.do_init = chacha20_init;
-    ctx->super.do_transform = chacha20_transform;
-    cf_chacha20_init(&ctx->chacha, key, PTLS_CHACHA20_KEY_SIZE, (const uint8_t *)"01234567" /* not used */);
-    return 0;
-}
-
-struct chacha20poly1305_context_t {
-    ptls_aead_context_t super;
-    uint8_t key[PTLS_CHACHA20_KEY_SIZE];
-    cf_chacha20_ctx chacha;
-    cf_poly1305 poly;
-    size_t aadlen;
-    size_t textlen;
-};
-
-static void chacha20poly1305_dispose_crypto(ptls_aead_context_t *_ctx)
-{
-    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-
-    /* clear all memory except super */
-    ptls_clear_memory(&ctx->key, sizeof(*ctx) - offsetof(struct chacha20poly1305_context_t, key));
-}
-
-static const uint8_t zeros64[64] = {0};
-
-static void chacha20poly1305_encrypt_pad(cf_poly1305 *poly, size_t n)
-{
-    if (n % 16 != 0)
-        cf_poly1305_update(poly, zeros64, 16 - (n % 16));
-}
-
-static void chacha20poly1305_finalize(struct chacha20poly1305_context_t *ctx, uint8_t *tag)
-{
-    uint8_t lenbuf[16];
-
-    chacha20poly1305_encrypt_pad(&ctx->poly, ctx->textlen);
-
-    write64_le(ctx->aadlen, lenbuf);
-    write64_le(ctx->textlen, lenbuf + 8);
-    cf_poly1305_update(&ctx->poly, lenbuf, sizeof(lenbuf));
-
-    cf_poly1305_finish(&ctx->poly, tag);
-}
-
-static void chacha20poly1305_init(ptls_aead_context_t *_ctx, const void *iv, const void *aad, size_t aadlen)
-{
-    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-    uint8_t tmpbuf[64];
-
-    /* init chacha */
-    memset(tmpbuf, 0, 16 - PTLS_CHACHA20POLY1305_IV_SIZE);
-    memcpy(tmpbuf + 16 - PTLS_CHACHA20POLY1305_IV_SIZE, iv, PTLS_CHACHA20POLY1305_IV_SIZE);
-    cf_chacha20_init_custom(&ctx->chacha, ctx->key, sizeof(ctx->key), tmpbuf, 4);
-
-    /* init poly1305 (by using first 16 bytes of the key stream of the first block) */
-    cf_chacha20_cipher(&ctx->chacha, zeros64, tmpbuf, 64);
-    cf_poly1305_init(&ctx->poly, tmpbuf, tmpbuf + 16);
-
-    ptls_clear_memory(tmpbuf, sizeof(tmpbuf));
-
-    /* aad */
-    if (aadlen != 0) {
-        cf_poly1305_update(&ctx->poly, aad, aadlen);
-        chacha20poly1305_encrypt_pad(&ctx->poly, aadlen);
-    }
-
-    ctx->aadlen = aadlen;
-    ctx->textlen = 0;
-}
-
-static size_t chacha20poly1305_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
-{
-    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-
-    cf_chacha20_cipher(&ctx->chacha, input, output, inlen);
-    cf_poly1305_update(&ctx->poly, output, inlen);
-    ctx->textlen += inlen;
-
-    return inlen;
-}
-
-static size_t chacha20poly1305_encrypt_final(ptls_aead_context_t *_ctx, void *output)
-{
-    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-
-    chacha20poly1305_finalize(ctx, output);
-
-    ptls_clear_memory(&ctx->chacha, sizeof(ctx->chacha));
-    return PTLS_CHACHA20POLY1305_TAG_SIZE;
-}
-
-static size_t chacha20poly1305_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, const void *iv,
-                                       const void *aad, size_t aadlen)
-{
-    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-    uint8_t tag[PTLS_CHACHA20POLY1305_TAG_SIZE];
-    size_t ret;
-
-    if (inlen < sizeof(tag))
-        return SIZE_MAX;
-
-    chacha20poly1305_init(&ctx->super, iv, aad, aadlen);
-
-    cf_poly1305_update(&ctx->poly, input, inlen - sizeof(tag));
-    ctx->textlen = inlen - sizeof(tag);
-
-    chacha20poly1305_finalize(ctx, tag);
-    if (mem_eq(tag, (const uint8_t *)input + inlen - sizeof(tag), sizeof(tag))) {
-        cf_chacha20_cipher(&ctx->chacha, input, output, inlen - sizeof(tag));
-        ret = inlen - sizeof(tag);
-    } else {
-        ret = SIZE_MAX;
-    }
-
-    ptls_clear_memory(tag, sizeof(tag));
-    ptls_clear_memory(&ctx->poly, sizeof(ctx->poly));
-
-    return ret;
-}
-
-static int aead_chacha20poly1305_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key)
-{
-    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
-
-    ctx->super.dispose_crypto = chacha20poly1305_dispose_crypto;
-    if (is_enc) {
-        ctx->super.do_encrypt_init = chacha20poly1305_init;
-        ctx->super.do_encrypt_update = chacha20poly1305_encrypt_update;
-        ctx->super.do_encrypt_final = chacha20poly1305_encrypt_final;
-        ctx->super.do_decrypt = NULL;
-    } else {
-        ctx->super.do_encrypt_init = NULL;
-        ctx->super.do_encrypt_update = NULL;
-        ctx->super.do_encrypt_final = NULL;
-        ctx->super.do_decrypt = chacha20poly1305_decrypt;
-    }
-
-    memcpy(ctx->key, key, sizeof(ctx->key));
-    return 0;
-}
-
-ptls_define_hash(sha256, cf_sha256_context, cf_sha256_init, cf_sha256_update, cf_sha256_digest_final);
-ptls_define_hash(sha384, cf_sha512_context, cf_sha384_init, cf_sha384_update, cf_sha384_digest_final);
-
-ptls_key_exchange_algorithm_t ptls_minicrypto_x25519 = {PTLS_GROUP_X25519, x25519_create_key_exchange, x25519_key_exchange};
-ptls_cipher_algorithm_t ptls_minicrypto_aes128ecb = {
-    "AES128-ECB",          PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct aesecb_context_t),
-    aes128ecb_setup_crypto};
-ptls_cipher_algorithm_t ptls_minicrypto_aes128ctr = {
-    "AES128-CTR",          PTLS_AES128_KEY_SIZE, 1 /* block size */, PTLS_AES_IV_SIZE, sizeof(struct aesctr_context_t),
-    aes128ctr_setup_crypto};
-ptls_aead_algorithm_t ptls_minicrypto_aes128gcm = {
-    "AES128-GCM",        &ptls_minicrypto_aes128ctr, &ptls_minicrypto_aes128ecb,      PTLS_AES128_KEY_SIZE,
-    PTLS_AESGCM_IV_SIZE, PTLS_AESGCM_TAG_SIZE,       sizeof(struct aesgcm_context_t), aead_aes128gcm_setup_crypto};
-ptls_cipher_algorithm_t ptls_minicrypto_aes256ecb = {
-    "AES128-ECB",          PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct aesecb_context_t),
-    aes256ecb_setup_crypto};
-ptls_cipher_algorithm_t ptls_minicrypto_aes256ctr = {
-    "AES256-CTR",          PTLS_AES256_KEY_SIZE, 1 /* block size */, PTLS_AES_IV_SIZE, sizeof(struct aesctr_context_t),
-    aes256ctr_setup_crypto};
-ptls_aead_algorithm_t ptls_minicrypto_aes256gcm = {
-    "AES256-GCM",        &ptls_minicrypto_aes256ctr, &ptls_minicrypto_aes256ecb,      PTLS_AES256_KEY_SIZE,
-    PTLS_AESGCM_IV_SIZE, PTLS_AESGCM_TAG_SIZE,       sizeof(struct aesgcm_context_t), aead_aes256gcm_setup_crypto};
-ptls_hash_algorithm_t ptls_minicrypto_sha256 = {PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, sha256_create,
-                                                PTLS_ZERO_DIGEST_SHA256};
-ptls_hash_algorithm_t ptls_minicrypto_sha384 = {PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, sha384_create,
-                                                PTLS_ZERO_DIGEST_SHA384};
-ptls_cipher_algorithm_t ptls_minicrypto_chacha20 = {
-    "CHACHA20",           PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct chacha20_context_t),
-    chacha20_setup_crypto};
-ptls_aead_algorithm_t ptls_minicrypto_chacha20poly1305 = {"CHACHA20-POLY1305",
-                                                          &ptls_minicrypto_chacha20,
-                                                          NULL,
-                                                          PTLS_CHACHA20_KEY_SIZE,
-                                                          PTLS_CHACHA20POLY1305_IV_SIZE,
-                                                          PTLS_CHACHA20POLY1305_TAG_SIZE,
-                                                          sizeof(struct chacha20poly1305_context_t),
-                                                          aead_chacha20poly1305_setup_crypto};
-ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256 = {PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, &ptls_minicrypto_aes128gcm,
-                                                       &ptls_minicrypto_sha256};
-ptls_cipher_suite_t ptls_minicrypto_aes256gcmsha384 = {PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, &ptls_minicrypto_aes256gcm,
-                                                       &ptls_minicrypto_sha384};
-ptls_cipher_suite_t ptls_minicrypto_chacha20poly1305sha256 = {PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256,
-                                                              &ptls_minicrypto_chacha20poly1305, &ptls_minicrypto_sha256};
 ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_aes128gcmsha256,
                                                         &ptls_minicrypto_chacha20poly1305sha256, NULL};
diff --git a/lib/cifra/aes-common.h b/lib/cifra/aes-common.h
new file mode 100644
index 0000000..9823337
--- /dev/null
+++ b/lib/cifra/aes-common.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include "aes.h"
+#include "modes.h"
+#include "sha2.h"
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+
+struct aesecb_context_t {
+    ptls_cipher_context_t super;
+    cf_aes_context aes;
+};
+
+static inline void aesecb_dispose(ptls_cipher_context_t *_ctx)
+{
+    struct aesecb_context_t *ctx = (struct aesecb_context_t *)_ctx;
+    ptls_clear_memory(ctx, sizeof(*ctx));
+}
+
+static inline void aesecb_encrypt(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
+{
+    struct aesecb_context_t *ctx = (struct aesecb_context_t *)_ctx;
+    assert(len % AES_BLOCKSZ == 0);
+    cf_aes_encrypt(&ctx->aes, input, output);
+}
+
+static inline void aesecb_decrypt(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
+{
+    struct aesecb_context_t *ctx = (struct aesecb_context_t *)_ctx;
+    assert(len % AES_BLOCKSZ == 0);
+    cf_aes_decrypt(&ctx->aes, input, output);
+}
+
+static inline int aesecb_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key, size_t key_size)
+{
+    struct aesecb_context_t *ctx = (struct aesecb_context_t *)_ctx;
+    ctx->super.do_dispose = aesecb_dispose;
+    ctx->super.do_init = NULL;
+    ctx->super.do_transform = is_enc ? aesecb_encrypt : aesecb_decrypt;
+    cf_aes_init(&ctx->aes, key, key_size);
+    return 0;
+}
+
+struct aesctr_context_t {
+    ptls_cipher_context_t super;
+    cf_aes_context aes;
+    cf_ctr ctr;
+};
+
+static inline void aesctr_dispose(ptls_cipher_context_t *_ctx)
+{
+    struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
+    ptls_clear_memory(ctx, sizeof(*ctx));
+}
+
+static inline void aesctr_init(ptls_cipher_context_t *_ctx, const void *iv)
+{
+    struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
+    cf_ctr_init(&ctx->ctr, &cf_aes, &ctx->aes, iv);
+}
+
+static inline void aesctr_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
+{
+    struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
+    cf_ctr_cipher(&ctx->ctr, input, output, len);
+}
+
+static inline int aesctr_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key, size_t key_size)
+{
+    struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
+    ctx->super.do_dispose = aesctr_dispose;
+    ctx->super.do_init = aesctr_init;
+    ctx->super.do_transform = aesctr_transform;
+    cf_aes_init(&ctx->aes, key, key_size);
+    return 0;
+}
+
+struct aesgcm_context_t {
+    ptls_aead_context_t super;
+    cf_aes_context aes;
+    cf_gcm_ctx gcm;
+};
+
+static inline void aesgcm_dispose_crypto(ptls_aead_context_t *_ctx)
+{
+    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+    /* clear all memory except super */
+    ptls_clear_memory((uint8_t *)ctx + sizeof(ctx->super), sizeof(*ctx) - sizeof(ctx->super));
+}
+
+static inline void aesgcm_encrypt_init(ptls_aead_context_t *_ctx, const void *iv, const void *aad, size_t aadlen)
+{
+    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+    cf_gcm_encrypt_init(&cf_aes, &ctx->aes, &ctx->gcm, aad, aadlen, iv, PTLS_AESGCM_IV_SIZE);
+}
+
+static inline size_t aesgcm_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
+{
+    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+    cf_gcm_encrypt_update(&ctx->gcm, input, inlen, output);
+    return inlen;
+}
+
+static inline size_t aesgcm_encrypt_final(ptls_aead_context_t *_ctx, void *output)
+{
+    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+    cf_gcm_encrypt_final(&ctx->gcm, output, PTLS_AESGCM_TAG_SIZE);
+    return PTLS_AESGCM_TAG_SIZE;
+}
+
+static inline size_t aesgcm_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, const void *iv,
+                             const void *aad, size_t aadlen)
+{
+    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+    if (inlen < PTLS_AESGCM_TAG_SIZE)
+        return SIZE_MAX;
+    size_t tag_offset = inlen - PTLS_AESGCM_TAG_SIZE;
+
+    if (cf_gcm_decrypt(&cf_aes, &ctx->aes, input, tag_offset, aad, aadlen, iv, PTLS_AESGCM_IV_SIZE, (uint8_t *)input + tag_offset,
+                       PTLS_AESGCM_TAG_SIZE, output) != 0)
+        return SIZE_MAX;
+
+    return tag_offset;
+}
+
+static inline int aead_aesgcm_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, size_t key_size)
+{
+    struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+    ctx->super.dispose_crypto = aesgcm_dispose_crypto;
+    if (is_enc) {
+        ctx->super.do_encrypt_init = aesgcm_encrypt_init;
+        ctx->super.do_encrypt_update = aesgcm_encrypt_update;
+        ctx->super.do_encrypt_final = aesgcm_encrypt_final;
+        ctx->super.do_decrypt = NULL;
+    } else {
+        ctx->super.do_encrypt_init = NULL;
+        ctx->super.do_encrypt_update = NULL;
+        ctx->super.do_encrypt_final = NULL;
+        ctx->super.do_decrypt = aesgcm_decrypt;
+    }
+
+    cf_aes_init(&ctx->aes, key, key_size);
+    return 0;
+}
diff --git a/lib/cifra/aes128.c b/lib/cifra/aes128.c
new file mode 100644
index 0000000..31a2598
--- /dev/null
+++ b/lib/cifra/aes128.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "aes-common.h"
+
+static int aes128ecb_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+    return aesecb_setup_crypto(ctx, is_enc, key, PTLS_AES128_KEY_SIZE);
+}
+
+static int aes128ctr_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+    return aesctr_setup_crypto(ctx, is_enc, key, PTLS_AES128_KEY_SIZE);
+}
+
+static int aead_aes128gcm_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
+{
+    return aead_aesgcm_setup_crypto(ctx, is_enc, key, PTLS_AES128_KEY_SIZE);
+}
+
+ptls_define_hash(sha256, cf_sha256_context, cf_sha256_init, cf_sha256_update, cf_sha256_digest_final);
+
+ptls_hash_algorithm_t ptls_minicrypto_sha256 = {PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, sha256_create,
+                                                PTLS_ZERO_DIGEST_SHA256};
+
+ptls_cipher_algorithm_t ptls_minicrypto_aes128ecb = {
+    "AES128-ECB",          PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct aesecb_context_t),
+    aes128ecb_setup_crypto};
+ptls_cipher_algorithm_t ptls_minicrypto_aes128ctr = {
+    "AES128-CTR",          PTLS_AES128_KEY_SIZE, 1 /* block size */, PTLS_AES_IV_SIZE, sizeof(struct aesctr_context_t),
+    aes128ctr_setup_crypto};
+ptls_aead_algorithm_t ptls_minicrypto_aes128gcm = {
+    "AES128-GCM",        &ptls_minicrypto_aes128ctr, &ptls_minicrypto_aes128ecb,      PTLS_AES128_KEY_SIZE,
+    PTLS_AESGCM_IV_SIZE, PTLS_AESGCM_TAG_SIZE,       sizeof(struct aesgcm_context_t), aead_aes128gcm_setup_crypto};
+ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256 = {PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, &ptls_minicrypto_aes128gcm,
+                                                       &ptls_minicrypto_sha256};
diff --git a/lib/cifra/aes256.c b/lib/cifra/aes256.c
new file mode 100644
index 0000000..b2cec2c
--- /dev/null
+++ b/lib/cifra/aes256.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "aes-common.h"
+
+static int aes256ecb_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+    return aesecb_setup_crypto(ctx, is_enc, key, PTLS_AES256_KEY_SIZE);
+}
+
+static int aes256ctr_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+    return aesctr_setup_crypto(ctx, is_enc, key, PTLS_AES256_KEY_SIZE);
+}
+
+static int aead_aes256gcm_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
+{
+    return aead_aesgcm_setup_crypto(ctx, is_enc, key, PTLS_AES256_KEY_SIZE);
+}
+
+ptls_define_hash(sha384, cf_sha512_context, cf_sha384_init, cf_sha384_update, cf_sha384_digest_final);
+
+ptls_hash_algorithm_t ptls_minicrypto_sha384 = {PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, sha384_create,
+                                                PTLS_ZERO_DIGEST_SHA384};
+
+ptls_cipher_algorithm_t ptls_minicrypto_aes256ecb = {
+    "AES256-ECB",          PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct aesecb_context_t),
+    aes256ecb_setup_crypto};
+ptls_cipher_algorithm_t ptls_minicrypto_aes256ctr = {
+    "AES256-CTR",          PTLS_AES256_KEY_SIZE, 1 /* block size */, PTLS_AES_IV_SIZE, sizeof(struct aesctr_context_t),
+    aes256ctr_setup_crypto};
+ptls_aead_algorithm_t ptls_minicrypto_aes256gcm = {
+    "AES256-GCM",        &ptls_minicrypto_aes256ctr, &ptls_minicrypto_aes256ecb,      PTLS_AES256_KEY_SIZE,
+    PTLS_AESGCM_IV_SIZE, PTLS_AESGCM_TAG_SIZE,       sizeof(struct aesgcm_context_t), aead_aes256gcm_setup_crypto};
+ptls_cipher_suite_t ptls_minicrypto_aes256gcmsha384 = {PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, &ptls_minicrypto_aes256gcm,
+                                                       &ptls_minicrypto_sha384};
diff --git a/lib/cifra/chacha20.c b/lib/cifra/chacha20.c
new file mode 100644
index 0000000..ab956fa
--- /dev/null
+++ b/lib/cifra/chacha20.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include "bitops.h"
+#include "../deps/cifra/src/ext/handy.h"
+#include "poly1305.h"
+#include "salsa20.h"
+#include "sha2.h"
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+
+struct chacha20_context_t {
+    ptls_cipher_context_t super;
+    cf_chacha20_ctx chacha;
+    uint8_t key[PTLS_CHACHA20_KEY_SIZE];
+};
+
+static void chacha20_dispose(ptls_cipher_context_t *_ctx)
+{
+    struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
+    ptls_clear_memory(ctx, sizeof(*ctx));
+}
+
+static void chacha20_init(ptls_cipher_context_t *_ctx, const void *iv)
+{
+    struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
+    ctx->chacha.nblock = 0;
+    ctx->chacha.ncounter = 0;
+    memcpy(ctx->chacha.nonce, iv, sizeof ctx->chacha.nonce);
+}
+
+static void chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
+{
+    struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
+    cf_chacha20_cipher(&ctx->chacha, input, output, len);
+}
+
+static int chacha20_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key)
+{
+    struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
+    ctx->super.do_dispose = chacha20_dispose;
+    ctx->super.do_init = chacha20_init;
+    ctx->super.do_transform = chacha20_transform;
+    cf_chacha20_init(&ctx->chacha, key, PTLS_CHACHA20_KEY_SIZE, (const uint8_t *)"01234567" /* not used */);
+    return 0;
+}
+
+struct chacha20poly1305_context_t {
+    ptls_aead_context_t super;
+    uint8_t key[PTLS_CHACHA20_KEY_SIZE];
+    cf_chacha20_ctx chacha;
+    cf_poly1305 poly;
+    size_t aadlen;
+    size_t textlen;
+};
+
+static void chacha20poly1305_dispose_crypto(ptls_aead_context_t *_ctx)
+{
+    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+    /* clear all memory except super */
+    ptls_clear_memory(&ctx->key, sizeof(*ctx) - offsetof(struct chacha20poly1305_context_t, key));
+}
+
+static const uint8_t zeros64[64] = {0};
+
+static void chacha20poly1305_encrypt_pad(cf_poly1305 *poly, size_t n)
+{
+    if (n % 16 != 0)
+        cf_poly1305_update(poly, zeros64, 16 - (n % 16));
+}
+
+static void chacha20poly1305_finalize(struct chacha20poly1305_context_t *ctx, uint8_t *tag)
+{
+    uint8_t lenbuf[16];
+
+    chacha20poly1305_encrypt_pad(&ctx->poly, ctx->textlen);
+
+    write64_le(ctx->aadlen, lenbuf);
+    write64_le(ctx->textlen, lenbuf + 8);
+    cf_poly1305_update(&ctx->poly, lenbuf, sizeof(lenbuf));
+
+    cf_poly1305_finish(&ctx->poly, tag);
+}
+
+static void chacha20poly1305_init(ptls_aead_context_t *_ctx, const void *iv, const void *aad, size_t aadlen)
+{
+    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+    uint8_t tmpbuf[64];
+
+    /* init chacha */
+    memset(tmpbuf, 0, 16 - PTLS_CHACHA20POLY1305_IV_SIZE);
+    memcpy(tmpbuf + 16 - PTLS_CHACHA20POLY1305_IV_SIZE, iv, PTLS_CHACHA20POLY1305_IV_SIZE);
+    cf_chacha20_init_custom(&ctx->chacha, ctx->key, sizeof(ctx->key), tmpbuf, 4);
+
+    /* init poly1305 (by using first 16 bytes of the key stream of the first block) */
+    cf_chacha20_cipher(&ctx->chacha, zeros64, tmpbuf, 64);
+    cf_poly1305_init(&ctx->poly, tmpbuf, tmpbuf + 16);
+
+    ptls_clear_memory(tmpbuf, sizeof(tmpbuf));
+
+    /* aad */
+    if (aadlen != 0) {
+        cf_poly1305_update(&ctx->poly, aad, aadlen);
+        chacha20poly1305_encrypt_pad(&ctx->poly, aadlen);
+    }
+
+    ctx->aadlen = aadlen;
+    ctx->textlen = 0;
+}
+
+static size_t chacha20poly1305_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
+{
+    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+    cf_chacha20_cipher(&ctx->chacha, input, output, inlen);
+    cf_poly1305_update(&ctx->poly, output, inlen);
+    ctx->textlen += inlen;
+
+    return inlen;
+}
+
+static size_t chacha20poly1305_encrypt_final(ptls_aead_context_t *_ctx, void *output)
+{
+    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+    chacha20poly1305_finalize(ctx, output);
+
+    ptls_clear_memory(&ctx->chacha, sizeof(ctx->chacha));
+    return PTLS_CHACHA20POLY1305_TAG_SIZE;
+}
+
+static size_t chacha20poly1305_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, const void *iv,
+                                       const void *aad, size_t aadlen)
+{
+    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+    uint8_t tag[PTLS_CHACHA20POLY1305_TAG_SIZE];
+    size_t ret;
+
+    if (inlen < sizeof(tag))
+        return SIZE_MAX;
+
+    chacha20poly1305_init(&ctx->super, iv, aad, aadlen);
+
+    cf_poly1305_update(&ctx->poly, input, inlen - sizeof(tag));
+    ctx->textlen = inlen - sizeof(tag);
+
+    chacha20poly1305_finalize(ctx, tag);
+    if (mem_eq(tag, (const uint8_t *)input + inlen - sizeof(tag), sizeof(tag))) {
+        cf_chacha20_cipher(&ctx->chacha, input, output, inlen - sizeof(tag));
+        ret = inlen - sizeof(tag);
+    } else {
+        ret = SIZE_MAX;
+    }
+
+    ptls_clear_memory(tag, sizeof(tag));
+    ptls_clear_memory(&ctx->poly, sizeof(ctx->poly));
+
+    return ret;
+}
+
+static int aead_chacha20poly1305_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key)
+{
+    struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+    ctx->super.dispose_crypto = chacha20poly1305_dispose_crypto;
+    if (is_enc) {
+        ctx->super.do_encrypt_init = chacha20poly1305_init;
+        ctx->super.do_encrypt_update = chacha20poly1305_encrypt_update;
+        ctx->super.do_encrypt_final = chacha20poly1305_encrypt_final;
+        ctx->super.do_decrypt = NULL;
+    } else {
+        ctx->super.do_encrypt_init = NULL;
+        ctx->super.do_encrypt_update = NULL;
+        ctx->super.do_encrypt_final = NULL;
+        ctx->super.do_decrypt = chacha20poly1305_decrypt;
+    }
+
+    memcpy(ctx->key, key, sizeof(ctx->key));
+    return 0;
+}
+
+ptls_cipher_algorithm_t ptls_minicrypto_chacha20 = {
+    "CHACHA20",           PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct chacha20_context_t),
+    chacha20_setup_crypto};
+ptls_aead_algorithm_t ptls_minicrypto_chacha20poly1305 = {"CHACHA20-POLY1305",
+                                                          &ptls_minicrypto_chacha20,
+                                                          NULL,
+                                                          PTLS_CHACHA20_KEY_SIZE,
+                                                          PTLS_CHACHA20POLY1305_IV_SIZE,
+                                                          PTLS_CHACHA20POLY1305_TAG_SIZE,
+                                                          sizeof(struct chacha20poly1305_context_t),
+                                                          aead_chacha20poly1305_setup_crypto};
+ptls_cipher_suite_t ptls_minicrypto_chacha20poly1305sha256 = {PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256,
+                                                              &ptls_minicrypto_chacha20poly1305, &ptls_minicrypto_sha256};
diff --git a/lib/cifra/random.c b/lib/cifra/random.c
new file mode 100644
index 0000000..4dc3a55
--- /dev/null
+++ b/lib/cifra/random.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016-2019 DeNA Co., Ltd., Kazuho Oku, Christian Huitema
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _WINDOWS
+#include "wincompat.h"
+#else
+#include <unistd.h>
+#endif
+#include "drbg.h"
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+#include <stdio.h>
+#ifdef _WINDOWS
+#ifdef _WINDOWS_XP
+ /* The modern BCrypt API is only available on Windows Vista and later versions.
+  * If compiling on Windows XP, we need to use the olded "wincrypt" API */
+#include <wincrypt.h>
+
+static void read_entropy(uint8_t *entropy, size_t size)
+{
+    HCRYPTPROV hCryptProv = 0;
+    BOOL ret = FALSE;
+
+    if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
+        ret = CryptGenRandom(hCryptProv, (DWORD)size, entropy);
+        (void)CryptReleaseContext(hCryptProv, 0);
+    }
+
+    if (ret == FALSE) {
+        perror("ptls_minicrypto_random_bytes: could not use CryptGenRandom");
+        abort();
+    }
+}
+#else
+ /* The old "Wincrypt" API requires access to default security containers.
+  * This can cause access control errors on some systems. We prefer
+  * to use the modern BCrypt API when available */
+#include <bcrypt.h>
+
+ static void read_entropy(uint8_t *entropy, size_t size)
+ {
+    NTSTATUS nts = 0;
+    BCRYPT_ALG_HANDLE hAlgorithm = 0;
+
+    nts = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_RNG_ALGORITHM, NULL, 0);
+
+    if (BCRYPT_SUCCESS(nts)) {
+        nts = BCryptGenRandom(hAlgorithm, (PUCHAR)entropy, (ULONG)size, 0);
+
+        (void)BCryptCloseAlgorithmProvider(hAlgorithm, 0);
+    }
+
+    if (!BCRYPT_SUCCESS(nts)) {
+        perror("ptls_minicrypto_random_bytes: could not open BCrypt RNG Algorithm");
+        abort();
+    }
+}
+#endif
+#else
+static void read_entropy(uint8_t *entropy, size_t size)
+{
+    int fd;
+
+    if ((fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC)) == -1) {
+        if ((fd = open("/dev/random", O_RDONLY | O_CLOEXEC)) == -1) {
+            perror("ptls_minicrypto_random_bytes: could not open neither /dev/random or /dev/urandom");
+            abort();
+        }
+    }
+
+    while (size != 0) {
+        ssize_t rret;
+        while ((rret = read(fd, entropy, size)) == -1 && errno == EINTR)
+            ;
+        if (rret < 0) {
+            perror("ptls_minicrypto_random_bytes");
+            abort();
+        }
+        entropy += rret;
+        size -= rret;
+    }
+
+    close(fd);
+}
+#endif
+
+void ptls_minicrypto_random_bytes(void *buf, size_t len)
+{
+#ifdef _WINDOWS
+    static __declspec(thread) cf_hash_drbg_sha256 ctx;
+#else
+    static __thread cf_hash_drbg_sha256 ctx;
+#endif
+
+    if (cf_hash_drbg_sha256_needs_reseed(&ctx)) {
+        uint8_t entropy[256];
+        read_entropy(entropy, sizeof(entropy));
+        cf_hash_drbg_sha256_init(&ctx, entropy, sizeof(entropy) / 2, entropy + sizeof(entropy) / 2, sizeof(entropy) / 2, "ptls", 4);
+    }
+    cf_hash_drbg_sha256_gen(&ctx, buf, len);
+}
diff --git a/lib/cifra/x25519.c b/lib/cifra/x25519.c
new file mode 100644
index 0000000..3d28487
--- /dev/null
+++ b/lib/cifra/x25519.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include "curve25519.h"
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+
+#define X25519_KEY_SIZE 32
+
+struct st_x25519_key_exchange_t {
+    ptls_key_exchange_context_t super;
+    uint8_t priv[X25519_KEY_SIZE];
+    uint8_t pub[X25519_KEY_SIZE];
+};
+
+static void x25519_create_keypair(uint8_t *priv, uint8_t *pub)
+{
+    ptls_minicrypto_random_bytes(priv, X25519_KEY_SIZE);
+    cf_curve25519_mul_base(pub, priv);
+}
+
+static int x25519_derive_secret(ptls_iovec_t *secret, const uint8_t *clientpriv, const uint8_t *clientpub,
+                                const uint8_t *serverpriv, const uint8_t *serverpub)
+{
+    if ((secret->base = malloc(X25519_KEY_SIZE)) == NULL)
+        return PTLS_ERROR_NO_MEMORY;
+
+    cf_curve25519_mul(secret->base, clientpriv != NULL ? clientpriv : serverpriv, clientpriv != NULL ? serverpub : clientpub);
+    secret->len = X25519_KEY_SIZE;
+    return 0;
+}
+
+static int x25519_on_exchange(ptls_key_exchange_context_t **_ctx, int release, ptls_iovec_t *secret, ptls_iovec_t peerkey)
+{
+    struct st_x25519_key_exchange_t *ctx = (struct st_x25519_key_exchange_t *)*_ctx;
+    int ret;
+
+    if (secret == NULL) {
+        ret = 0;
+        goto Exit;
+    }
+
+    if (peerkey.len != X25519_KEY_SIZE) {
+        ret = PTLS_ALERT_DECRYPT_ERROR;
+        goto Exit;
+    }
+    ret = x25519_derive_secret(secret, ctx->priv, ctx->pub, NULL, peerkey.base);
+
+Exit:
+    if (release) {
+        ptls_clear_memory(ctx->priv, sizeof(ctx->priv));
+        free(ctx);
+        *_ctx = NULL;
+    }
+    return ret;
+}
+
+static int x25519_create_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **_ctx)
+{
+    struct st_x25519_key_exchange_t *ctx;
+
+    if ((ctx = (struct st_x25519_key_exchange_t *)malloc(sizeof(*ctx))) == NULL)
+        return PTLS_ERROR_NO_MEMORY;
+    ctx->super = (ptls_key_exchange_context_t){algo, ptls_iovec_init(ctx->pub, sizeof(ctx->pub)), x25519_on_exchange};
+    x25519_create_keypair(ctx->priv, ctx->pub);
+
+    *_ctx = &ctx->super;
+    return 0;
+}
+
+static int x25519_key_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret,
+                               ptls_iovec_t peerkey)
+{
+    uint8_t priv[X25519_KEY_SIZE], *pub = NULL;
+    int ret;
+
+    if (peerkey.len != X25519_KEY_SIZE) {
+        ret = PTLS_ALERT_DECRYPT_ERROR;
+        goto Exit;
+    }
+    if ((pub = malloc(X25519_KEY_SIZE)) == NULL) {
+        ret = PTLS_ERROR_NO_MEMORY;
+        goto Exit;
+    }
+
+    x25519_create_keypair(priv, pub);
+    if ((ret = x25519_derive_secret(secret, NULL, peerkey.base, priv, pub)) != 0)
+        goto Exit;
+
+    *pubkey = ptls_iovec_init(pub, X25519_KEY_SIZE);
+    ret = 0;
+
+Exit:
+    ptls_clear_memory(priv, sizeof(priv));
+    if (pub != NULL && ret != 0)
+        ptls_clear_memory(pub, X25519_KEY_SIZE);
+    return ret;
+}
+
+ptls_key_exchange_algorithm_t ptls_minicrypto_x25519 = {PTLS_GROUP_X25519, x25519_create_key_exchange, x25519_key_exchange};
diff --git a/lib/openssl.c b/lib/openssl.c
index 5ce6e85..9f95768 100644
--- a/lib/openssl.c
+++ b/lib/openssl.c
@@ -48,7 +48,7 @@
 #define _CRT_SECURE_NO_WARNINGS
 #endif
 #pragma warning(disable : 4996)
-#include <ms\applink.c>
+#include <ms/applink.c>
 #endif
 
 #if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
diff --git a/lib/picotls.c b/lib/picotls.c
index a479bb8..d79d96c 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -1658,8 +1658,8 @@
     });
 
     /* check validity period */
-    now = ctx->get_time->cb(ctx->get_time) / 1000;
-    if (!(not_before <= now && now <= not_after)) {
+    now = ctx->get_time->cb(ctx->get_time);
+    if (!(not_before * 1000 <= now && now <= not_after * 1000)) {
         ret = PTLS_ALERT_DECODE_ERROR;
         goto Exit;
     }
diff --git a/picotls.xcodeproj/project.pbxproj b/picotls.xcodeproj/project.pbxproj
index 793bf0f..921682e 100644
--- a/picotls.xcodeproj/project.pbxproj
+++ b/picotls.xcodeproj/project.pbxproj
@@ -116,6 +116,17 @@
 		E9E865EB203BD46600E2FFCD /* sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = E9E865E9203BD45600E2FFCD /* sha512.c */; };
 		E9E865EC203BD46600E2FFCD /* sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = E9E865E9203BD45600E2FFCD /* sha512.c */; };
 		E9E865ED203BD46700E2FFCD /* sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = E9E865E9203BD45600E2FFCD /* sha512.c */; };
+		E9F20BEA22E34B3E0018D260 /* aes-common.h in Headers */ = {isa = PBXBuildFile; fileRef = E9F20BE322E34B340018D260 /* aes-common.h */; };
+		E9F20BEB22E34B3E0018D260 /* aes128.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BE222E34B340018D260 /* aes128.c */; };
+		E9F20BEC22E34B3E0018D260 /* aes256.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BE022E34B340018D260 /* aes256.c */; };
+		E9F20BED22E34B3E0018D260 /* chacha20.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BE422E34B340018D260 /* chacha20.c */; };
+		E9F20BEE22E34B3E0018D260 /* x25519.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BE122E34B340018D260 /* x25519.c */; };
+		E9F20BEF22E34B480018D260 /* aes128.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BE222E34B340018D260 /* aes128.c */; };
+		E9F20BF022E34B480018D260 /* aes256.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BE022E34B340018D260 /* aes256.c */; };
+		E9F20BF122E34B480018D260 /* chacha20.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BE422E34B340018D260 /* chacha20.c */; };
+		E9F20BF222E34B480018D260 /* x25519.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BE122E34B340018D260 /* x25519.c */; };
+		E9F20BFB22E34C1B0018D260 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BF922E34C110018D260 /* random.c */; };
+		E9F20BFC22E34C1C0018D260 /* random.c in Sources */ = {isa = PBXBuildFile; fileRef = E9F20BF922E34C110018D260 /* random.c */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -254,6 +265,12 @@
 		E9E4B12A2180530400514B47 /* certificate_compression.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = certificate_compression.c; sourceTree = "<group>"; };
 		E9E4B12C2181927900514B47 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
 		E9E865E9203BD45600E2FFCD /* sha512.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sha512.c; path = src/sha512.c; sourceTree = "<group>"; };
+		E9F20BE022E34B340018D260 /* aes256.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aes256.c; sourceTree = "<group>"; };
+		E9F20BE122E34B340018D260 /* x25519.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x25519.c; sourceTree = "<group>"; };
+		E9F20BE222E34B340018D260 /* aes128.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aes128.c; sourceTree = "<group>"; };
+		E9F20BE322E34B340018D260 /* aes-common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "aes-common.h"; sourceTree = "<group>"; };
+		E9F20BE422E34B340018D260 /* chacha20.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = chacha20.c; sourceTree = "<group>"; };
+		E9F20BF922E34C110018D260 /* random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = random.c; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -402,6 +419,7 @@
 				E99B75DE1F5CDDB500CF503E /* asn1.c */,
 				E97577022212405D00D1EF74 /* ffx.c */,
 				E99B75DF1F5CDDB500CF503E /* pembase64.c */,
+				E9F20BDF22E34B210018D260 /* cifra */,
 				1059003F1DC8D53200FB4085 /* cifra.c */,
 				106530C21D9B004B005B2C60 /* openssl.c */,
 				106530BF1D998641005B2C60 /* picotls.c */,
@@ -464,6 +482,19 @@
 			path = src;
 			sourceTree = "<group>";
 		};
+		E9F20BDF22E34B210018D260 /* cifra */ = {
+			isa = PBXGroup;
+			children = (
+				E9F20BE322E34B340018D260 /* aes-common.h */,
+				E9F20BE222E34B340018D260 /* aes128.c */,
+				E9F20BE022E34B340018D260 /* aes256.c */,
+				E9F20BE422E34B340018D260 /* chacha20.c */,
+				E9F20BF922E34C110018D260 /* random.c */,
+				E9F20BE122E34B340018D260 /* x25519.c */,
+			);
+			path = cifra;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXHeadersBuildPhase section */
@@ -513,6 +544,7 @@
 				10EACB081DCEAF0F00CA0341 /* cf_config.h in Headers */,
 				10EACB091DCEAF0F00CA0341 /* handy.h in Headers */,
 				10EACB0A1DCEAF0F00CA0341 /* uECC.h in Headers */,
+				E9F20BEA22E34B3E0018D260 /* aes-common.h in Headers */,
 				10EACB0B1DCEAF0F00CA0341 /* drbg.h in Headers */,
 				10EACB0C1DCEAF0F00CA0341 /* tassert.h in Headers */,
 				10EACB0D1DCEAF0F00CA0341 /* hmac.h in Headers */,
@@ -704,11 +736,16 @@
 				105900C41DC96B2200FB4085 /* uECC.c in Sources */,
 				105900441DC8D57000FB4085 /* picotest.c in Sources */,
 				105900611DC8DF8C00FB4085 /* sha256.c in Sources */,
+				E9F20BF122E34B480018D260 /* chacha20.c in Sources */,
 				E9BC76D21EF3A36A00EB7A09 /* chacha20.c in Sources */,
 				1059004E1DC8D61800FB4085 /* minicrypto.c in Sources */,
 				E99B75E31F5CE54D00CF503E /* asn1.c in Sources */,
 				E9E865ED203BD46700E2FFCD /* sha512.c in Sources */,
+				E9F20BF022E34B480018D260 /* aes256.c in Sources */,
+				E9F20BFC22E34C1C0018D260 /* random.c in Sources */,
+				E9F20BEF22E34B480018D260 /* aes128.c in Sources */,
 				10EACAF01DCC843A00CA0341 /* drbg.c in Sources */,
+				E9F20BF222E34B480018D260 /* x25519.c in Sources */,
 				E9BC76E11EF3CCDE00EB7A09 /* poly1305.c in Sources */,
 				1059006A1DC8DFE300FB4085 /* hmac.c in Sources */,
 				1059006F1DC8E00B00FB4085 /* chash.c in Sources */,
@@ -786,16 +823,21 @@
 				E949EF282073629300511ECA /* minicrypto-pem.c in Sources */,
 				10EACAF51DCEAF0F00CA0341 /* gf128.c in Sources */,
 				10EACAF61DCEAF0F00CA0341 /* gcm.c in Sources */,
+				E9F20BED22E34B3E0018D260 /* chacha20.c in Sources */,
+				E9F20BFB22E34C1B0018D260 /* random.c in Sources */,
+				E9F20BEC22E34B3E0018D260 /* aes256.c in Sources */,
 				10EACAF71DCEAF0F00CA0341 /* sha256.c in Sources */,
 				10EACAF81DCEAF0F00CA0341 /* aes.c in Sources */,
 				E9BC76DD1EF3CCD100EB7A09 /* poly1305.c in Sources */,
 				10EACAF91DCEAF0F00CA0341 /* modes.c in Sources */,
 				E9BC76CF1EF3A35E00EB7A09 /* chacha20.c in Sources */,
 				10EACAFB1DCEAF0F00CA0341 /* chash.c in Sources */,
+				E9F20BEB22E34B3E0018D260 /* aes128.c in Sources */,
 				10EACAFC1DCEAF0F00CA0341 /* curve25519.c in Sources */,
 				10EACAFD1DCEAF0F00CA0341 /* hmac.c in Sources */,
 				10EACAFE1DCEAF0F00CA0341 /* drbg.c in Sources */,
 				E9E865EB203BD46600E2FFCD /* sha512.c in Sources */,
+				E9F20BEE22E34B3E0018D260 /* x25519.c in Sources */,
 				10EACAFF1DCEAF0F00CA0341 /* cifra.c in Sources */,
 				10EACB001DCEAF0F00CA0341 /* blockwise.c in Sources */,
 			);
diff --git a/picotlsvs/picotls-core/picotls-core.vcxproj b/picotlsvs/picotls-core/picotls-core.vcxproj
new file mode 100644
index 0000000..6cca7d6
--- /dev/null
+++ b/picotlsvs/picotls-core/picotls-core.vcxproj
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{497433FE-B252-4985-A504-54EB791F57F4}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>picotlscore</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\lib\pembase64.c" />
+    <ClCompile Include="..\..\lib\picotls.c" />
+    <ClCompile Include="..\picotls\wintimeofday.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-core/picotls-core.vcxproj.filters b/picotlsvs/picotls-core/picotls-core.vcxproj.filters
new file mode 100644
index 0000000..8cb862a
--- /dev/null
+++ b/picotlsvs/picotls-core/picotls-core.vcxproj.filters
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\lib\pembase64.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\picotls.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\picotls\wintimeofday.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-core/picotls-core.vcxproj.user b/picotlsvs/picotls-core/picotls-core.vcxproj.user
new file mode 100644
index 0000000..be25078
--- /dev/null
+++ b/picotlsvs/picotls-core/picotls-core.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-core/targetver.h b/picotlsvs/picotls-core/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/picotlsvs/picotls-core/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/picotlsvs/picotls-esni/picotls-esni.vcxproj b/picotlsvs/picotls-esni/picotls-esni.vcxproj
index 9e4678f..0e22f56 100644
--- a/picotlsvs/picotls-esni/picotls-esni.vcxproj
+++ b/picotlsvs/picotls-esni/picotls-esni.vcxproj
@@ -98,13 +98,13 @@
       <PreprocessorDefinitions>_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
-      <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;$(ProjectDir)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OPENSSL64DIR)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;libcrypto.lib;libssl.lib;microecc.lib;cifra.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -116,13 +116,13 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
-      <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(ProjectDir)..\..\include;$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(OPENSSLDIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OPENSSLDIR)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;libcrypto.lib;libssl.lib;microecc.lib;cifra.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -136,7 +136,7 @@
       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
-      <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(ProjectDir)..\..\include;$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(OPENSSLDIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -144,7 +144,7 @@
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OPENSSLDIR)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;libcrypto.lib;libssl.lib;microecc.lib;cifra.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -158,7 +158,7 @@
       <PreprocessorDefinitions>NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
       <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
-      <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;$(ProjectDir)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -166,7 +166,7 @@
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OPENSSL64DIR)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;libcrypto.lib;libssl.lib;microecc.lib;cifra.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj b/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj
new file mode 100644
index 0000000..27e57f6
--- /dev/null
+++ b/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>picotlsminicryptodeps</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\deps\cifra\src\aes.c" />
+    <ClCompile Include="..\..\deps\cifra\src\blockwise.c" />
+    <ClCompile Include="..\..\deps\cifra\src\chacha20.c" />
+    <ClCompile Include="..\..\deps\cifra\src\chash.c" />
+    <ClCompile Include="..\..\deps\cifra\src\curve25519.c" />
+    <ClCompile Include="..\..\deps\cifra\src\drbg.c" />
+    <ClCompile Include="..\..\deps\cifra\src\gcm.c" />
+    <ClCompile Include="..\..\deps\cifra\src\gf128.c" />
+    <ClCompile Include="..\..\deps\cifra\src\hmac.c" />
+    <ClCompile Include="..\..\deps\cifra\src\modes.c" />
+    <ClCompile Include="..\..\deps\cifra\src\poly1305.c" />
+    <ClCompile Include="..\..\deps\cifra\src\sha256.c" />
+    <ClCompile Include="..\..\deps\cifra\src\sha512.c" />
+    <ClCompile Include="..\..\deps\micro-ecc\uECC.c" />
+    <ClCompile Include="..\..\lib\cifra.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj.filters b/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj.filters
new file mode 100644
index 0000000..909a8ca
--- /dev/null
+++ b/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj.filters
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\deps\cifra\src\aes.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\blockwise.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\chacha20.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\chash.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\cifra.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\curve25519.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\drbg.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\gcm.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\gf128.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\hmac.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\poly1305.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\sha256.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\sha512.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\micro-ecc\uECC.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\deps\cifra\src\modes.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj.user b/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj.user
new file mode 100644
index 0000000..be25078
--- /dev/null
+++ b/picotlsvs/picotls-minicrypto-deps/picotls-minicrypto-deps.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-minicrypto-deps/targetver.h b/picotlsvs/picotls-minicrypto-deps/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/picotlsvs/picotls-minicrypto-deps/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj b/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj
new file mode 100644
index 0000000..6469f0e
--- /dev/null
+++ b/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{559AC085-1BEF-450A-A62D-0D370561D596}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>picotlsminicrypto</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\micro-ecc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\micro-ecc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\micro-ecc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\micro-ecc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\lib\asn1.c" />
+    <ClCompile Include="..\..\lib\cifra.c" />
+    <ClCompile Include="..\..\lib\cifra\aes128.c" />
+    <ClCompile Include="..\..\lib\cifra\aes256.c" />
+    <ClCompile Include="..\..\lib\cifra\chacha20.c" />
+    <ClCompile Include="..\..\lib\cifra\random.c" />
+    <ClCompile Include="..\..\lib\cifra\x25519.c" />
+    <ClCompile Include="..\..\lib\ffx.c" />
+    <ClCompile Include="..\..\lib\minicrypto-pem.c" />
+    <ClCompile Include="..\..\lib\uecc.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj.filters b/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj.filters
new file mode 100644
index 0000000..b770ce5
--- /dev/null
+++ b/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj.filters
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\lib\cifra.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\cifra\aes128.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\cifra\aes256.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\cifra\chacha20.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\cifra\x25519.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\asn1.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\ffx.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\minicrypto-pem.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\uecc.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\lib\cifra\random.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj.user b/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj.user
new file mode 100644
index 0000000..be25078
--- /dev/null
+++ b/picotlsvs/picotls-minicrypto/picotls-minicrypto.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-minicrypto/targetver.h b/picotlsvs/picotls-minicrypto/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/picotlsvs/picotls-minicrypto/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/picotlsvs/picotls-openssl/picotls-openssl.vcxproj b/picotlsvs/picotls-openssl/picotls-openssl.vcxproj
new file mode 100644
index 0000000..ffa492c
--- /dev/null
+++ b/picotlsvs/picotls-openssl/picotls-openssl.vcxproj
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{56C264BF-822B-4F29-B512-5B26157CA2EC}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>picotlsopenssl</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(OPENSSL64DIR)\include;$(OPENSSL64DIR);$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(OPENSSLDIR);$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)\..\..\picotls;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\deps\cifra\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(OPENSSLDIR);$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)\..\..\picotls;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\deps\cifra\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <AdditionalIncludeDirectories>$(OPENSSL64DIR)\include;$(OPENSSL64DIR);$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\lib\openssl.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-openssl/picotls-openssl.vcxproj.filters b/picotlsvs/picotls-openssl/picotls-openssl.vcxproj.filters
new file mode 100644
index 0000000..d199a14
--- /dev/null
+++ b/picotlsvs/picotls-openssl/picotls-openssl.vcxproj.filters
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\lib\openssl.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-openssl/picotls-openssl.vcxproj.user b/picotlsvs/picotls-openssl/picotls-openssl.vcxproj.user
new file mode 100644
index 0000000..be25078
--- /dev/null
+++ b/picotlsvs/picotls-openssl/picotls-openssl.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/picotls-openssl/targetver.h b/picotlsvs/picotls-openssl/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/picotlsvs/picotls-openssl/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/picotlsvs/picotlsvs.sln b/picotlsvs/picotlsvs.sln
index 39a4171..194eeac 100644
--- a/picotlsvs/picotlsvs.sln
+++ b/picotlsvs/picotlsvs.sln
@@ -5,38 +5,44 @@
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotlsvs", "picotlsvs\picotlsvs.vcxproj", "{D0265367-FCCF-47A4-95FD-C33BECAB3486}"
 	ProjectSection(ProjectDependencies) = postProject
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440} = {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821} = {46E6D6E9-7A30-4058-9661-DF70CC07E821}
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A} = {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}
+		{559AC085-1BEF-450A-A62D-0D370561D596} = {559AC085-1BEF-450A-A62D-0D370561D596}
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5} = {499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}
+		{56C264BF-822B-4F29-B512-5B26157CA2EC} = {56C264BF-822B-4F29-B512-5B26157CA2EC}
+		{497433FE-B252-4985-A504-54EB791F57F4} = {497433FE-B252-4985-A504-54EB791F57F4}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotls", "picotls\picotls.vcxproj", "{46E6D6E9-7A30-4058-9661-DF70CC07E821}"
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testopenssl", "testopenssl\testopenssl.vcxproj", "{8750EE3B-9440-48BF-8D83-7274E94B06A7}"
 	ProjectSection(ProjectDependencies) = postProject
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440} = {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821} = {46E6D6E9-7A30-4058-9661-DF70CC07E821}
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A} = {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}
+		{559AC085-1BEF-450A-A62D-0D370561D596} = {559AC085-1BEF-450A-A62D-0D370561D596}
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5} = {499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}
+		{56C264BF-822B-4F29-B512-5B26157CA2EC} = {56C264BF-822B-4F29-B512-5B26157CA2EC}
+		{497433FE-B252-4985-A504-54EB791F57F4} = {497433FE-B252-4985-A504-54EB791F57F4}
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "microecc", "microecc\microecc.vcxproj", "{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cifra", "cifra\cifra.vcxproj", "{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}"
-EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ptlsbench", "ptlsbench\ptlsbench.vcxproj", "{15D7D32F-3B62-4B10-A06A-BA1ADD591D7F}"
 	ProjectSection(ProjectDependencies) = postProject
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440} = {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821} = {46E6D6E9-7A30-4058-9661-DF70CC07E821}
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A} = {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}
+		{559AC085-1BEF-450A-A62D-0D370561D596} = {559AC085-1BEF-450A-A62D-0D370561D596}
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5} = {499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}
+		{56C264BF-822B-4F29-B512-5B26157CA2EC} = {56C264BF-822B-4F29-B512-5B26157CA2EC}
+		{497433FE-B252-4985-A504-54EB791F57F4} = {497433FE-B252-4985-A504-54EB791F57F4}
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotls-esni", "picotls-esni\picotls-esni.vcxproj", "{592127C5-DD8C-47ED-8EBA-026B5848C374}"
 	ProjectSection(ProjectDependencies) = postProject
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440} = {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821} = {46E6D6E9-7A30-4058-9661-DF70CC07E821}
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A} = {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}
+		{559AC085-1BEF-450A-A62D-0D370561D596} = {559AC085-1BEF-450A-A62D-0D370561D596}
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5} = {499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}
+		{56C264BF-822B-4F29-B512-5B26157CA2EC} = {56C264BF-822B-4F29-B512-5B26157CA2EC}
+		{497433FE-B252-4985-A504-54EB791F57F4} = {497433FE-B252-4985-A504-54EB791F57F4}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotls-core", "picotls-core\picotls-core.vcxproj", "{497433FE-B252-4985-A504-54EB791F57F4}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotls-minicrypto", "picotls-minicrypto\picotls-minicrypto.vcxproj", "{559AC085-1BEF-450A-A62D-0D370561D596}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotls-openssl", "picotls-openssl\picotls-openssl.vcxproj", "{56C264BF-822B-4F29-B512-5B26157CA2EC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotls-minicrypto-deps", "picotls-minicrypto-deps\picotls-minicrypto-deps.vcxproj", "{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|x64 = Debug|x64
@@ -53,14 +59,6 @@
 		{D0265367-FCCF-47A4-95FD-C33BECAB3486}.Release|x64.Build.0 = Release|x64
 		{D0265367-FCCF-47A4-95FD-C33BECAB3486}.Release|x86.ActiveCfg = Release|Win32
 		{D0265367-FCCF-47A4-95FD-C33BECAB3486}.Release|x86.Build.0 = Release|Win32
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821}.Debug|x64.ActiveCfg = Debug|x64
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821}.Debug|x64.Build.0 = Debug|x64
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821}.Debug|x86.ActiveCfg = Debug|Win32
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821}.Debug|x86.Build.0 = Debug|Win32
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821}.Release|x64.ActiveCfg = Release|x64
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821}.Release|x64.Build.0 = Release|x64
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821}.Release|x86.ActiveCfg = Release|Win32
-		{46E6D6E9-7A30-4058-9661-DF70CC07E821}.Release|x86.Build.0 = Release|Win32
 		{8750EE3B-9440-48BF-8D83-7274E94B06A7}.Debug|x64.ActiveCfg = Debug|x64
 		{8750EE3B-9440-48BF-8D83-7274E94B06A7}.Debug|x64.Build.0 = Debug|x64
 		{8750EE3B-9440-48BF-8D83-7274E94B06A7}.Debug|x86.ActiveCfg = Debug|Win32
@@ -69,22 +67,6 @@
 		{8750EE3B-9440-48BF-8D83-7274E94B06A7}.Release|x64.Build.0 = Release|x64
 		{8750EE3B-9440-48BF-8D83-7274E94B06A7}.Release|x86.ActiveCfg = Release|Win32
 		{8750EE3B-9440-48BF-8D83-7274E94B06A7}.Release|x86.Build.0 = Release|Win32
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Debug|x64.ActiveCfg = Debug|x64
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Debug|x64.Build.0 = Debug|x64
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Debug|x86.ActiveCfg = Debug|Win32
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Debug|x86.Build.0 = Debug|Win32
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Release|x64.ActiveCfg = Release|x64
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Release|x64.Build.0 = Release|x64
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Release|x86.ActiveCfg = Release|Win32
-		{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Release|x86.Build.0 = Release|Win32
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Debug|x64.ActiveCfg = Debug|x64
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Debug|x64.Build.0 = Debug|x64
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Debug|x86.ActiveCfg = Debug|Win32
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Debug|x86.Build.0 = Debug|Win32
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Release|x64.ActiveCfg = Release|x64
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Release|x64.Build.0 = Release|x64
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Release|x86.ActiveCfg = Release|Win32
-		{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Release|x86.Build.0 = Release|Win32
 		{15D7D32F-3B62-4B10-A06A-BA1ADD591D7F}.Debug|x64.ActiveCfg = Debug|x64
 		{15D7D32F-3B62-4B10-A06A-BA1ADD591D7F}.Debug|x64.Build.0 = Debug|x64
 		{15D7D32F-3B62-4B10-A06A-BA1ADD591D7F}.Debug|x86.ActiveCfg = Debug|Win32
@@ -101,6 +83,38 @@
 		{592127C5-DD8C-47ED-8EBA-026B5848C374}.Release|x64.Build.0 = Release|x64
 		{592127C5-DD8C-47ED-8EBA-026B5848C374}.Release|x86.ActiveCfg = Release|Win32
 		{592127C5-DD8C-47ED-8EBA-026B5848C374}.Release|x86.Build.0 = Release|Win32
+		{497433FE-B252-4985-A504-54EB791F57F4}.Debug|x64.ActiveCfg = Debug|x64
+		{497433FE-B252-4985-A504-54EB791F57F4}.Debug|x64.Build.0 = Debug|x64
+		{497433FE-B252-4985-A504-54EB791F57F4}.Debug|x86.ActiveCfg = Debug|Win32
+		{497433FE-B252-4985-A504-54EB791F57F4}.Debug|x86.Build.0 = Debug|Win32
+		{497433FE-B252-4985-A504-54EB791F57F4}.Release|x64.ActiveCfg = Release|x64
+		{497433FE-B252-4985-A504-54EB791F57F4}.Release|x64.Build.0 = Release|x64
+		{497433FE-B252-4985-A504-54EB791F57F4}.Release|x86.ActiveCfg = Release|Win32
+		{497433FE-B252-4985-A504-54EB791F57F4}.Release|x86.Build.0 = Release|Win32
+		{559AC085-1BEF-450A-A62D-0D370561D596}.Debug|x64.ActiveCfg = Debug|x64
+		{559AC085-1BEF-450A-A62D-0D370561D596}.Debug|x64.Build.0 = Debug|x64
+		{559AC085-1BEF-450A-A62D-0D370561D596}.Debug|x86.ActiveCfg = Debug|Win32
+		{559AC085-1BEF-450A-A62D-0D370561D596}.Debug|x86.Build.0 = Debug|Win32
+		{559AC085-1BEF-450A-A62D-0D370561D596}.Release|x64.ActiveCfg = Release|x64
+		{559AC085-1BEF-450A-A62D-0D370561D596}.Release|x64.Build.0 = Release|x64
+		{559AC085-1BEF-450A-A62D-0D370561D596}.Release|x86.ActiveCfg = Release|Win32
+		{559AC085-1BEF-450A-A62D-0D370561D596}.Release|x86.Build.0 = Release|Win32
+		{56C264BF-822B-4F29-B512-5B26157CA2EC}.Debug|x64.ActiveCfg = Debug|x64
+		{56C264BF-822B-4F29-B512-5B26157CA2EC}.Debug|x64.Build.0 = Debug|x64
+		{56C264BF-822B-4F29-B512-5B26157CA2EC}.Debug|x86.ActiveCfg = Debug|Win32
+		{56C264BF-822B-4F29-B512-5B26157CA2EC}.Debug|x86.Build.0 = Debug|Win32
+		{56C264BF-822B-4F29-B512-5B26157CA2EC}.Release|x64.ActiveCfg = Release|x64
+		{56C264BF-822B-4F29-B512-5B26157CA2EC}.Release|x64.Build.0 = Release|x64
+		{56C264BF-822B-4F29-B512-5B26157CA2EC}.Release|x86.ActiveCfg = Release|Win32
+		{56C264BF-822B-4F29-B512-5B26157CA2EC}.Release|x86.Build.0 = Release|Win32
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}.Debug|x64.ActiveCfg = Debug|x64
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}.Debug|x64.Build.0 = Debug|x64
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}.Debug|x86.ActiveCfg = Debug|Win32
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}.Debug|x86.Build.0 = Debug|Win32
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}.Release|x64.ActiveCfg = Release|x64
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}.Release|x64.Build.0 = Release|x64
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}.Release|x86.ActiveCfg = Release|Win32
+		{499B82B3-F5A5-4C2E-91EF-A2F77CBC33F5}.Release|x86.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/picotlsvs/picotlsvs/picotlsvs.vcxproj b/picotlsvs/picotlsvs/picotlsvs.vcxproj
index 2cca43a..f1190d1 100644
--- a/picotlsvs/picotlsvs/picotlsvs.vcxproj
+++ b/picotlsvs/picotlsvs/picotlsvs.vcxproj
@@ -88,12 +88,12 @@
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;libcrypto.lib;libssl.lib;microecc.lib;cifra.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -102,12 +102,12 @@
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <PreprocessorDefinitions>_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OPENSSL64DIR)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -118,14 +118,14 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -136,14 +136,14 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <PreprocessorDefinitions>NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OPENSSL64DIR)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
diff --git a/picotlsvs/pioctls-core/pioctls-core.vcxproj b/picotlsvs/pioctls-core/pioctls-core.vcxproj
new file mode 100644
index 0000000..c4c7e53
--- /dev/null
+++ b/picotlsvs/pioctls-core/pioctls-core.vcxproj
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>15.0</VCProjectVersion>
+    <ProjectGuid>{F53F19EE-149A-4C36-9772-25B01AB4BD7A}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>pioctlscore</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/pioctls-core/pioctls-core.vcxproj.filters b/picotlsvs/pioctls-core/pioctls-core.vcxproj.filters
new file mode 100644
index 0000000..782ac4b
--- /dev/null
+++ b/picotlsvs/pioctls-core/pioctls-core.vcxproj.filters
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/pioctls-core/pioctls-core.vcxproj.user b/picotlsvs/pioctls-core/pioctls-core.vcxproj.user
new file mode 100644
index 0000000..be25078
--- /dev/null
+++ b/picotlsvs/pioctls-core/pioctls-core.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup />
+</Project>
\ No newline at end of file
diff --git a/picotlsvs/pioctls-core/stdafx.cpp b/picotlsvs/pioctls-core/stdafx.cpp
new file mode 100644
index 0000000..fd4f341
--- /dev/null
+++ b/picotlsvs/pioctls-core/stdafx.cpp
@@ -0,0 +1 @@
+#include "stdafx.h"
diff --git a/picotlsvs/pioctls-core/stdafx.h b/picotlsvs/pioctls-core/stdafx.h
new file mode 100644
index 0000000..69f8872
--- /dev/null
+++ b/picotlsvs/pioctls-core/stdafx.h
@@ -0,0 +1,14 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
+
+
+
+// reference additional headers your program requires here
diff --git a/picotlsvs/pioctls-core/targetver.h b/picotlsvs/pioctls-core/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/picotlsvs/pioctls-core/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/picotlsvs/ptlsbench/ptlsbench.vcxproj b/picotlsvs/ptlsbench/ptlsbench.vcxproj
index 51f65a3..7c4525b 100644
--- a/picotlsvs/ptlsbench/ptlsbench.vcxproj
+++ b/picotlsvs/ptlsbench/ptlsbench.vcxproj
@@ -100,7 +100,7 @@
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OPENSSL64DIR)\lib;$(OutDir)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -118,7 +118,7 @@
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -140,7 +140,7 @@
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -162,7 +162,7 @@
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OPENSSL64DIR)\lib;$(OutDir)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/picotlsvs/ptlsbench/ptlsbench.vcxproj.user b/picotlsvs/ptlsbench/ptlsbench.vcxproj.user
index be25078..a7c76ba 100644
--- a/picotlsvs/ptlsbench/ptlsbench.vcxproj.user
+++ b/picotlsvs/ptlsbench/ptlsbench.vcxproj.user
@@ -1,4 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
 </Project>
\ No newline at end of file
diff --git a/picotlsvs/testopenssl/testopenssl.vcxproj b/picotlsvs/testopenssl/testopenssl.vcxproj
index 849725f..f1bb883 100644
--- a/picotlsvs/testopenssl/testopenssl.vcxproj
+++ b/picotlsvs/testopenssl/testopenssl.vcxproj
@@ -94,7 +94,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -104,12 +104,12 @@
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <PreprocessorDefinitions>_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSL64DIR)\include;$(OPENSSL64DIR)\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;$(OPENSSL64DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OPENSSL64DIR)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -128,7 +128,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -140,14 +140,14 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <PreprocessorDefinitions>NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSL64DIR)\include;$(OPENSSL64DIR)\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;$(OPENSSL64DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OPENSSL64DIR)\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>picotls-core.lib;picotls-openssl.lib;picotls-minicrypto.lib;picotls-minicrypto-deps.lib;libcrypto.lib;bcrypt.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>