/* GOST 28147-89 (Magma) implementation * * Copyright: 2015, 2016 Dmitry Eremin-Solenikov * Copyright: 2009-2012 Aleksey Kravchenko * * 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 #include #include #include "gost28147.h" #include #include 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_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_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); }