]> wagner.pp.ru Git - openssl-gost/engine.git/blobdiff - gost_grasshopper_cipher.c
Merge branch 'mgm_impl' of https://github.com/gost-engine/engine into mgm_impl
[openssl-gost/engine.git] / gost_grasshopper_cipher.c
index 921a175b943ddc1d05db71ba2e478cef7732ee26..2249161cf62a3fa021a46f8055b56f515f951bd6 100644 (file)
@@ -667,19 +667,6 @@ static void gf128_mul_uint64(uint64_t *result, uint64_t *arg1, uint64_t *arg2)
     BUF_reverse((unsigned char *)result, (unsigned char *)z, 16);
 }
 
-static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
-{
-    int n = 0;
-
-    fprintf(f, "%s", title);
-    for (; n < l; ++n) {
-        if ((n % 16) == 0)
-            fprintf(f, "\n%04x", n);
-        fprintf(f, " %02x", s[n]);
-    }
-    fprintf(f, "\n");
-}
-
 int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                    const unsigned char *in, size_t inl)
 {
@@ -700,6 +687,7 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
 
     grasshopper_w128_t *iv_buffer = (grasshopper_w128_t *) iv;
     grasshopper_w128_t tmp;
+    int encrypting = EVP_CIPHER_CTX_encrypting(ctx);
 
 /* ======== Here we deal with associated data =========== */
     if (out == NULL && c->mgm_state == mgm_associated_data) {
@@ -707,7 +695,6 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
             grasshopper_encrypt_block(&c->c.encrypt_round_keys, c->mgm_iv,
                                       &c->partial_buffer, &c->c.buffer);
             memcpy(c->mgm_iv, &c->partial_buffer, GRASSHOPPER_BLOCK_SIZE);
-            hexdump(stderr, "Tag", c->tag, 16);
         }
 
         if (rest_len != 0) {
@@ -725,15 +712,12 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                           &h, &c->c.buffer);
                 inc_counter(c->mgm_iv->b, 8);
 
-                hexdump(stderr, "Hnext", h.b, 16);
-                hexdump(stderr, "Adata", c->mgm_partial_buffer.b, 16);
                 /* Galois multiply Hi * Ai */
                 gf128_mul_uint64(tmp.q, h.q, c->mgm_partial_buffer.q);
 
                 /* XOR to c->tag */
                 grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
                 grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
-                hexdump(stderr, "Tag", c->tag, 16);
 
                 current_in += GRASSHOPPER_BLOCK_SIZE - rest_len;
                 inl -= (GRASSHOPPER_BLOCK_SIZE - rest_len);
@@ -748,15 +732,12 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                       &h, &c->c.buffer);
             inc_counter(c->mgm_iv->b, 8);
 
-            hexdump(stderr, "Hnext", h.b, 16);
-            hexdump(stderr, "Adata", currentInputBlock->b, 16);
             /* Galois multiply */
             gf128_mul_uint64(tmp.q, h.q, currentInputBlock->q);
 
             /* XOR to c->tag */
             grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
             grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
-            hexdump(stderr, "Tag", c->tag, 16);
 
             current_in += GRASSHOPPER_BLOCK_SIZE;
             inl -= GRASSHOPPER_BLOCK_SIZE;
@@ -785,15 +766,12 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                   &h, &c->c.buffer);
         inc_counter(c->mgm_iv->b, 8);
 
-        hexdump(stderr, "Hnext", h.b, 16);
-        hexdump(stderr, "Padded Adata", c->mgm_partial_buffer.b, 16);
         /* Galois multiply Hi * Ai */
         gf128_mul_uint64(tmp.q, h.q, c->mgm_partial_buffer.q);
 
         /* XOR to c->tag */
         grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
         grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
-        hexdump(stderr, "Tag", c->tag, 16);
 
         /* We finish processing associated data */
         /* Pad rest of mgm_partial_buffer */
@@ -804,7 +782,6 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
         EVP_CIPHER_CTX_set_num(ctx, 0);
         c->mgm_state = mgm_main_data;
 
-        fprintf(stderr, "============= Deal with main data\n");
     }
 
 /* ======== Here we deal with main data =========== */
@@ -813,12 +790,15 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
                                   &c->partial_buffer, &c->c.buffer);
         memcpy(iv, c->partial_buffer.b, GRASSHOPPER_BLOCK_SIZE);
-        //hexdump(stderr, "Y1", iv, 16);
     }
 
     while (rest_len && inl) {
         *(current_out++) = *(current_in++) ^ c->partial_buffer.b[rest_len];
-        c->partial_buffer.b[rest_len] = *(current_out - 1);
+
+        if (encrypting)
+            c->partial_buffer.b[rest_len] = *(current_out - 1);
+        else
+            c->partial_buffer.b[rest_len] = *(current_in - 1);
 
         --inl;
         n++;
@@ -828,40 +808,48 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
             grasshopper_encrypt_block(&c->c.encrypt_round_keys, c->mgm_iv,
                                       &h, &c->c.buffer);
             inc_counter(c->mgm_iv->b, 8);
-            hexdump(stderr, "Hnext", h.b, 16);
-            hexdump(stderr, "Ciphertext", c->partial_buffer.b, 16);
             /* Galois multiply Hi * Ai */
             gf128_mul_uint64(tmp.q, h.q, c->partial_buffer.q);
 
             /* XOR to c->tag */
             grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
             grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
-            hexdump(stderr, "Tag", c->tag, 16);
         }
     }
 
     // full parts
     for (i = 0; i < blocks; i++) {
+        grasshopper_encrypt_block(&c->c.encrypt_round_keys, c->mgm_iv,
+                                  &h, &c->c.buffer);
+        inc_counter(c->mgm_iv->b, 8);
+
         currentInputBlock = (grasshopper_w128_t *) current_in;
         currentOutputBlock = (grasshopper_w128_t *) current_out;
         grasshopper_encrypt_block(&c->c.encrypt_round_keys, iv_buffer,
                                   &c->partial_buffer, &c->c.buffer);
         grasshopper_plus128(&tmp, &c->partial_buffer, currentInputBlock);
-        grasshopper_copy128(currentOutputBlock, &tmp);
-        //hexdump(stderr, "Ciphertext", currentOutputBlock->b, 16);
 
-        grasshopper_encrypt_block(&c->c.encrypt_round_keys, c->mgm_iv,
-                                  &h, &c->c.buffer);
-        inc_counter(c->mgm_iv->b, 8);
-        hexdump(stderr, "Hnext", h.b, 16);
-        hexdump(stderr, "Ciphertext", currentOutputBlock->b, 16);
-        /* Galois multiply Hi * Ai */
-        gf128_mul_uint64(tmp.q, h.q, currentOutputBlock->q);
+        if (encrypting) {
+            grasshopper_copy128(currentOutputBlock, &tmp);
 
-        /* XOR to c->tag */
-        grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
-        grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
-        hexdump(stderr, "Tag", c->tag, 16);
+            /* Galois multiply Hi * Ai */
+            gf128_mul_uint64(tmp.q, h.q, currentOutputBlock->q);
+
+            /* XOR to c->tag */
+            grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
+            grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
+        } else {
+            grasshopper_w128_t tmpin;
+            grasshopper_copy128(&tmpin, currentInputBlock);
+            grasshopper_copy128(currentOutputBlock, &tmp);
+
+            /* Galois multiply Hi * Ai */
+            gf128_mul_uint64(tmp.q, h.q, tmpin.q);
+
+            /* XOR to c->tag */
+            grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
+            grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
+        }
 
         ctr128_inc(iv_buffer->b);
         current_in += GRASSHOPPER_BLOCK_SIZE;
@@ -879,9 +867,16 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
         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];
-            c->partial_buffer.b[i] = currentOutputBlock->b[i];
+            if (encrypting) {
+                currentOutputBlock->b[i] =
+                    c->partial_buffer.b[i] ^ currentInputBlock->b[i];
+                c->partial_buffer.b[i] = currentOutputBlock->b[i];
+            } else {
+                unsigned char in = currentInputBlock->b[i];
+                currentOutputBlock->b[i] =
+                    c->partial_buffer.b[i] ^ currentInputBlock->b[i];
+                c->partial_buffer.b[i] = in;
+            }
         }
         EVP_CIPHER_CTX_set_num(ctx, n + i);
         ctr128_inc(iv_buffer->b);
@@ -898,15 +893,12 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
             grasshopper_encrypt_block(&c->c.encrypt_round_keys, c->mgm_iv, &h,
                                       &c->c.buffer);
             inc_counter(c->mgm_iv->b, 8);
-            hexdump(stderr, "Hnext", h.b, 16);
-            hexdump(stderr, "Padded ciphertext", c->partial_buffer.b, 16);
             /* Galois multiply Hi * Ai */
             gf128_mul_uint64(tmp.q, h.q, c->partial_buffer.q);
 
             /* XOR to c->tag */
             grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
             grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
-            hexdump(stderr, "Tag", c->tag, 16);
         }
 
         a_len = c->ad_length << 3;
@@ -923,21 +915,30 @@ int gost_grasshopper_cipher_do_mgm(EVP_CIPHER_CTX *ctx, unsigned char *out,
         grasshopper_encrypt_block(&c->c.encrypt_round_keys, c->mgm_iv,
                                   &h, &c->c.buffer);
 
-        hexdump(stderr, "Hlast", h.b, 16);
-        hexdump(stderr, "Lenbuf", len_buf, 16);
         /* Galois multiply Hi * Ai */
         gf128_mul_uint64(tmp.q, h.q, (uint64_t *)len_buf);
 
         /* XOR to c->tag */
         grasshopper_plus128(&h, (grasshopper_w128_t *) c->tag, &tmp);
         grasshopper_copy128((grasshopper_w128_t *) c->tag, &h);
-        hexdump(stderr, "Tag", c->tag, 16);
 
         /* Final tag calculation */
-        grasshopper_encrypt_block(&c->c.encrypt_round_keys,
-                                  (grasshopper_w128_t *) c->tag,
-                                  (grasshopper_w128_t *) c->final_tag,
-                                  &c->c.buffer);
+        if (encrypting) {
+            grasshopper_encrypt_block(&c->c.encrypt_round_keys,
+                                      (grasshopper_w128_t *) c->tag,
+                                      (grasshopper_w128_t *) c->final_tag,
+                                      &c->c.buffer);
+            return 1;
+        } else {
+            grasshopper_w128_t decrypt_tag;
+            grasshopper_encrypt_block(&c->c.encrypt_round_keys,
+                                      (grasshopper_w128_t *) c->tag,
+                                      &decrypt_tag, &c->c.buffer);
+            if (memcmp(decrypt_tag.b, c->final_tag, 16)) {
+                return 0;
+            } else
+                return 1;
+        }
     }
 
     return 1;
@@ -1183,54 +1184,47 @@ int gost_grasshopper_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg,
 #ifdef EVP_CTRL_TLS1_2_TLSTREE
     case EVP_CTRL_TLS1_2_TLSTREE:
         {
-            unsigned char newkey[32];
-            int mode = EVP_CIPHER_CTX_mode(ctx);
-            static const unsigned char zeroseq[8];
-            gost_grasshopper_cipher_ctx_ctr *ctr_ctx = NULL;
-            gost_grasshopper_cipher_ctx *c = NULL;
-
-            unsigned char adjusted_iv[16];
-            unsigned char seq[8];
-            int j;
-            if (mode != EVP_CIPH_CTR_MODE)
-                return -1;
-
-            ctr_ctx = (gost_grasshopper_cipher_ctx_ctr *)
-                EVP_CIPHER_CTX_get_cipher_data(ctx);
-            c = &(ctr_ctx->c);
-
-            memcpy(seq, ptr, 8);
-            if (EVP_CIPHER_CTX_encrypting(ctx)) {
-                /*
-                 * OpenSSL increments seq after mac calculation.
-                 * As we have Mac-Then-Encrypt, we need decrement it here on encryption
-                 * to derive the key correctly.
-                 * */
-                if (memcmp(seq, zeroseq, 8) != 0) {
-                    for (j = 7; j >= 0; j--) {
-                        if (seq[j] != 0) {
-                            seq[j]--;
-                            break;
-                        } else
-                            seq[j] = 0xFF;
-                    }
-                }
+          unsigned char newkey[32];
+          int mode = EVP_CIPHER_CTX_mode(ctx);
+          static const unsigned char zeroseq[8];
+          gost_grasshopper_cipher_ctx_ctr *ctr_ctx = NULL;
+          gost_grasshopper_cipher_ctx *c = NULL;
+
+          unsigned char adjusted_iv[16];
+          unsigned char seq[8];
+          int j, carry;
+          if (mode != EVP_CIPH_CTR_MODE)
+            return -1;
+
+          ctr_ctx = (gost_grasshopper_cipher_ctx_ctr *)
+            EVP_CIPHER_CTX_get_cipher_data(ctx);
+          c = &(ctr_ctx->c);
+
+          memcpy(seq, ptr, 8);
+          if (EVP_CIPHER_CTX_encrypting(ctx)) {
+            /*
+             * OpenSSL increments seq after mac calculation.
+             * As we have Mac-Then-Encrypt, we need decrement it here on encryption
+             * to derive the key correctly.
+             * */
+            if (memcmp(seq, zeroseq, 8) != 0)
+            {
+              for(j=7; j>=0; j--)
+              {
+                if (seq[j] != 0) {seq[j]--; break;}
+                else seq[j]  = 0xFF;
+              }
             }
-            if (gost_tlstree(NID_grasshopper_cbc, c->master_key.k.b, newkey,
-                             (const unsigned char *)seq) > 0) {
-                memset(adjusted_iv, 0, 16);
-                memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 8);
-                for (j = 7; j >= 0; j--) {
-                    int adj_byte, carry = 0;
-                    adj_byte = adjusted_iv[j] + seq[j] + carry;
-                    carry = (adj_byte > 255) ? 1 : 0;
-                    adjusted_iv[j] = adj_byte & 0xFF;
-                }
-                EVP_CIPHER_CTX_set_num(ctx, 0);
-                memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), adjusted_iv, 16);
-
-                gost_grasshopper_cipher_key(c, newkey);
-                return 1;
+          }
+          if (gost_tlstree(NID_grasshopper_cbc, c->master_key.k.b, newkey,
+                (const unsigned char *)seq) > 0) {
+            memset(adjusted_iv, 0, 16);
+            memcpy(adjusted_iv, EVP_CIPHER_CTX_original_iv(ctx), 8);
+            for(j=7,carry=0; j>=0; j--)
+            {
+              int adj_byte = adjusted_iv[j]+seq[j]+carry;
+              carry = (adj_byte > 255) ? 1 : 0;
+              adjusted_iv[j] = adj_byte & 0xFF;
             }
         }
         return -1;