From 585ab77911db9b4ed588cd20cc03abec20390501 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 20 Mar 2020 01:11:59 +0300 Subject: [PATCH 33/87] gost: add support for magma cipher GOST R 34.12-2015 defines Magma cipher (a variant of GOST 28147-89 with fixed S-BOX and endianness change), see draft-dolmatov-magma. Sponsored by ROSA Linux Signed-off-by: Dmitry Baryshkov --- src/lib/libcrypto/Symbols.list | 5 + src/lib/libcrypto/evp/c_all.c | 5 + src/lib/libcrypto/evp/e_magma.c | 123 +++++++++++++++++++++ src/lib/libcrypto/evp/evp.h | 5 + src/lib/libcrypto/gost/gost.h | 29 +++++ src/lib/libcrypto/gost/gost2814789.c | 71 ++++++++++++ src/lib/libcrypto/gost/gost89_params.c | 24 ++++ src/lib/libcrypto/gost/gost_locl.h | 11 ++ src/lib/libcrypto/objects/obj_mac.num | 9 ++ src/lib/libcrypto/objects/objects.txt | 14 +++ src/regress/lib/libcrypto/evp/evptests.txt | 18 +++ 11 files changed, 314 insertions(+) create mode 100644 src/lib/libcrypto/evp/e_magma.c diff --git a/src/lib/libcrypto/Symbols.list b/src/lib/libcrypto/Symbols.list index 662eb4dc2..6102af2f8 100644 --- a/src/lib/libcrypto/Symbols.list +++ b/src/lib/libcrypto/Symbols.list @@ -1725,6 +1725,11 @@ EVP_idea_cfb EVP_idea_cfb64 EVP_idea_ecb EVP_idea_ofb +EVP_magma_cbc +EVP_magma_cfb64 +EVP_magma_ctr +EVP_magma_ecb +EVP_magma_ofb EVP_md4 EVP_md5 EVP_md5_sha1 diff --git a/src/lib/libcrypto/evp/c_all.c b/src/lib/libcrypto/evp/c_all.c index 9e9d39d5a..59342beb7 100644 --- a/src/lib/libcrypto/evp/c_all.c +++ b/src/lib/libcrypto/evp/c_all.c @@ -229,6 +229,11 @@ OpenSSL_add_all_ciphers_internal(void) EVP_add_cipher(EVP_gost2814789_ecb()); EVP_add_cipher(EVP_gost2814789_cfb64()); EVP_add_cipher(EVP_gost2814789_cnt()); + EVP_add_cipher(EVP_magma_ecb()); + EVP_add_cipher(EVP_magma_cbc()); + EVP_add_cipher(EVP_magma_cfb64()); + EVP_add_cipher(EVP_magma_ofb()); + EVP_add_cipher(EVP_magma_ctr()); #endif #ifndef OPENSSL_NO_SM4 diff --git a/src/lib/libcrypto/evp/e_magma.c b/src/lib/libcrypto/evp/e_magma.c new file mode 100644 index 000000000..712f79278 --- /dev/null +++ b/src/lib/libcrypto/evp/e_magma.c @@ -0,0 +1,123 @@ +/* $OpenBSD: e_magma.c,v 1.4 2017/01/29 17:49:23 beck Exp $ */ +/* + * Copyright (c) 2020 Dmitry Baryshkov + * + * Sponsored by ROSA Linux + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include + +#include + +#ifndef OPENSSL_NO_GOST +#include +#include +#include +#include +#include "evp_locl.h" + +typedef struct { + MAGMA_KEY ks; +} EVP_MAGMA_CTX; + +static int +magma_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_MAGMA_CTX *c = ctx->cipher_data; + + Magma_set_key(&c->ks, key); + + return 1; +} + +static int +magma_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +{ + switch (type) { + case EVP_CTRL_PBE_PRF_NID: + if (ptr != NULL) { + *((int *)ptr) = NID_id_tc26_hmac_gost_3411_12_256; + return 1; + } else { + return 0; + } + default: + return -1; + } +} + +static void +Magma_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len, + const MAGMA_KEY *key, unsigned char *ivec, const int enc) +{ + if (enc) + CRYPTO_cbc64_encrypt(in, out, len, key, ivec, + (block64_f)Magma_encrypt); + else + CRYPTO_cbc64_decrypt(in, out, len, key, ivec, + (block64_f)Magma_decrypt); +} + +static void +Magma_cfb64_encrypt(const unsigned char *in, unsigned char *out, size_t length, + const MAGMA_KEY *key, unsigned char *ivec, int *num, const int enc) +{ + CRYPTO_cfb64_encrypt(in, out, length, key, ivec, num, enc, + (block64_f)Magma_encrypt); +} + +static void +Magma_ecb_encrypt(const unsigned char *in, unsigned char *out, const MAGMA_KEY *key, + const int enc) +{ + if (enc) + Magma_encrypt(in, out, key); + else + Magma_decrypt(in, out, key); +} + +static void +Magma_ofb64_encrypt(const unsigned char *in, unsigned char *out, size_t length, + const MAGMA_KEY *key, unsigned char *ivec, int *num) +{ + CRYPTO_ofb64_encrypt(in, out, length, key, ivec, num, + (block64_f)Magma_encrypt); +} + +static int +magma_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, + size_t len) +{ + EVP_MAGMA_CTX *key = EVP_C_DATA(EVP_MAGMA_CTX, ctx); + + CRYPTO_ctr64_encrypt(in, out, len, &key->ks, ctx->iv, ctx->buf, + &ctx->num, (block64_f)Magma_encrypt); + return 1; +} + +IMPLEMENT_BLOCK_CIPHER(magma, ks, Magma, EVP_MAGMA_CTX, + NID_magma, 8, 32, 8, 64, 0, magma_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + magma_ctl) + +BLOCK_CIPHER_def1(magma, ctr, ctr, CTR, EVP_MAGMA_CTX, + NID_magma, 1, 32, 4, 0, + magma_init_key, NULL, + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + magma_ctl) + +#endif diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h index f1fe8a1e3..63d4e41a7 100644 --- a/src/lib/libcrypto/evp/evp.h +++ b/src/lib/libcrypto/evp/evp.h @@ -846,6 +846,11 @@ const EVP_CIPHER *EVP_chacha20(void); const EVP_CIPHER *EVP_gost2814789_ecb(void); const EVP_CIPHER *EVP_gost2814789_cfb64(void); const EVP_CIPHER *EVP_gost2814789_cnt(void); +const EVP_CIPHER *EVP_magma_ecb(void); +const EVP_CIPHER *EVP_magma_cbc(void); +const EVP_CIPHER *EVP_magma_cfb64(void); +const EVP_CIPHER *EVP_magma_ofb(void); +const EVP_CIPHER *EVP_magma_ctr(void); #endif #ifndef OPENSSL_NO_SM4 diff --git a/src/lib/libcrypto/gost/gost.h b/src/lib/libcrypto/gost/gost.h index a9ed5a1c5..d584a55f3 100644 --- a/src/lib/libcrypto/gost/gost.h +++ b/src/lib/libcrypto/gost/gost.h @@ -83,6 +83,35 @@ void Gost2814789_cnt_encrypt(const unsigned char *in, unsigned char *out, size_t length, GOST2814789_KEY *key, unsigned char *ivec, unsigned char *cnt_buf, int *num); +#define MAGMA_KEY GOST2814789_KEY + +void Magma_set_key(MAGMA_KEY *key, const unsigned char *userKey); + +void Magma_encrypt(const unsigned char *in, unsigned char *out, + const MAGMA_KEY *key); +void Magma_decrypt(const unsigned char *in, unsigned char *out, + const MAGMA_KEY *key); + +#define KUZNYECHIK_KEY_SIZE 32 +#define KUZNYECHIK_SUBKEYS_SIZE (16 * 10) +#define KUZNYECHIK_BLOCK_SIZE 16 + +typedef struct kuznyechik_key_st +{ + unsigned char key[KUZNYECHIK_SUBKEYS_SIZE]; + unsigned int count; + unsigned int key_meshing; +} KUZNYECHIK_KEY; + +void Kuznyechik_set_key(KUZNYECHIK_KEY *key, const unsigned char *userKey, int enc); + +void Kuznyechik_encrypt(const unsigned char *in, unsigned char *out, + const KUZNYECHIK_KEY *key); +void Kuznyechik_decrypt(const unsigned char *in, unsigned char *out, + const KUZNYECHIK_KEY *key); +void Kuznyechik_acpkm_encrypt(const unsigned char *in, unsigned char *out, + KUZNYECHIK_KEY *key); + typedef struct { ASN1_OCTET_STRING *iv; ASN1_OBJECT *enc_param_set; diff --git a/src/lib/libcrypto/gost/gost2814789.c b/src/lib/libcrypto/gost/gost2814789.c index e5c7f6a2b..c9deee695 100644 --- a/src/lib/libcrypto/gost/gost2814789.c +++ b/src/lib/libcrypto/gost/gost2814789.c @@ -1,8 +1,11 @@ /* $OpenBSD: gost2814789.c,v 1.5 2015/09/10 15:56:25 jsing Exp $ */ /* + * Copyright (c) 2020 Dmitry Baryshkov * Copyright (c) 2014 Dmitry Eremin-Solenikov * Copyright (c) 2005-2006 Cryptocom LTD * + * Magma support sponsored by ROSA Linux + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -134,6 +137,74 @@ Gost2814789_decrypt(const unsigned char *in, unsigned char *out, l2c(n1, out); } +void +Magma_encrypt(const unsigned char *in, unsigned char *out, + const MAGMA_KEY *key) +{ + unsigned int n1, n2; /* As named in the GOST */ + + be_c2l(in, n2); + be_c2l(in, n1); + + /* Instead of swapping halves, swap names each round */ + n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]); + n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]); + n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]); + n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]); + + n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]); + n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]); + n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]); + n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]); + + n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]); + n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]); + n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]); + n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]); + + n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]); + n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]); + n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]); + n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]); + + be_l2c(n1, out); + be_l2c(n2, out); +} + +void +Magma_decrypt(const unsigned char *in, unsigned char *out, + const MAGMA_KEY *key) +{ + unsigned int n1, n2; /* As named in the GOST */ + + be_c2l(in, n2); + be_c2l(in, n1); + + /* Instead of swapping halves, swap names each round */ + n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]); + n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]); + n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]); + n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]); + + n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]); + n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]); + n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]); + n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]); + + n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]); + n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]); + n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]); + n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]); + + n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]); + n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]); + n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]); + n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]); + + be_l2c(n1, out); + be_l2c(n2, out); +} + static void Gost2814789_mac(const unsigned char *in, unsigned char *mac, GOST2814789_KEY *key) diff --git a/src/lib/libcrypto/gost/gost89_params.c b/src/lib/libcrypto/gost/gost89_params.c index c454fd7af..7365f7a43 100644 --- a/src/lib/libcrypto/gost/gost89_params.c +++ b/src/lib/libcrypto/gost/gost89_params.c @@ -223,6 +223,30 @@ Gost2814789_set_key(GOST2814789_KEY *key, const unsigned char *userKey) key->count = 0; } +void +Magma_set_key_int(MAGMA_KEY *key, const unsigned char *userKey) +{ + int i; + + for (i = 0; i < 8; i++) + be_c2l(userKey, key->key[i]); + + key->count = 0; +} + +void +Magma_set_key(MAGMA_KEY *key, const unsigned char *userKey) +{ + unsigned int km = key->key_meshing; + + /* Preserve key meshing setting around setting sbox */ + Gost2814789_set_sbox(key, NID_id_tc26_gost_28147_param_Z); + + key->key_meshing = km; + + Magma_set_key_int(key, userKey); +} + void Gost2814789_cryptopro_key_mesh(GOST2814789_KEY *key) { diff --git a/src/lib/libcrypto/gost/gost_locl.h b/src/lib/libcrypto/gost/gost_locl.h index b2e2c1362..302a19c5c 100644 --- a/src/lib/libcrypto/gost/gost_locl.h +++ b/src/lib/libcrypto/gost/gost_locl.h @@ -83,12 +83,23 @@ typedef struct { *((c)++)=(unsigned char)(((l)>>24)&0xff)) #endif +#define be_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) )) +#define be_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + extern void Gost2814789_encrypt(const unsigned char *in, unsigned char *out, const GOST2814789_KEY *key); extern void Gost2814789_decrypt(const unsigned char *in, unsigned char *out, const GOST2814789_KEY *key); extern void Gost2814789_cryptopro_key_mesh(GOST2814789_KEY *key); +void Magma_set_key_int(MAGMA_KEY *key, const unsigned char *userKey); + /* GOST 28147-89 key wrapping */ extern int gost_key_unwrap_crypto_pro(int nid, const unsigned char *keyExchangeKey, const unsigned char *wrappedKey, diff --git a/src/lib/libcrypto/objects/obj_mac.num b/src/lib/libcrypto/objects/obj_mac.num index ba75ec246..fa5914ada 100644 --- a/src/lib/libcrypto/objects/obj_mac.num +++ b/src/lib/libcrypto/objects/obj_mac.num @@ -998,3 +998,12 @@ id_tc26_gost_3410_12_512_paramSetTest 997 id_tc26_gost_3410_12_512_paramSetC 998 id_tc26_hmac_gost_3411_12_256 999 id_tc26_hmac_gost_3411_12_512 1000 +magma_ecb 1001 +magma_cbc 1002 +magma_cfb64 1003 +magma_ofb64 1004 +magma_ctr 1005 +id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1006 +id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1007 +id_tc26_cipher_gostr3412_2015_magma_mgm 1008 +magma_mac 1009 diff --git a/src/lib/libcrypto/objects/objects.txt b/src/lib/libcrypto/objects/objects.txt index 8e533530f..2dbd8575d 100644 --- a/src/lib/libcrypto/objects/objects.txt +++ b/src/lib/libcrypto/objects/objects.txt @@ -1388,6 +1388,20 @@ tc26 1 1 2 : id-tc26-gost3410-2012-512 : GOST R 34.10-2012 (512 bit) tc26 1 3 2 : id-tc26-signwithdigest-gost3410-2012-256 : GOST R 34.11-2012 with GOST R 34.10-2012 (256 bit) tc26 1 3 3 : id-tc26-signwithdigest-gost3410-2012-512 : GOST R 34.11-2012 with GOST R 34.10-2012 (512 bit) +#GOST R 34.12-2014, cipher Magma + : magma-ecb + : magma-cbc + : magma-cfb64 + : magma-ofb64 + : magma-ctr +!Cname id-tc26-cipher-gostr3412-2015-magma-ctracpkm +tc26 1 5 1 1 : magma-ctr-acpkm +!Cname id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac +tc26 1 5 1 2 : magma-ctr-acpkm-omac +!Cname id-tc26-cipher-gostr3412-2015-magma-mgm +tc26 1 5 1 3 : magma-mgm + : magma-mac + # Curves from draft-ietf-curdle-pkix-02 1 3 101 110 : X25519 1 3 101 111 : X448 diff --git a/src/regress/lib/libcrypto/evp/evptests.txt b/src/regress/lib/libcrypto/evp/evptests.txt index 2a5806526..8b4739276 100644 --- a/src/regress/lib/libcrypto/evp/evptests.txt +++ b/src/regress/lib/libcrypto/evp/evptests.txt @@ -382,3 +382,21 @@ ChaCha:5555555555555555555555555555555555555555555555555555555555555555:00000000 ChaCha:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:0000000000000000aaaaaaaaaaaaaaaa0000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:9aa2a9f656efde5aa7591c5fed4b35aea2895dec7cb4543b9e9f21f5e7bcbcf3c43c748a970888f8248393a09d43e0b7e164bc4d0b0fb240a2d72115c4808906:1 ChaCha:00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100:00000000000000000f1e2d3c4b5a69780000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:9fadf409c00811d00431d67efbd88fba59218d5d6708b1d685863fabbb0e961eea480fd6fb532bfd494b2151015057423ab60a63fe4f55f7a212e2167ccab931:1 ChaCha:c46ec1b18ce8a878725a37e780dfb7351f68ed2e194c79fbc6aebee1a667975d:00000000000000001ada31d5cf6882210000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f63a89b75c2271f9368816542ba52f06ed49241792302b00b5e8f80ae9a473afc25b218f519af0fdd406362e8d69de7f54c604a6e00f353f110f771bdca8ab92:1 + +#GOST R 34.12-2015 test vectors +magma-ecb:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff::fedcba9876543210:4ee901e5c2d8ca3d:1 +magma-ecb:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff::fedcba9876543210:4ee901e5c2d8ca3d:0 + +#GOST R 34.13-2015 test vectors +magma-ecb:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff::92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:2b073f0494f372a0de70e715d3556e4811d8d9e9eacfbc1e7c68260996c67efb:1 +magma-ecb:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff::92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:2b073f0494f372a0de70e715d3556e4811d8d9e9eacfbc1e7c68260996c67efb:0 +magma-ctr:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:12345678:92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:4e98110c97b7b93c3e250d93d6e85d69136d868807b2dbef568eb680ab52a12d:1 +magma-ctr:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:12345678:92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:4e98110c97b7b93c3e250d93d6e85d69136d868807b2dbef568eb680ab52a12d:0 + +# Manually +magma-cbc:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:1234567890abcdef234567890abcdef1:92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:96d1b05eea683919f396b78c1d47bb616183e2cca976a4babe9ce87d6fa73cf2:1 +magma-cbc:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:1234567890abcdef234567890abcdef1:92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:96d1b05eea683919f396b78c1d47bb616183e2cca976a4babe9ce87d6fa73cf2:0 +magma-ofb64:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:1234567890abcdef234567890abcdef1:92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:db37e0e266903c8331340c48dcbead127193f8746455692c527d38b4e3feedd2:1 +magma-ofb64:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:1234567890abcdef234567890abcdef1:92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:db37e0e266903c8331340c48dcbead127193f8746455692c527d38b4e3feedd2:0 +magma-cfb64:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:1234567890abcdef234567890abcdef1:92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:db37e0e266903c83b571ee29cca54ce791fabcb3abbe2fe3ff5d972d770f6ae9:1 +magma-cfb64:ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:1234567890abcdef234567890abcdef1:92def06b3c130a59db54c704f8189d204a98fb2e67a8024c8912409b17b57e41:db37e0e266903c83b571ee29cca54ce791fabcb3abbe2fe3ff5d972d770f6ae9:0 -- 2.17.1