From bbcf0a8fdd0a84563e65d9e9aea3b8e6254e7343 Mon Sep 17 00:00:00 2001 From: andyk555 <36532623+andyk555@users.noreply.github.com> Date: Fri, 16 Feb 2018 22:16:15 +0300 Subject: Update gost_grasshopper_cipher.c (cherry picked from commit 6be1ab0065c7b2d24d1835f8b1bcb7cd28fb76e5) --- gost_grasshopper_cipher.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/gost_grasshopper_cipher.c b/gost_grasshopper_cipher.c index 23ba575..c797fe1 100644 --- a/gost_grasshopper_cipher.c +++ b/gost_grasshopper_cipher.c @@ -138,8 +138,6 @@ static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ctr(gost_grasshop grasshopper_zero128(&ctx->iv_buffer); grasshopper_zero128(&ctx->partial_buffer); - - ctx->counter = 0; } int gost_grasshopper_cipher_init(EVP_CIPHER_CTX* ctx, const unsigned char* key, @@ -214,8 +212,6 @@ GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX* ctx, con grasshopper_zero128(&c->iv_buffer); grasshopper_zero128(&c->partial_buffer); - c->counter = 0; - return gost_grasshopper_cipher_init(ctx, key, iv, enc); } @@ -283,6 +279,21 @@ int gost_grasshopper_cipher_do_cbc(EVP_CIPHER_CTX* ctx, unsigned char* out, return 1; } +/* increment counter (128-bit int) by 1 */ +static void ctr128_inc(unsigned char *counter) +{ + unsigned int n = 16; + unsigned char c; + + do { + --n; + c = counter[n]; + ++c; + counter[n] = c; + if (c) return; + } while (n); +} + int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, const unsigned char* in, size_t inl) { gost_grasshopper_cipher_ctx_ctr* c = (gost_grasshopper_cipher_ctx_ctr*) EVP_CIPHER_CTX_get_cipher_data(ctx); @@ -301,10 +312,9 @@ int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, for (i = 0; i < blocks; i++) { currentInputBlock = (grasshopper_w128_t*) current_in; currentOutputBlock = (grasshopper_w128_t*) current_out; - memcpy(c->iv_buffer.b + 8, &c->counter, 8); grasshopper_encrypt_block(&c->c.encrypt_round_keys, &c->iv_buffer, currentOutputBlock, &c->c.buffer); grasshopper_append128(currentOutputBlock, currentInputBlock); - c->counter += 1; + ctr128_inc(c->iv_buffer.b); current_in += GRASSHOPPER_BLOCK_SIZE; current_out += GRASSHOPPER_BLOCK_SIZE; } @@ -314,12 +324,11 @@ int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, if (lasted > 0) { currentInputBlock = (grasshopper_w128_t*) current_in; currentOutputBlock = (grasshopper_w128_t*) current_out; - memcpy(c->iv_buffer.b + 8, &c->counter, 8); grasshopper_encrypt_block(&c->c.encrypt_round_keys, &c->iv_buffer, &c->partial_buffer, &c->c.buffer); for (i = 0; i < lasted; i++) { currentOutputBlock->b[i] = c->partial_buffer.b[i] ^ currentInputBlock->b[i]; } - c->counter += 1; + ctr128_inc(c->iv_buffer.b); } return 1; -- cgit v1.1 From fb4e4e11e21242b10d4c24ffcfa406ed335191fa Mon Sep 17 00:00:00 2001 From: Vitaly Chikunov Date: Sun, 22 Jul 2018 10:34:03 +0300 Subject: grasshopper: Fix streaming for CTR mode Previously CTR did not continue unfinished block on the next cipher iteration. (cherry picked from commit cf2ab51a449ce3d92163217c8078f0f625aac7ae) --- gost_grasshopper_cipher.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gost_grasshopper_cipher.c b/gost_grasshopper_cipher.c index c797fe1..2cdf57e 100644 --- a/gost_grasshopper_cipher.c +++ b/gost_grasshopper_cipher.c @@ -208,6 +208,7 @@ GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX* ctx, con gost_grasshopper_cipher_ctx_ctr* c = EVP_CIPHER_CTX_get_cipher_data(ctx); c->c.type = GRASSHOPPER_CIPHER_CTR; + EVP_CIPHER_CTX_set_num(ctx, 0); grasshopper_zero128(&c->iv_buffer); grasshopper_zero128(&c->partial_buffer); @@ -300,12 +301,20 @@ int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, unsigned char* iv = EVP_CIPHER_CTX_iv_noconst(ctx); const unsigned char* current_in = in; unsigned char* current_out = out; - size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE; grasshopper_w128_t* currentInputBlock; grasshopper_w128_t* currentOutputBlock; + unsigned int n = EVP_CIPHER_CTX_num(ctx); size_t lasted; size_t i; + while (n && inl) { + *(current_out++) = *(current_in++) ^ c->partial_buffer.b[n]; + --inl; + n = (n + 1) % GRASSHOPPER_BLOCK_SIZE; + } + EVP_CIPHER_CTX_set_num(ctx, n); + size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE; + memcpy(&c->iv_buffer, iv, 8); // full parts @@ -328,6 +337,7 @@ int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, for (i = 0; i < lasted; i++) { currentOutputBlock->b[i] = c->partial_buffer.b[i] ^ currentInputBlock->b[i]; } + EVP_CIPHER_CTX_set_num(ctx, i); ctr128_inc(c->iv_buffer.b); } -- cgit v1.1 From 6fc723c572a2df36cad8c523a66702c39f7aea5c Mon Sep 17 00:00:00 2001 From: Vitaly Chikunov Date: Mon, 23 Jul 2018 03:35:13 +0300 Subject: grasshopper: Fix OFB implementation. Previous implementation was not OFB at all, and fail tests. Note: This implementation is for fixed width 128-bit IV which makes shift regiser redundant. (cherry picked from commit 1e15537d7583cdd5a4b003b5efb92f0b6e1fdcc6) --- gost_grasshopper_cipher.c | 45 ++++----------------------------------------- gost_grasshopper_cipher.h | 2 -- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/gost_grasshopper_cipher.c b/gost_grasshopper_cipher.c index 2cdf57e..8ee8481 100644 --- a/gost_grasshopper_cipher.c +++ b/gost_grasshopper_cipher.c @@ -344,51 +344,14 @@ int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, return 1; } +/* + * Fixed 128-bit IV implementation make shift regiser redundant. + */ static void gost_grasshopper_cnt_next(gost_grasshopper_cipher_ctx_ofb* ctx, grasshopper_w128_t* iv, grasshopper_w128_t* buf) { memcpy(&ctx->buffer1, iv, 16); - ctx->g = ctx->buffer1.b[0] | (ctx->buffer1.b[1] << 8) | (ctx->buffer1.b[2] << 16) | - ((uint32_t) ctx->buffer1.b[3] << 24); - ctx->g += 0x01010101; - ctx->buffer1.b[0] = (unsigned char) (ctx->g & 0xff); - ctx->buffer1.b[1] = (unsigned char) ((ctx->g >> 8) & 0xff); - ctx->buffer1.b[2] = (unsigned char) ((ctx->g >> 16) & 0xff); - ctx->buffer1.b[3] = (unsigned char) ((ctx->g >> 24) & 0xff); - ctx->g = ctx->buffer1.b[4] | (ctx->buffer1.b[5] << 8) | (ctx->buffer1.b[6] << 16) | - ((uint32_t) ctx->buffer1.b[7] << 24); - ctx->go = ctx->g; - ctx->g += 0x01010104; - if (ctx->go > ctx->g) { /* overflow */ - ctx->g++; - } - ctx->buffer1.b[4] = (unsigned char) (ctx->g & 0xff); - ctx->buffer1.b[5] = (unsigned char) ((ctx->g >> 8) & 0xff); - ctx->buffer1.b[6] = (unsigned char) ((ctx->g >> 16) & 0xff); - ctx->buffer1.b[7] = (unsigned char) ((ctx->g >> 24) & 0xff); - ctx->g = ctx->buffer1.b[8] | (ctx->buffer1.b[9] << 8) | (ctx->buffer1.b[10] << 16) | - ((uint32_t) ctx->buffer1.b[11] << 24); - ctx->go = ctx->g; - ctx->g += 0x01010107; - if (ctx->go > ctx->g) { /* overflow */ - ctx->g++; - } - ctx->buffer1.b[8] = (unsigned char) (ctx->g & 0xff); - ctx->buffer1.b[9] = (unsigned char) ((ctx->g >> 8) & 0xff); - ctx->buffer1.b[10] = (unsigned char) ((ctx->g >> 16) & 0xff); - ctx->buffer1.b[11] = (unsigned char) ((ctx->g >> 24) & 0xff); - ctx->g = ctx->buffer1.b[12] | (ctx->buffer1.b[13] << 8) | (ctx->buffer1.b[14] << 16) | - ((uint32_t) ctx->buffer1.b[15] << 24); - ctx->go = ctx->g; - ctx->g += 0x01010110; - if (ctx->go > ctx->g) { /* overflow */ - ctx->g++; - } - ctx->buffer1.b[12] = (unsigned char) (ctx->g & 0xff); - ctx->buffer1.b[13] = (unsigned char) ((ctx->g >> 8) & 0xff); - ctx->buffer1.b[14] = (unsigned char) ((ctx->g >> 16) & 0xff); - ctx->buffer1.b[15] = (unsigned char) ((ctx->g >> 24) & 0xff); - memcpy(iv, &ctx->buffer1, 16); grasshopper_encrypt_block(&ctx->c.encrypt_round_keys, &ctx->buffer1, buf, &ctx->c.buffer); + memcpy(iv, buf, 16); } int gost_grasshopper_cipher_do_ofb(EVP_CIPHER_CTX* ctx, unsigned char* out, diff --git a/gost_grasshopper_cipher.h b/gost_grasshopper_cipher.h index 7f775a2..34bf8cc 100644 --- a/gost_grasshopper_cipher.h +++ b/gost_grasshopper_cipher.h @@ -27,8 +27,6 @@ typedef struct { typedef struct { gost_grasshopper_cipher_ctx c; grasshopper_w128_t buffer1; - uint32_t g; - uint32_t go; } gost_grasshopper_cipher_ctx_ofb; typedef struct { -- cgit v1.1 From ed191fe63d7ac2c4906d828eb4ea673f3004c847 Mon Sep 17 00:00:00 2001 From: Gleb Fotengauer-Malinovskiy Date: Thu, 19 Jul 2018 20:11:37 +0300 Subject: Fix grasshopper-ctr reinitialization Also, document why CTR IV size is now set to 16, so user is noted to set IV appropriately to full extent (including counter). Basically, it's for openssh (and alike) to make it copy IV from privilege separated process. (cherry picked from commit 74d13288e0a664f2615014d441087792eabc5cfa) --- gost_grasshopper_cipher.c | 17 +++++++++-------- gost_grasshopper_cipher.h | 1 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gost_grasshopper_cipher.c b/gost_grasshopper_cipher.c index 8ee8481..92be991 100644 --- a/gost_grasshopper_cipher.c +++ b/gost_grasshopper_cipher.c @@ -97,7 +97,10 @@ static struct GRASSHOPPER_CIPHER_PARAMS gost_cipher_params[5] = { gost_grasshopper_cipher_destroy_ctr, 1, sizeof(gost_grasshopper_cipher_ctx_ctr), - 8, + /* IV size is set to match full block, to make it responsibility of + * user to assign correct values (IV || 0), and to make naive context + * copy possible (for software such as openssh) */ + 16, false }, }; @@ -136,7 +139,6 @@ static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ofb(gost_grasshop static GRASSHOPPER_INLINE void gost_grasshopper_cipher_destroy_ctr(gost_grasshopper_cipher_ctx* c) { gost_grasshopper_cipher_ctx_ctr* ctx = (gost_grasshopper_cipher_ctx_ctr*) c; - grasshopper_zero128(&ctx->iv_buffer); grasshopper_zero128(&ctx->partial_buffer); } @@ -210,7 +212,6 @@ GRASSHOPPER_INLINE int gost_grasshopper_cipher_init_ctr(EVP_CIPHER_CTX* ctx, con c->c.type = GRASSHOPPER_CIPHER_CTR; EVP_CIPHER_CTX_set_num(ctx, 0); - grasshopper_zero128(&c->iv_buffer); grasshopper_zero128(&c->partial_buffer); return gost_grasshopper_cipher_init(ctx, key, iv, enc); @@ -315,15 +316,15 @@ int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, EVP_CIPHER_CTX_set_num(ctx, n); size_t blocks = inl / GRASSHOPPER_BLOCK_SIZE; - memcpy(&c->iv_buffer, iv, 8); + grasshopper_w128_t* iv_buffer = (grasshopper_w128_t*) iv; // full parts for (i = 0; i < blocks; i++) { currentInputBlock = (grasshopper_w128_t*) current_in; currentOutputBlock = (grasshopper_w128_t*) current_out; - grasshopper_encrypt_block(&c->c.encrypt_round_keys, &c->iv_buffer, currentOutputBlock, &c->c.buffer); + grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer, currentOutputBlock, &c->c.buffer); grasshopper_append128(currentOutputBlock, currentInputBlock); - ctr128_inc(c->iv_buffer.b); + ctr128_inc(iv_buffer->b); current_in += GRASSHOPPER_BLOCK_SIZE; current_out += GRASSHOPPER_BLOCK_SIZE; } @@ -333,12 +334,12 @@ int gost_grasshopper_cipher_do_ctr(EVP_CIPHER_CTX* ctx, unsigned char* out, if (lasted > 0) { currentInputBlock = (grasshopper_w128_t*) current_in; currentOutputBlock = (grasshopper_w128_t*) current_out; - grasshopper_encrypt_block(&c->c.encrypt_round_keys, &c->iv_buffer, &c->partial_buffer, &c->c.buffer); + grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer, &c->partial_buffer, &c->c.buffer); for (i = 0; i < lasted; i++) { currentOutputBlock->b[i] = c->partial_buffer.b[i] ^ currentInputBlock->b[i]; } EVP_CIPHER_CTX_set_num(ctx, i); - ctr128_inc(c->iv_buffer.b); + ctr128_inc(iv_buffer->b); } return 1; diff --git a/gost_grasshopper_cipher.h b/gost_grasshopper_cipher.h index 34bf8cc..3a8531f 100644 --- a/gost_grasshopper_cipher.h +++ b/gost_grasshopper_cipher.h @@ -31,7 +31,6 @@ typedef struct { typedef struct { gost_grasshopper_cipher_ctx c; - grasshopper_w128_t iv_buffer; grasshopper_w128_t partial_buffer; uint64_t counter; } gost_grasshopper_cipher_ctx_ctr; -- cgit v1.1