123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848 |
- /*
- * 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.
- */
- #ifndef _WINDOWS
- /* This module is only defined for windows.
- * It is an implementation of the main crypto algorithms
- * using windows crypto libraries */
- int ptls_bcrypt_init()
- {
- return -1;
- }
- void ptlc_bcrypt_dispose()
- {
- }
- #else
- #include "wincompat.h"
- #include <bcrypt.h>
- #include "picotls.h"
- /**
- * Initialize the brcrypt libraries, creates the
- * required common variables, etc. */
- int ptls_bcrypt_init()
- {
- return 0;
- }
- /**
- * Clear the initialization of the bcrypt libraries */
- void ptlc_bcrypt_dispose()
- {
- }
- /**
- * Random number generation */
- void ptls_bcrypt_random_bytes(void *buf, size_t len)
- {
- /* TODO: Crypto gen random */
- }
- /*
- * Support for symmetric ciphers
- */
- struct ptls_bcrypt_symmetric_param_t {
- HANDLE hKey;
- DWORD dwFlags;
- ULONG cbKeyObject;
- uint8_t iv[PTLS_MAX_IV_SIZE];
- uint8_t *key_object;
- int is_enc;
- };
- struct ptls_bcrypt_symmetric_context_t {
- ptls_cipher_context_t super;
- struct ptls_bcrypt_symmetric_param_t bctx;
- };
- static void ptls_bcrypt_cipher_init_ctr(ptls_cipher_context_t *_ctx, const void *iv)
- {
- struct ptls_bcrypt_symmetric_context_t *ctx = (struct ptls_bcrypt_symmetric_context_t *)_ctx;
- /* Copy the IV to inside structure */
- if (iv != NULL) {
- memcpy(ctx->bctx.iv, iv, ctx->super.algo->block_size);
- } else {
- memset(ctx->bctx.iv, 0, ctx->super.algo->block_size);
- }
- }
- static void ptls_bcrypt_cipher_dispose(ptls_cipher_context_t *_ctx)
- {
- struct ptls_bcrypt_symmetric_context_t *ctx = (struct ptls_bcrypt_symmetric_context_t *)_ctx;
- if (ctx->bctx.hKey != NULL) {
- (void)BCryptDestroyKey(ctx->bctx.hKey);
- }
- if (ctx->bctx.key_object != NULL) {
- free(ctx->bctx.key_object);
- }
- memset(&ctx->bctx, 0, sizeof(struct ptls_bcrypt_symmetric_param_t));
- }
- static void ptls_bcrypt_cipher_transform_ecb(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
- {
- struct ptls_bcrypt_symmetric_context_t *ctx = (struct ptls_bcrypt_symmetric_context_t *)_ctx;
- ULONG cbResult;
- NTSTATUS ret;
- assert((len % ctx->super.algo->block_size) == 0);
- /* Call the encryption */
- if (ctx->bctx.is_enc) {
- ret = BCryptEncrypt(ctx->bctx.hKey, (PUCHAR)input, (ULONG)len, NULL, NULL, 0, output, (ULONG)len, &cbResult, 0);
- } else {
- ret = BCryptDecrypt(ctx->bctx.hKey, (PUCHAR)input, (ULONG)len, NULL, NULL, 0, output, (ULONG)len, &cbResult, 0);
- }
- assert(BCRYPT_SUCCESS(ret));
- if (!BCRYPT_SUCCESS(ret)) {
- memset(output, 0, cbResult);
- }
- }
- static void ptls_bcrypt_cipher_transform_ctr(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
- {
- struct ptls_bcrypt_symmetric_context_t *ctx = (struct ptls_bcrypt_symmetric_context_t *)_ctx;
- ULONG cbResult;
- NTSTATUS ret;
- uint8_t eiv[PTLS_MAX_IV_SIZE];
- size_t i;
- uint64_t seq = 0;
- size_t processed = 0;
- uint8_t const *v_in = input;
- uint8_t *v_out = output;
- assert(ctx->super.algo->block_size > 0);
- assert(ctx->super.algo->block_size <= PTLS_MAX_IV_SIZE);
- while (processed < len) {
- ret = BCryptEncrypt(ctx->bctx.hKey, (PUCHAR)ctx->bctx.iv, (ULONG)ctx->super.algo->block_size, NULL, NULL, 0, eiv,
- (ULONG)(ULONG)ctx->super.algo->block_size, &cbResult, 0);
- assert(BCRYPT_SUCCESS(ret));
- if (BCRYPT_SUCCESS(ret)) {
- for (i = 0; processed < len && i < ctx->super.algo->block_size; i++, processed++) {
- v_out[processed] = v_in[processed] ^ eiv[i];
- }
- /* Increment the iv block */
- i = (int)ctx->super.algo->block_size - 1;
- while (i >= 0) {
- ctx->bctx.iv[i] += 1;
- if (ctx->bctx.iv[i] > 0) {
- break;
- }
- i--;
- }
- }
- }
- }
- static int ptls_bcrypt_cipher_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key, wchar_t const *bcrypt_name,
- int is_ctr)
- {
- struct ptls_bcrypt_symmetric_context_t *ctx = (struct ptls_bcrypt_symmetric_context_t *)_ctx;
- HANDLE hAlgorithm = NULL;
- NTSTATUS ret;
- memset(&ctx->bctx, 0, sizeof(struct ptls_bcrypt_symmetric_param_t));
- ret = BCryptOpenAlgorithmProvider(&hAlgorithm, bcrypt_name, NULL, 0);
- if (BCRYPT_SUCCESS(ret)) {
- DWORD ko_size = 0;
- ULONG cbResult = 0;
- ret = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&ko_size, (ULONG)sizeof(ko_size), &cbResult, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ctx->bctx.key_object = (uint8_t *)malloc(ko_size);
- if (ctx->bctx.key_object == NULL) {
- ret = STATUS_NO_MEMORY;
- } else {
- ctx->bctx.cbKeyObject = ko_size;
- }
- }
- }
- if (BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(hAlgorithm, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
- }
- if (BCRYPT_SUCCESS(ret)) {
- ret = BCryptGenerateSymmetricKey(hAlgorithm, &ctx->bctx.hKey, ctx->bctx.key_object, ctx->bctx.cbKeyObject, (PUCHAR)key,
- (ULONG)ctx->super.algo->key_size, 0);
- }
- if (hAlgorithm != NULL) {
- BCryptCloseAlgorithmProvider(hAlgorithm, 0);
- }
- if (BCRYPT_SUCCESS(ret)) {
- ctx->super.do_dispose = ptls_bcrypt_cipher_dispose;
- if (is_ctr) {
- ctx->super.do_init = ptls_bcrypt_cipher_init_ctr;
- ctx->super.do_transform = ptls_bcrypt_cipher_transform_ctr;
- } else {
- ctx->super.do_init = NULL;
- ctx->super.do_transform = ptls_bcrypt_cipher_transform_ecb;
- }
- ctx->bctx.is_enc = is_enc;
- return 0;
- } else {
- ptls_bcrypt_cipher_dispose(_ctx);
- return PTLS_ERROR_LIBRARY;
- }
- }
- static int ptls_bcrypt_cipher_setup_crypto_aes_ecb(ptls_cipher_context_t *_ctx, int is_enc, const void *key)
- {
- return ptls_bcrypt_cipher_setup_crypto(_ctx, is_enc, key, BCRYPT_AES_ALGORITHM, 0);
- }
- static int ptls_bcrypt_cipher_setup_crypto_aes_ctr(ptls_cipher_context_t *_ctx, int is_enc, const void *key)
- {
- return ptls_bcrypt_cipher_setup_crypto(_ctx, is_enc, key, BCRYPT_AES_ALGORITHM, 1);
- }
- /* Picotls assumes that AEAD encryption works as:
- * - an "init" call that prepares the encryption context.
- * - a series of "update" calls that encrypt segments of the message
- * - a "final" call that completes the encryption.
- *
- * In Bcrypt, the update calls will be implemented as a series of calls
- * to BCryptEncrypt. The state necessary to pass these calls is provided
- * to the Bcrypt function in two parameters:
- * - the "padding info" points to a BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
- * structure
- * - the "IV" parameter points to a buffer holding intermediate updates
- * of the IV. That buffer shall be initialize to zero before the
- * first call.
- * The documentation of the AEAD mode on MSDN is slightly obscure, and
- * also slightly wrong. After trial and errors and web searches, we find
- * that:
- * - the Nonce parameter (pbNonce, cbNonce) points to the initial
- * vector for the encryption, as passed by Picotls. Picotls combines
- * per session IV and sequence number in that nonce prior to the call.
- * - The Authdata parameter (pbAuthData, cbAuthData) points to the
- * authenticated data passed to the API as aad, aadlen.
- * - The cbAAd parameter contains the length of auth data that needs
- * to be processed. It is initialized before the first call.
- * - The tag parameter (pbTag, cbTag) points to a buffer that
- * holds intermediate tag values during chaining. The size must be
- * the size of the tag for the algorithm. It must be
- * initialized to zero before first call.
- * - The Mac Context parameter (pbMacContext, cbMacContext) contains
- * a working buffer for the computation of the tag. The size
- * must be the maxLength parameter returned retrieved in the
- * BCRYPT_AUTH_TAG_LENGTH property of the algorithm. It must be
- * initialized to zero before first call.
- * - The dwflag parameters must be set to
- * BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG on first call. (The
- * MSDN documentation says BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG,
- * but that's an error.)
- *
- * The members of the BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO struct
- * should not be modified between calls, except for:
- * - the BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG should be cleared
- * before the final call.
- *
- * The Picotls API does not constrain the length of the segments
- * passed in the "update" calls, but BCryptEncrypt will fail with
- * error STATUS_INVALID_BUFFER_SIZE if the length passed in the
- * chained calls is not an integer multiple of block size. This forces
- * us to maintain an intermediate buffer of "extra bytes".
- *
- */
- struct ptls_bcrypt_aead_param_t {
- HANDLE hKey;
- ULONG cbKeyObject;
- ULONG maxTagLength;
- ULONG nbExtraBytes;
- uint8_t *key_object;
- uint8_t iv_static[PTLS_MAX_IV_SIZE];
- uint8_t extraBytes[PTLS_MAX_DIGEST_SIZE];
- uint8_t iv[PTLS_MAX_IV_SIZE];
- uint8_t ivbuf[PTLS_MAX_IV_SIZE];
- uint8_t tag[PTLS_MAX_DIGEST_SIZE];
- uint8_t auth_tag[PTLS_MAX_DIGEST_SIZE];
- BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO aead_params;
- };
- struct ptls_bcrypt_aead_context_t {
- struct st_ptls_aead_context_t super;
- struct ptls_bcrypt_aead_param_t bctx;
- };
- static void ptls_bcrypt_aead_dispose_crypto(struct st_ptls_aead_context_t *_ctx)
- {
- struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
- if (ctx->bctx.hKey != NULL) {
- (void)BCryptDestroyKey(ctx->bctx.hKey);
- }
- if (ctx->bctx.key_object != NULL) {
- free(ctx->bctx.key_object);
- }
- memset(&ctx->bctx, 0, sizeof(struct ptls_bcrypt_aead_param_t));
- }
- static void ptls_bcrypt_aead_do_encrypt_init(struct st_ptls_aead_context_t *_ctx, uint64_t seq, const void *aad, size_t aadlen)
- {
- struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
- /* Build the IV for this encryption */
- ptls_aead__build_iv(ctx->super.algo, ctx->bctx.iv, ctx->bctx.iv_static, seq);
- /* Auth tag to NULL */
- memset(ctx->bctx.tag, 0, sizeof(ctx->super.algo->tag_size));
- BCRYPT_INIT_AUTH_MODE_INFO(ctx->bctx.aead_params);
- assert(ctx->super.algo->iv_size <= sizeof(ctx->bctx.ivbuf));
- assert(ctx->super.algo->tag_size <= sizeof(ctx->bctx.tag));
- assert(ctx->bctx.maxTagLength <= sizeof(ctx->bctx.auth_tag));
- memset(ctx->bctx.ivbuf, 0, ctx->super.algo->iv_size);
- memset(ctx->bctx.tag, 0, ctx->super.algo->tag_size);
- memset(ctx->bctx.auth_tag, 0, sizeof(ctx->bctx.auth_tag));
- ctx->bctx.nbExtraBytes = 0;
- ctx->bctx.aead_params.pbNonce = (PUCHAR)&ctx->bctx.iv;
- ctx->bctx.aead_params.cbNonce = (ULONG)ctx->super.algo->iv_size;
- ctx->bctx.aead_params.pbAuthData = (PUCHAR)aad;
- ctx->bctx.aead_params.cbAuthData = (ULONG)aadlen;
- ctx->bctx.aead_params.pbTag = (PUCHAR)ctx->bctx.tag;
- ctx->bctx.aead_params.cbTag = (ULONG)ctx->super.algo->tag_size;
- // ctx->bctx.aead_params.cbAAD = (ULONG)aadlen;
- ctx->bctx.aead_params.pbMacContext = (PUCHAR)ctx->bctx.auth_tag;
- ctx->bctx.aead_params.cbMacContext = (ULONG)ctx->bctx.maxTagLength;
- ctx->bctx.aead_params.dwFlags = BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG;
- }
- static size_t ptls_bcrypt_aead_do_encrypt_update(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
- {
- struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
- size_t outlenMax = inlen + ctx->super.algo->tag_size + ctx->bctx.nbExtraBytes;
- ULONG cbResult1 = 0;
- ULONG cbResult2 = 0;
- NTSTATUS ret;
- /* If there are extra bytes, complement and encrypt */
- if (ctx->bctx.nbExtraBytes > 0) {
- ULONG requiredBytes = (ULONG)(ctx->super.algo->ecb_cipher->block_size - ctx->bctx.nbExtraBytes);
- if (inlen < requiredBytes) {
- memcpy(&ctx->bctx.extraBytes[ctx->bctx.nbExtraBytes], input, inlen);
- ctx->bctx.nbExtraBytes += (ULONG)inlen;
- inlen = 0;
- } else {
- memcpy(&ctx->bctx.extraBytes[ctx->bctx.nbExtraBytes], input, requiredBytes);
- inlen -= requiredBytes;
- input = (void *)(((uint8_t *)input) + requiredBytes);
- ret = BCryptEncrypt(ctx->bctx.hKey, (PUCHAR)ctx->bctx.extraBytes, (ULONG)ctx->super.algo->ecb_cipher->block_size,
- (void *)&ctx->bctx.aead_params, ctx->bctx.ivbuf, (ULONG)ctx->super.algo->iv_size, output,
- (ULONG)outlenMax, &cbResult1, 0);
- assert(BCRYPT_SUCCESS(ret));
- if (!BCRYPT_SUCCESS(ret)) {
- memset(output, 0, cbResult1);
- }
- outlenMax -= cbResult1;
- output = (void *)(((uint8_t *)output) + cbResult1);
- }
- }
- /* If there are trailing bytes, store them in the extra bytes */
- ctx->bctx.nbExtraBytes = (ULONG)(inlen % ctx->super.algo->ecb_cipher->block_size);
- if (ctx->bctx.nbExtraBytes > 0) {
- inlen -= ctx->bctx.nbExtraBytes;
- memcpy(&ctx->bctx.extraBytes, (void *)(((uint8_t *)input) + inlen), ctx->bctx.nbExtraBytes);
- }
- if (inlen > 0) {
- ret = BCryptEncrypt(ctx->bctx.hKey, (PUCHAR)input, (ULONG)inlen, (void *)&ctx->bctx.aead_params, ctx->bctx.ivbuf,
- (ULONG)ctx->super.algo->iv_size, output, (ULONG)outlenMax, &cbResult2, 0);
- assert(BCRYPT_SUCCESS(ret));
- if (!BCRYPT_SUCCESS(ret)) {
- memset(output, 0, cbResult2);
- }
- }
- return (size_t)cbResult1 + cbResult2;
- }
- static size_t ptls_bcrypt_aead_do_encrypt_final(struct st_ptls_aead_context_t *_ctx, void *output)
- {
- struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
- size_t outlenMax = ctx->super.algo->tag_size + ctx->bctx.nbExtraBytes;
- ULONG cbResult = 0;
- NTSTATUS ret;
- ctx->bctx.aead_params.dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG;
- ret = BCryptEncrypt(ctx->bctx.hKey, (PUCHAR)ctx->bctx.extraBytes, (ULONG)ctx->bctx.nbExtraBytes, (void *)&ctx->bctx.aead_params,
- ctx->bctx.ivbuf, (ULONG)ctx->super.algo->iv_size, output, (ULONG)outlenMax, &cbResult, 0);
- assert(BCRYPT_SUCCESS(ret));
- if (BCRYPT_SUCCESS(ret)) {
- /* Find the tag in the aead parameters and append it to the output */
- assert(cbResult + ctx->bctx.aead_params.cbTag <= outlenMax);
- memcpy(((uint8_t *)output) + cbResult, ctx->bctx.aead_params.pbTag, ctx->bctx.aead_params.cbTag);
- cbResult += ctx->bctx.aead_params.cbTag;
- }
- return cbResult;
- }
- void ptls_bcrypt_do_encrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq, const void *aad,
- size_t aadlen, ptls_aead_supplementary_encryption_t *supp)
- {
- size_t after_update;
- ctx->do_encrypt_init(ctx, seq, aad, aadlen);
- after_update = ctx->do_encrypt_update(ctx, output, input, inlen);
- ctx->do_encrypt_final(ctx, (uint8_t *)output + after_update);
- if (supp != NULL) {
- ptls_cipher_init(supp->ctx, supp->input);
- memset(supp->output, 0, sizeof(supp->output));
- ptls_cipher_encrypt(supp->ctx, supp->output, supp->output, sizeof(supp->output));
- }
- }
- static size_t ptls_bcrypt_aead_do_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen,
- uint64_t seq, const void *aad, size_t aadlen)
- {
- struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
- ULONG cbResult;
- size_t textLen = inlen - ctx->super.algo->tag_size;
- NTSTATUS ret;
- /* Build the IV for this decryption */
- ptls_aead__build_iv(ctx->super.algo, ctx->bctx.iv, ctx->bctx.iv_static, seq);
- /* TODO: pPaddingInfo must point to BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO structure. */
- BCRYPT_INIT_AUTH_MODE_INFO(ctx->bctx.aead_params);
- /* TODO: find clarity on handling of ivbuf */
- memset(ctx->bctx.tag, 0, sizeof(ctx->super.algo->tag_size));
- ctx->bctx.aead_params.pbNonce = (PUCHAR)&ctx->bctx.iv;
- ctx->bctx.aead_params.cbNonce = (ULONG)ctx->super.algo->iv_size;
- ctx->bctx.aead_params.pbAuthData = (PUCHAR)aad;
- ctx->bctx.aead_params.cbAuthData = (ULONG)aadlen;
- ctx->bctx.aead_params.pbTag = (PUCHAR)(((uint8_t *)input) + textLen);
- ctx->bctx.aead_params.cbTag = (ULONG)(ULONG)ctx->super.algo->tag_size;
- /* Call the decryption */
- ret = BCryptDecrypt(ctx->bctx.hKey, (PUCHAR)input, (ULONG)textLen, (void *)&ctx->bctx.aead_params, NULL, 0, (PUCHAR)output,
- (ULONG)textLen, &cbResult, 0);
- if (BCRYPT_SUCCESS(ret)) {
- return (size_t)cbResult;
- } else {
- return SIZE_MAX;
- }
- }
- static void ptls_bcrypt_aead_get_iv(ptls_aead_context_t *_ctx, void *iv)
- {
- struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
- memcpy(iv, ctx->bctx.iv, ctx->super.algo->iv_size);
- }
- static void ptls_bcrypt_aead_set_iv(ptls_aead_context_t *_ctx, const void *iv)
- {
- struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
- memcpy(ctx->bctx.iv, iv, ctx->super.algo->iv_size);
- }
- static int ptls_bcrypt_aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv,
- wchar_t const *bcrypt_name, wchar_t const *bcrypt_mode, size_t bcrypt_mode_size)
- {
- struct ptls_bcrypt_aead_context_t *ctx = (struct ptls_bcrypt_aead_context_t *)_ctx;
- HANDLE hAlgorithm = NULL;
- NTSTATUS ret;
- memset(&ctx->bctx, 0, sizeof(struct ptls_bcrypt_symmetric_param_t));
- ret = BCryptOpenAlgorithmProvider(&hAlgorithm, bcrypt_name, NULL, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ret = BCryptSetProperty(hAlgorithm, BCRYPT_CHAINING_MODE, (PBYTE)bcrypt_mode, (ULONG)bcrypt_mode_size, 0);
- }
- if (BCRYPT_SUCCESS(ret)) {
- DWORD ko_size = 0;
- ULONG cbResult = 0;
- ret = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&ko_size, (ULONG)sizeof(ko_size), &cbResult, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ctx->bctx.key_object = (uint8_t *)malloc(ko_size);
- if (ctx->bctx.key_object == NULL) {
- ret = STATUS_NO_MEMORY;
- } else {
- ctx->bctx.cbKeyObject = ko_size;
- }
- }
- }
- if (BCRYPT_SUCCESS(ret)) {
- BCRYPT_KEY_LENGTHS_STRUCT atl_st;
- ULONG cbResult = 0;
- ret = BCryptGetProperty(hAlgorithm, BCRYPT_AUTH_TAG_LENGTH, (PUCHAR)&atl_st, (ULONG)sizeof(atl_st), &cbResult, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ctx->bctx.maxTagLength = atl_st.dwMaxLength;
- }
- }
- if (BCRYPT_SUCCESS(ret)) {
- ret = BCryptGenerateSymmetricKey(hAlgorithm, &ctx->bctx.hKey, ctx->bctx.key_object, ctx->bctx.cbKeyObject, (PUCHAR)key,
- (ULONG)ctx->super.algo->key_size, 0);
- }
- if (hAlgorithm != NULL) {
- BCryptCloseAlgorithmProvider(hAlgorithm, 0);
- }
- if (BCRYPT_SUCCESS(ret)) {
- memcpy(ctx->bctx.iv_static, iv, ctx->super.algo->iv_size);
- if (is_enc) {
- ctx->super.dispose_crypto = ptls_bcrypt_aead_dispose_crypto;
- ctx->super.do_get_iv = ptls_bcrypt_aead_get_iv;
- ctx->super.do_set_iv = ptls_bcrypt_aead_set_iv;
- ctx->super.do_decrypt = NULL;
- ctx->super.do_encrypt_init = ptls_bcrypt_aead_do_encrypt_init;
- ctx->super.do_encrypt_update = ptls_bcrypt_aead_do_encrypt_update;
- ctx->super.do_encrypt_final = ptls_bcrypt_aead_do_encrypt_final;
- ctx->super.do_encrypt = ptls_bcrypt_do_encrypt;
- ctx->super.do_encrypt_v = ptls_aead__do_encrypt_v;
- } else {
- ctx->super.dispose_crypto = ptls_bcrypt_aead_dispose_crypto;
- ctx->super.do_decrypt = ptls_bcrypt_aead_do_decrypt;
- ctx->super.do_encrypt_init = NULL;
- ctx->super.do_encrypt_update = NULL;
- ctx->super.do_encrypt_final = NULL;
- ctx->super.do_encrypt = NULL;
- ctx->super.do_encrypt_v = NULL;
- }
- return 0;
- } else {
- ptls_bcrypt_aead_dispose_crypto(_ctx);
- return PTLS_ERROR_LIBRARY;
- }
- }
- static int ptls_bcrypt_aead_setup_crypto_aesgcm(ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv)
- {
- return ptls_bcrypt_aead_setup_crypto(_ctx, is_enc, key, iv, BCRYPT_AES_ALGORITHM, BCRYPT_CHAIN_MODE_GCM,
- sizeof(BCRYPT_CHAIN_MODE_GCM));
- }
- /* Hash algorithms */
- struct st_ptls_bcrypt_hash_param_t {
- wchar_t const *bcrypt_name;
- BCRYPT_HASH_HANDLE hHash;
- PUCHAR pbHashObject;
- ULONG cbHashObject;
- ULONG hash_size;
- int has_error;
- };
- struct st_ptls_bcrypt_hash_context_t {
- ptls_hash_context_t super;
- struct st_ptls_bcrypt_hash_param_t ctx;
- };
- static void ptls_bcrypt_hash_update(struct st_ptls_hash_context_t *_ctx, const void *src, size_t len)
- {
- struct st_ptls_bcrypt_hash_context_t *ctx = (struct st_ptls_bcrypt_hash_context_t *)_ctx;
- NTSTATUS ret = BCryptHashData(ctx->ctx.hHash, (PUCHAR)src, (ULONG)len, 0);
- assert(BCRYPT_SUCCESS(ret));
- if (!BCRYPT_SUCCESS(ret)) {
- ctx->ctx.has_error = 1;
- }
- }
- static struct st_ptls_bcrypt_hash_context_t *ptls_bcrypt_hash_context_free(struct st_ptls_bcrypt_hash_context_t *ctx)
- {
- if (ctx->ctx.pbHashObject != NULL) {
- ptls_clear_memory(ctx->ctx.pbHashObject, ctx->ctx.cbHashObject);
- free(ctx->ctx.pbHashObject);
- }
- ptls_clear_memory(&ctx->ctx, sizeof(ctx->ctx));
- return NULL;
- }
- static ptls_hash_context_t *ptls_bcrypt_hash_clone(struct st_ptls_hash_context_t *_ctx);
- static void ptls_bcrypt_hash_final(struct st_ptls_hash_context_t *_ctx, void *md, ptls_hash_final_mode_t mode)
- {
- if (mode == PTLS_HASH_FINAL_MODE_SNAPSHOT) {
- /* TODO: Copying handle does not change the handle! */
- struct st_ptls_hash_context_t *clone_ctx = ptls_bcrypt_hash_clone(_ctx);
- if (clone_ctx != NULL) {
- ptls_bcrypt_hash_final(clone_ctx, md, PTLS_HASH_FINAL_MODE_FREE);
- } else {
- assert(clone_ctx != NULL);
- }
- } else {
- NTSTATUS ret;
- struct st_ptls_bcrypt_hash_context_t *ctx = (struct st_ptls_bcrypt_hash_context_t *)_ctx;
- if (md != NULL) {
- ret = BCryptFinishHash(ctx->ctx.hHash, md, ctx->ctx.hash_size, 0);
- assert(BCRYPT_SUCCESS(ret));
- if (!BCRYPT_SUCCESS(ret) || ctx->ctx.has_error) {
- memset(md, 0, ctx->ctx.hash_size);
- }
- }
- ret = BCryptDestroyHash(ctx->ctx.hHash);
- assert(BCRYPT_SUCCESS(ret));
- switch (mode) {
- case PTLS_HASH_FINAL_MODE_FREE:
- ctx = ptls_bcrypt_hash_context_free(ctx);
- break;
- case PTLS_HASH_FINAL_MODE_RESET: {
- BCRYPT_ALG_HANDLE hAlgorithm = NULL;
- ret = BCryptOpenAlgorithmProvider(&hAlgorithm, ctx->ctx.bcrypt_name, NULL, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ctx->ctx.hHash = NULL;
- ret = BCryptCreateHash(hAlgorithm, &ctx->ctx.hHash, ctx->ctx.pbHashObject, ctx->ctx.cbHashObject, NULL, 0, 0);
- BCryptCloseAlgorithmProvider(hAlgorithm, 0);
- }
- assert(BCRYPT_SUCCESS(ret));
- if (!BCRYPT_SUCCESS(ret)) {
- ctx->ctx.hHash = NULL;
- }
- break;
- }
- default:
- assert(!"FIXME");
- break;
- }
- }
- }
- static ptls_hash_context_t *ptls_bcrypt_hash_clone(struct st_ptls_hash_context_t *_ctx)
- {
- struct st_ptls_bcrypt_hash_context_t *ctx = (struct st_ptls_bcrypt_hash_context_t *)_ctx;
- struct st_ptls_bcrypt_hash_context_t *clone_ctx;
- if ((clone_ctx = (struct st_ptls_bcrypt_hash_context_t *)malloc(sizeof(*ctx))) != NULL) {
- NTSTATUS ret;
- ptls_clear_memory(&clone_ctx->ctx, sizeof(clone_ctx->ctx));
- clone_ctx->super = (ptls_hash_context_t){ptls_bcrypt_hash_update, ptls_bcrypt_hash_final, ptls_bcrypt_hash_clone};
- clone_ctx->ctx.pbHashObject = (uint8_t *)malloc(ctx->ctx.cbHashObject);
- clone_ctx->ctx.cbHashObject = ctx->ctx.cbHashObject;
- clone_ctx->ctx.bcrypt_name = ctx->ctx.bcrypt_name;
- clone_ctx->ctx.hash_size = ctx->ctx.hash_size;
- clone_ctx->ctx.has_error = ctx->ctx.has_error;
- if (clone_ctx->ctx.pbHashObject == NULL) {
- ret = STATUS_NO_MEMORY;
- } else {
- clone_ctx->ctx.hHash = NULL;
- ptls_clear_memory(&clone_ctx->ctx.pbHashObject, clone_ctx->ctx.cbHashObject);
- ret = BCryptDuplicateHash(ctx->ctx.hHash, &clone_ctx->ctx.hHash, clone_ctx->ctx.pbHashObject,
- clone_ctx->ctx.cbHashObject, 0);
- }
- if (!BCRYPT_SUCCESS(ret)) {
- clone_ctx = ptls_bcrypt_hash_context_free(clone_ctx);
- }
- }
- return (ptls_hash_context_t *)clone_ctx;
- }
- static ptls_hash_context_t *ptls_bcrypt_hash_create(wchar_t const *bcrypt_name, ULONG hash_size)
- {
- BCRYPT_ALG_HANDLE hAlgorithm = NULL;
- NTSTATUS ret;
- struct st_ptls_bcrypt_hash_context_t *ctx;
- if ((ctx = (struct st_ptls_bcrypt_hash_context_t *)malloc(sizeof(*ctx))) != NULL) {
- ctx->super = (ptls_hash_context_t){ptls_bcrypt_hash_update, ptls_bcrypt_hash_final, ptls_bcrypt_hash_clone};
- memset(&ctx->ctx, 0, sizeof(struct st_ptls_bcrypt_hash_param_t));
- ctx->ctx.hash_size = hash_size;
- ctx->ctx.bcrypt_name = bcrypt_name;
- ret = BCryptOpenAlgorithmProvider(&hAlgorithm, bcrypt_name, NULL, 0);
- if (BCRYPT_SUCCESS(ret)) {
- DWORD hb_length = 0;
- ULONG cbResult = 0;
- ret = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hb_length, (ULONG)sizeof(hb_length), &cbResult, 0);
- if (BCRYPT_SUCCESS(ret)) {
- ctx->ctx.pbHashObject = (uint8_t *)malloc(hb_length);
- if (ctx->ctx.pbHashObject == NULL) {
- ret = STATUS_NO_MEMORY;
- } else {
- ctx->ctx.cbHashObject = hb_length;
- }
- }
- }
- if (BCRYPT_SUCCESS(ret)) {
- ret = BCryptCreateHash(hAlgorithm, &ctx->ctx.hHash, ctx->ctx.pbHashObject, ctx->ctx.cbHashObject, NULL, 0, 0);
- }
- if (!BCRYPT_SUCCESS(ret)) {
- ctx = ptls_bcrypt_hash_context_free(ctx);
- }
- }
- if (hAlgorithm != NULL) {
- BCryptCloseAlgorithmProvider(hAlgorithm, 0);
- }
- return (ptls_hash_context_t *)ctx;
- }
- static ptls_hash_context_t *ptls_bcrypt_sha256_create(void)
- {
- return ptls_bcrypt_hash_create(BCRYPT_SHA256_ALGORITHM, PTLS_SHA256_DIGEST_SIZE);
- }
- static ptls_hash_context_t *ptls_bcrypt_sha384_create(void)
- {
- return ptls_bcrypt_hash_create(BCRYPT_SHA384_ALGORITHM, PTLS_SHA384_DIGEST_SIZE);
- }
- /* Declaration of algorithms
- */
- ptls_cipher_algorithm_t ptls_bcrypt_aes128ecb = {"AES128-ECB",
- PTLS_AES128_KEY_SIZE,
- PTLS_AES_BLOCK_SIZE,
- 0 /* iv size */,
- sizeof(struct ptls_bcrypt_symmetric_context_t),
- ptls_bcrypt_cipher_setup_crypto_aes_ecb};
- ptls_cipher_algorithm_t ptls_bcrypt_aes256ecb = {"AES256-ECB",
- PTLS_AES256_KEY_SIZE,
- PTLS_AES_BLOCK_SIZE,
- 0 /* iv size */,
- sizeof(struct ptls_bcrypt_symmetric_context_t),
- ptls_bcrypt_cipher_setup_crypto_aes_ecb};
- ptls_cipher_algorithm_t ptls_bcrypt_aes128ctr = {"AES128-CTR",
- PTLS_AES128_KEY_SIZE,
- PTLS_AES_BLOCK_SIZE,
- 0 /* iv size */,
- sizeof(struct ptls_bcrypt_symmetric_context_t),
- ptls_bcrypt_cipher_setup_crypto_aes_ctr};
- ptls_cipher_algorithm_t ptls_bcrypt_aes256ctr = {"AES256-CTR",
- PTLS_AES256_KEY_SIZE,
- PTLS_AES_BLOCK_SIZE,
- 0 /* iv size */,
- sizeof(struct ptls_bcrypt_symmetric_context_t),
- ptls_bcrypt_cipher_setup_crypto_aes_ctr};
- ptls_aead_algorithm_t ptls_bcrypt_aes128gcm = {"AES128-GCM",
- PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
- PTLS_AESGCM_INTEGRITY_LIMIT,
- &ptls_bcrypt_aes128ecb,
- &ptls_bcrypt_aes128ctr,
- PTLS_AES128_KEY_SIZE,
- PTLS_AESGCM_IV_SIZE,
- PTLS_AESGCM_TAG_SIZE,
- {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE},
- 0,
- 0,
- sizeof(struct ptls_bcrypt_aead_context_t),
- ptls_bcrypt_aead_setup_crypto_aesgcm};
- ptls_aead_algorithm_t ptls_bcrypt_aes256gcm = {"AES256-GCM",
- PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
- PTLS_AESGCM_INTEGRITY_LIMIT,
- &ptls_bcrypt_aes256ecb,
- &ptls_bcrypt_aes256ctr,
- PTLS_AES256_KEY_SIZE,
- PTLS_AESGCM_IV_SIZE,
- PTLS_AESGCM_TAG_SIZE,
- {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE},
- 0,
- 0,
- sizeof(struct ptls_bcrypt_aead_context_t),
- ptls_bcrypt_aead_setup_crypto_aesgcm};
- ptls_hash_algorithm_t ptls_bcrypt_sha256 = {"sha256", PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, ptls_bcrypt_sha256_create,
- PTLS_ZERO_DIGEST_SHA256};
- ptls_hash_algorithm_t ptls_bcrypt_sha384 = {"sha384", PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, ptls_bcrypt_sha384_create,
- PTLS_ZERO_DIGEST_SHA384};
- ptls_cipher_suite_t ptls_bcrypt_aes128gcmsha256 = {.id = PTLS_CIPHER_SUITE_AES_128_GCM_SHA256,
- .name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256,
- .aead = &ptls_bcrypt_aes128gcm,
- .hash = &ptls_bcrypt_sha256};
- ptls_cipher_suite_t ptls_bcrypt_aes256gcmsha384 = {.id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384,
- .name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384,
- .aead = &ptls_bcrypt_aes256gcm,
- .hash = &ptls_bcrypt_sha384};
- #ifdef PRLS_BCRYPT_TODO
- /* TODO: develp these bcrypt functions */
- ptls_key_exchange_algorithm_t ptls_bcrypt_secp256r1 = {PTLS_GROUP_SECP256R1, x9_62_create_key_exchange, secp_key_exchange,
- NID_X9_62_prime256v1};
- #if ptls_bcrypt_HAVE_SECP384R1
- ptls_key_exchange_algorithm_t ptls_bcrypt_secp384r1 = {PTLS_GROUP_SECP384R1, x9_62_create_key_exchange, secp_key_exchange,
- NID_secp384r1};
- #endif
- #if ptls_bcrypt_HAVE_SECP521R1
- ptls_key_exchange_algorithm_t ptls_bcrypt_secp521r1 = {PTLS_GROUP_SECP521R1, x9_62_create_key_exchange, secp_key_exchange,
- NID_secp521r1};
- #endif
- #if ptls_bcrypt_HAVE_X25519
- ptls_key_exchange_algorithm_t ptls_bcrypt_x25519 = {PTLS_GROUP_X25519, evp_keyex_create, evp_keyex_exchange, NID_X25519};
- #endif
- ptls_key_exchange_algorithm_t *ptls_bcrypt_key_exchanges[] = {&ptls_bcrypt_secp256r1, NULL};
- #endif
- #endif /* _WINDOWS */
|