From c99092ce70c10a4786bed1094ba044ae0026759f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 4 Apr 2020 16:56:14 +0300 Subject: [PATCH 38/87] gost: add support for GOST 34.12 (Magma, Kuznyechik) encryption params Add encoding and decoding support for GOST 34.12 encryption params. Signed-off-by: Dmitry Baryshkov --- src/lib/libcrypto/gost/gost.h | 3 + src/lib/libcrypto/gost/gost_asn1.c | 130 +++++++++++++++++++++++++++++ src/lib/libcrypto/gost/gost_asn1.h | 10 +++ 3 files changed, 143 insertions(+) diff --git a/src/lib/libcrypto/gost/gost.h b/src/lib/libcrypto/gost/gost.h index 4fef765ce..421ca29f3 100644 --- a/src/lib/libcrypto/gost/gost.h +++ b/src/lib/libcrypto/gost/gost.h @@ -121,6 +121,9 @@ GOST_CIPHER_PARAMS *d2i_GOST_CIPHER_PARAMS(GOST_CIPHER_PARAMS **a, const unsigne int i2d_GOST_CIPHER_PARAMS(GOST_CIPHER_PARAMS *a, unsigned char **out); extern const ASN1_ITEM GOST_CIPHER_PARAMS_it; +int gost3412_ctr_acpkm_set_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params, unsigned int il); +int gost3412_ctr_acpkm_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params, unsigned int il); + #define GOST2814789IMIT_LENGTH 4 #define GOST2814789IMIT_CBLOCK 8 #define GOST2814789IMIT_LONG unsigned int diff --git a/src/lib/libcrypto/gost/gost_asn1.c b/src/lib/libcrypto/gost/gost_asn1.c index bfd81faa1..14e46afab 100644 --- a/src/lib/libcrypto/gost/gost_asn1.c +++ b/src/lib/libcrypto/gost/gost_asn1.c @@ -10,9 +10,12 @@ #include #ifndef OPENSSL_NO_GOST +#include + #include #include #include +#include #include "gost_locl.h" #include "gost_asn1.h" @@ -344,4 +347,131 @@ GOST_CIPHER_PARAMS_free(GOST_CIPHER_PARAMS *a) ASN1_item_free((ASN1_VALUE *)a, &GOST_CIPHER_PARAMS_it); } +static const ASN1_TEMPLATE GOST3412_ENCRYPTION_PARAMS_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(GOST3412_ENCRYPTION_PARAMS, iv), + .field_name = "iv", + .item = &ASN1_OCTET_STRING_it, + }, +}; + +const ASN1_ITEM GOST3412_ENCRYPTION_PARAMS_it = { + .itype = ASN1_ITYPE_NDEF_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = GOST3412_ENCRYPTION_PARAMS_seq_tt, + .tcount = sizeof(GOST3412_ENCRYPTION_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(GOST3412_ENCRYPTION_PARAMS), + .sname = "GOST3412_ENCRYPTION_PARAMS", +}; + +GOST3412_ENCRYPTION_PARAMS * +d2i_GOST3412_ENCRYPTION_PARAMS(GOST3412_ENCRYPTION_PARAMS **a, const unsigned char **in, long len) +{ + return (GOST3412_ENCRYPTION_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &GOST3412_ENCRYPTION_PARAMS_it); +} + +int +i2d_GOST3412_ENCRYPTION_PARAMS(GOST3412_ENCRYPTION_PARAMS *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST3412_ENCRYPTION_PARAMS_it); +} + +GOST3412_ENCRYPTION_PARAMS * +GOST3412_ENCRYPTION_PARAMS_new(void) +{ + return (GOST3412_ENCRYPTION_PARAMS *)ASN1_item_new(&GOST3412_ENCRYPTION_PARAMS_it); +} + +void +GOST3412_ENCRYPTION_PARAMS_free(GOST3412_ENCRYPTION_PARAMS *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &GOST3412_ENCRYPTION_PARAMS_it); +} + +int +gost3412_ctr_acpkm_set_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params, unsigned int il) +{ + int len = 0; + unsigned char *buf = NULL; + unsigned char *p = NULL; + GOST3412_ENCRYPTION_PARAMS *gcp = NULL; + ASN1_OCTET_STRING *os = NULL; + + if (params == NULL) + return 0; + + gcp = GOST3412_ENCRYPTION_PARAMS_new(); + if (ASN1_OCTET_STRING_set(gcp->iv, NULL, il + 8) == 0) { + GOST3412_ENCRYPTION_PARAMS_free(gcp); + GOSTerror(ERR_R_ASN1_LIB); + return 0; + } + + memcpy(gcp->iv->data, ctx->iv, il); + memcpy(gcp->iv->data + il, ctx->oiv, 8); + + len = i2d_GOST3412_ENCRYPTION_PARAMS(gcp, NULL); + p = buf = malloc(len); + if (buf == NULL) { + GOST3412_ENCRYPTION_PARAMS_free(gcp); + GOSTerror(ERR_R_MALLOC_FAILURE); + return 0; + } + i2d_GOST3412_ENCRYPTION_PARAMS(gcp, &p); + GOST3412_ENCRYPTION_PARAMS_free(gcp); + + os = ASN1_OCTET_STRING_new(); + if (os == NULL) { + free(buf); + GOSTerror(ERR_R_MALLOC_FAILURE); + return 0; + } + if (ASN1_OCTET_STRING_set(os, buf, len) == 0) { + ASN1_OCTET_STRING_free(os); + free(buf); + GOSTerror(ERR_R_ASN1_LIB); + return 0; + } + free(buf); + + ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os); + + return 1; +} + +int +gost3412_ctr_acpkm_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params, unsigned int il) +{ + int len; + GOST3412_ENCRYPTION_PARAMS *gcp = NULL; + unsigned char *p; + + if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) + return -1; + + p = params->value.sequence->data; + + gcp = d2i_GOST3412_ENCRYPTION_PARAMS(NULL, (const unsigned char **)&p, + params->value.sequence->length); + + len = gcp->iv->length; + if (len != il + 8 || len > sizeof(ctx->iv)) { + GOST3412_ENCRYPTION_PARAMS_free(gcp); + GOSTerror(GOST_R_INVALID_IV_LENGTH); + return -1; + } + + memcpy(ctx->iv, gcp->iv->data, il); + memset(ctx->iv + il, 0, EVP_MAX_IV_LENGTH - il); + memcpy(ctx->oiv, gcp->iv->data + il, 8); + + GOST3412_ENCRYPTION_PARAMS_free(gcp); + + return 1; +} + #endif diff --git a/src/lib/libcrypto/gost/gost_asn1.h b/src/lib/libcrypto/gost/gost_asn1.h index cdbda7b98..5af16e00e 100644 --- a/src/lib/libcrypto/gost/gost_asn1.h +++ b/src/lib/libcrypto/gost/gost_asn1.h @@ -113,6 +113,16 @@ GOST_KEY_PARAMS *d2i_GOST_KEY_PARAMS(GOST_KEY_PARAMS **a, const unsigned char ** int i2d_GOST_KEY_PARAMS(GOST_KEY_PARAMS *a, unsigned char **out); extern const ASN1_ITEM GOST_KEY_PARAMS_it; +typedef struct { + ASN1_OCTET_STRING *iv; +} GOST3412_ENCRYPTION_PARAMS; + +GOST3412_ENCRYPTION_PARAMS *GOST3412_ENCRYPTION_PARAMS_new(void); +void GOST3412_ENCRYPTION_PARAMS_free(GOST3412_ENCRYPTION_PARAMS *a); +GOST3412_ENCRYPTION_PARAMS *d2i_GOST3412_ENCRYPTION_PARAMS(GOST3412_ENCRYPTION_PARAMS **a, const unsigned char **in, long len); +int i2d_GOST3412_ENCRYPTION_PARAMS(GOST3412_ENCRYPTION_PARAMS *a, unsigned char **out); +extern const ASN1_ITEM GOST3412_ENCRYPTION_PARAMS_it; + __END_HIDDEN_DECLS #endif -- 2.17.1