--- /dev/null
+/* GOST 28147-89 (Magma) implementation
+ *
+ * Copyright: 2015, 2016 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ * Copyright: 2009-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
+ *
+ * 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.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnutls_int.h>
+
+#include <string.h>
+
+#include <nettle/macros.h>
+#include "gost28147.h"
+#include <nettle/cfb.h>
+#include <nettle/memops.h>
+
+void
+gost28147_kdf_cryptopro(const struct gost28147_param *param,
+ const uint8_t *in,
+ const uint8_t *ukm,
+ uint8_t *out)
+{
+ struct gost28147_ctx ctx;
+ int i;
+
+ memcpy(out, in, GOST28147_KEY_SIZE);
+ for (i = 0; i < 8; i++) {
+ uint8_t mask;
+ uint8_t *p;
+ uint8_t iv[GOST28147_BLOCK_SIZE];
+ uint32_t block[2] = {0, 0};
+ uint32_t t;
+
+ for (p = out, mask = 1; mask; mask <<= 1) {
+ t = LE_READ_UINT32(p);
+ p += 4;
+ if (mask & ukm[i])
+ block[0] += t;
+ else
+ block[1] += t;
+ }
+
+ LE_WRITE_UINT32(iv + 0, block[0]);
+ LE_WRITE_UINT32(iv + 4, block[1]);
+
+ gost28147_set_key(&ctx, out);
+ gost28147_set_param(&ctx, param);
+ cfb_encrypt(&ctx,
+ (nettle_cipher_func*)gost28147_encrypt_for_cfb,
+ GOST28147_BLOCK_SIZE, iv,
+ GOST28147_KEY_SIZE, out, out);
+ }
+}
+
+void
+gost28147_key_wrap_cryptopro(const struct gost28147_param *param,
+ const uint8_t *kek,
+ const uint8_t *ukm, size_t ukm_size,
+ const uint8_t *cek,
+ uint8_t *enc,
+ uint8_t *imit)
+{
+ uint8_t kd[GOST28147_KEY_SIZE];
+ struct gost28147_ctx ctx;
+ struct gost28147_imit_ctx ictx;
+
+ assert(ukm_size >= GOST28147_IMIT_BLOCK_SIZE);
+
+ gost28147_kdf_cryptopro(param, kek, ukm, kd);
+ gost28147_set_key(&ctx, kd);
+ gost28147_set_param(&ctx, param);
+ gost28147_encrypt(&ctx, GOST28147_KEY_SIZE, enc, cek);
+
+ gost28147_imit_init(&ictx);
+ gost28147_imit_set_key(&ictx, GOST28147_KEY_SIZE, kd);
+ gost28147_imit_set_param(&ictx, param);
+ gost28147_imit_set_nonce(&ictx, ukm);
+ gost28147_imit_update(&ictx, GOST28147_KEY_SIZE, cek);
+ gost28147_imit_digest(&ictx, GOST28147_IMIT_DIGEST_SIZE, imit);
+}
+
+int
+gost28147_key_unwrap_cryptopro(const struct gost28147_param *param,
+ const uint8_t *kek,
+ const uint8_t *ukm, size_t ukm_size,
+ const uint8_t *enc,
+ const uint8_t *imit,
+ uint8_t *cek)
+{
+ uint8_t kd[GOST28147_KEY_SIZE];
+ uint8_t mac[GOST28147_IMIT_DIGEST_SIZE];
+ struct gost28147_ctx ctx;
+ struct gost28147_imit_ctx ictx;
+
+ assert(ukm_size >= GOST28147_IMIT_BLOCK_SIZE);
+
+ gost28147_kdf_cryptopro(param, kek, ukm, kd);
+ gost28147_set_key(&ctx, kd);
+ gost28147_set_param(&ctx, param);
+ gost28147_decrypt(&ctx, GOST28147_KEY_SIZE, cek, enc);
+
+ gost28147_imit_init(&ictx);
+ gost28147_imit_set_key(&ictx, GOST28147_KEY_SIZE, kd);
+ gost28147_imit_set_param(&ictx, param);
+ gost28147_imit_set_nonce(&ictx, ukm);
+ gost28147_imit_update(&ictx, GOST28147_KEY_SIZE, cek);
+ gost28147_imit_digest(&ictx, GOST28147_IMIT_DIGEST_SIZE, mac);
+
+ return memeql_sec(mac, imit, GOST28147_IMIT_DIGEST_SIZE);
+}
#define gost28147_cnt_set_iv _gnutls_gost28147_cnt_set_iv
#define gost28147_cnt_crypt _gnutls_gost28147_cnt_crypt
+#define gost28147_kdf_cryptopro _gnutls_gost28147_kdf_cryptopro
+#define gost28147_key_wrap_cryptopro _gnutls_gost28147_key_wrap_cryptopro
+#define gost28147_key_unwrap_cryptopro _gnutls_gost28147_key_unwrap_cryptopro
+
#define gost28147_imit_init _gnutls_gost28147_imit_init
#define gost28147_imit_set_key _gnutls_gost28147_imit_set_key
#define gost28147_imit_set_nonce _gnutls_gost28147_imit_set_nonce
size_t length, uint8_t *dst,
const uint8_t *src);
+void
+gost28147_kdf_cryptopro(const struct gost28147_param *param,
+ const uint8_t *in,
+ const uint8_t *ukm,
+ uint8_t *out);
+void
+gost28147_key_wrap_cryptopro(const struct gost28147_param *param,
+ const uint8_t *kek,
+ const uint8_t *ukm, size_t ukm_size,
+ const uint8_t *cek,
+ uint8_t *enc,
+ uint8_t *imit);
+
+int
+gost28147_key_unwrap_cryptopro(const struct gost28147_param *param,
+ const uint8_t *kek,
+ const uint8_t *ukm, size_t ukm_size,
+ const uint8_t *enc,
+ const uint8_t *imit,
+ uint8_t *cek);
+
#define GOST28147_IMIT_DIGEST_SIZE 4
#define GOST28147_IMIT_BLOCK_SIZE GOST28147_BLOCK_SIZE
#define GOST28147_IMIT_KEY_SIZE GOST28147_KEY_SIZE