check in v3.8.0 source

This commit is contained in:
2023-08-31 00:49:24 -07:00
parent 3ef498f9e6
commit 316795abde
1218 changed files with 562506 additions and 0 deletions

472
crypto/gost/gost2814789.c Normal file
View File

@@ -0,0 +1,472 @@
/* $OpenBSD: gost2814789.c,v 1.8 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <endian.h>
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/objects.h>
#include <openssl/gost.h>
#include "gost_local.h"
static inline unsigned int
f(const GOST2814789_KEY *c, unsigned int x)
{
return c->k87[(x>>24) & 255] | c->k65[(x>>16) & 255]|
c->k43[(x>> 8) & 255] | c->k21[(x ) & 255];
}
void
Gost2814789_encrypt(const unsigned char *in, unsigned char *out,
const GOST2814789_KEY *key)
{
unsigned int n1, n2; /* As named in the GOST */
c2l(in, n1);
c2l(in, n2);
/* 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]);
l2c(n2, out);
l2c(n1, out);
}
void
Gost2814789_decrypt(const unsigned char *in, unsigned char *out,
const GOST2814789_KEY *key)
{
unsigned int n1, n2; /* As named in the GOST */
c2l(in, n1);
c2l(in, n2);
/* 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]);
l2c(n2, out);
l2c(n1, out);
}
static void
Gost2814789_mac(const unsigned char *in, unsigned char *mac,
GOST2814789_KEY *key)
{
unsigned int n1, n2; /* As named in the GOST */
unsigned char *p;
int i;
for (i = 0; i < 8; i++)
mac[i] ^= in[i];
p = mac;
c2l(p, n1);
c2l(p, n2);
/* 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]);
p = mac;
l2c(n1, p);
l2c(n2, p);
}
void
Gost2814789_ecb_encrypt(const unsigned char *in, unsigned char *out,
GOST2814789_KEY *key, const int enc)
{
if (key->key_meshing && key->count == 1024) {
Gost2814789_cryptopro_key_mesh(key);
key->count = 0;
}
if (enc)
Gost2814789_encrypt(in, out, key);
else
Gost2814789_decrypt(in, out, key);
}
static inline void
Gost2814789_encrypt_mesh(unsigned char *iv, GOST2814789_KEY *key)
{
if (key->key_meshing && key->count == 1024) {
Gost2814789_cryptopro_key_mesh(key);
Gost2814789_encrypt(iv, iv, key);
key->count = 0;
}
Gost2814789_encrypt(iv, iv, key);
key->count += 8;
}
static inline void
Gost2814789_mac_mesh(const unsigned char *data, unsigned char *mac,
GOST2814789_KEY *key)
{
if (key->key_meshing && key->count == 1024) {
Gost2814789_cryptopro_key_mesh(key);
key->count = 0;
}
Gost2814789_mac(data, mac, key);
key->count += 8;
}
void
Gost2814789_cfb64_encrypt(const unsigned char *in, unsigned char *out,
size_t len, GOST2814789_KEY *key, unsigned char *ivec, int *num,
const int enc)
{
unsigned int n;
size_t l = 0;
n = *num;
if (enc) {
#if !defined(OPENSSL_SMALL_FOOTPRINT)
if (8 % sizeof(size_t) == 0) do { /* always true actually */
while (n && len) {
*(out++) = ivec[n] ^= *(in++);
--len;
n = (n + 1) % 8;
}
#ifdef __STRICT_ALIGNMENT
if (((size_t)in | (size_t)out | (size_t)ivec) %
sizeof(size_t) != 0)
break;
#endif
while (len >= 8) {
Gost2814789_encrypt_mesh(ivec, key);
for (; n < 8; n += sizeof(size_t)) {
*(size_t*)(out + n) =
*(size_t*)(ivec + n) ^=
*(size_t*)(in + n);
}
len -= 8;
out += 8;
in += 8;
n = 0;
}
if (len) {
Gost2814789_encrypt_mesh(ivec, key);
while (len--) {
out[n] = ivec[n] ^= in[n];
++n;
}
}
*num = n;
return;
} while (0);
/* the rest would be commonly eliminated by x86* compiler */
#endif
while (l<len) {
if (n == 0) {
Gost2814789_encrypt_mesh(ivec, key);
}
out[l] = ivec[n] ^= in[l];
++l;
n = (n + 1) % 8;
}
*num = n;
} else {
#if !defined(OPENSSL_SMALL_FOOTPRINT)
if (8 % sizeof(size_t) == 0) do { /* always true actually */
while (n && len) {
unsigned char c;
*(out++) = ivec[n] ^ (c = *(in++));
ivec[n] = c;
--len;
n = (n + 1) % 8;
}
#ifdef __STRICT_ALIGNMENT
if (((size_t)in | (size_t)out | (size_t)ivec) %
sizeof(size_t) != 0)
break;
#endif
while (len >= 8) {
Gost2814789_encrypt_mesh(ivec, key);
for (; n < 8; n += sizeof(size_t)) {
size_t t = *(size_t*)(in + n);
*(size_t*)(out + n) =
*(size_t*)(ivec + n) ^ t;
*(size_t*)(ivec + n) = t;
}
len -= 8;
out += 8;
in += 8;
n = 0;
}
if (len) {
Gost2814789_encrypt_mesh(ivec, key);
while (len--) {
unsigned char c;
out[n] = ivec[n] ^ (c = in[n]);
ivec[n] = c;
++n;
}
}
*num = n;
return;
} while (0);
/* the rest would be commonly eliminated by x86* compiler */
#endif
while (l < len) {
unsigned char c;
if (n == 0) {
Gost2814789_encrypt_mesh(ivec, key);
}
out[l] = ivec[n] ^ (c = in[l]); ivec[n] = c;
++l;
n = (n + 1) % 8;
}
*num = n;
}
}
static inline void
Gost2814789_cnt_next(unsigned char *ivec, unsigned char *out,
GOST2814789_KEY *key)
{
unsigned char *p = ivec, *p2 = ivec;
unsigned int val, val2;
if (key->count == 0)
Gost2814789_encrypt(ivec, ivec, key);
if (key->key_meshing && key->count == 1024) {
Gost2814789_cryptopro_key_mesh(key);
Gost2814789_encrypt(ivec, ivec, key);
key->count = 0;
}
c2l(p, val);
val2 = val + 0x01010101;
l2c(val2, p2);
c2l(p, val);
val2 = val + 0x01010104;
if (val > val2) /* overflow */
val2++;
l2c(val2, p2);
Gost2814789_encrypt(ivec, out, key);
key->count += 8;
}
void
Gost2814789_cnt_encrypt(const unsigned char *in, unsigned char *out, size_t len,
GOST2814789_KEY *key, unsigned char *ivec, unsigned char *cnt_buf, int *num)
{
unsigned int n;
size_t l = 0;
n = *num;
#if !defined(OPENSSL_SMALL_FOOTPRINT)
if (8 % sizeof(size_t) == 0) do { /* always true actually */
while (n && len) {
*(out++) = *(in++) ^ cnt_buf[n];
--len;
n = (n + 1) % 8;
}
#ifdef __STRICT_ALIGNMENT
if (((size_t)in | (size_t)out | (size_t)ivec) %
sizeof(size_t) != 0)
break;
#endif
while (len >= 8) {
Gost2814789_cnt_next(ivec, cnt_buf, key);
for (; n < 8; n += sizeof(size_t))
*(size_t *)(out + n) = *(size_t *)(in + n) ^
*(size_t *)(cnt_buf + n);
len -= 8;
out += 8;
in += 8;
n = 0;
}
if (len) {
Gost2814789_cnt_next(ivec, cnt_buf, key);
while (len--) {
out[n] = in[n] ^ cnt_buf[n];
++n;
}
}
*num = n;
return;
} while(0);
/* the rest would be commonly eliminated by x86* compiler */
#endif
while (l < len) {
if (n==0)
Gost2814789_cnt_next(ivec, cnt_buf, key);
out[l] = in[l] ^ cnt_buf[n];
++l;
n = (n + 1) % 8;
}
*num=n;
}
int
GOST2814789IMIT_Init(GOST2814789IMIT_CTX *c, int nid)
{
c->Nl = c->Nh = c->num = 0;
memset(c->mac, 0, 8);
return Gost2814789_set_sbox(&c->cipher, nid);
}
static void
GOST2814789IMIT_block_data_order(GOST2814789IMIT_CTX *ctx,
const unsigned char *p, size_t num)
{
int i;
for (i = 0; i < num; i++) {
Gost2814789_mac_mesh(p, ctx->mac, &ctx->cipher);
p += 8;
}
}
#define DATA_ORDER_IS_LITTLE_ENDIAN
#define HASH_CBLOCK GOST2814789IMIT_CBLOCK
#define HASH_LONG GOST2814789IMIT_LONG
#define HASH_CTX GOST2814789IMIT_CTX
#define HASH_UPDATE GOST2814789IMIT_Update
#define HASH_TRANSFORM GOST2814789IMIT_Transform
#define HASH_NO_FINAL 1
#define HASH_BLOCK_DATA_ORDER GOST2814789IMIT_block_data_order
#include "md32_common.h"
int
GOST2814789IMIT_Final(unsigned char *md, GOST2814789IMIT_CTX *c)
{
if (c->num) {
memset(c->data + c->num, 0, 8 - c->num);
Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
}
if (c->Nl <= 8 * 8 && c->Nl > 0 && c->Nh == 0) {
memset(c->data, 0, 8);
Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
}
memcpy(md, c->mac, 4);
return 1;
}
unsigned char *
GOST2814789IMIT(const unsigned char *d, size_t n, unsigned char *md, int nid,
const unsigned char *key, const unsigned char *iv)
{
GOST2814789IMIT_CTX c;
static unsigned char m[GOST2814789IMIT_LENGTH];
if (md == NULL)
md = m;
GOST2814789IMIT_Init(&c, nid);
memcpy(c.mac, iv, 8);
Gost2814789_set_key(&c.cipher, key, 256);
GOST2814789IMIT_Update(&c, d, n);
GOST2814789IMIT_Final(md, &c);
explicit_bzero(&c, sizeof(c));
return (md);
}
#endif

View File

@@ -0,0 +1,138 @@
/* $OpenBSD: gost89_keywrap.c,v 1.4 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/gost.h>
#include "gost_local.h"
static void
key_diversify_crypto_pro(GOST2814789_KEY *ctx, const unsigned char *inputKey,
const unsigned char *ukm, unsigned char *outputKey)
{
unsigned long k, s1, s2;
int i, mask;
unsigned char S[8];
unsigned char *p;
memcpy(outputKey, inputKey, 32);
for (i = 0; i < 8; i++) {
/* Make array of integers from key */
/* Compute IV S */
s1 = 0, s2 = 0;
p = outputKey;
for (mask = 1; mask < 256; mask <<= 1) {
c2l(p, k);
if (mask & ukm[i]) {
s1 += k;
} else {
s2 += k;
}
}
p = S;
l2c (s1, p);
l2c (s2, p);
Gost2814789_set_key(ctx, outputKey, 256);
mask = 0;
Gost2814789_cfb64_encrypt(outputKey, outputKey, 32, ctx, S,
&mask, 1);
}
}
int
gost_key_wrap_crypto_pro(int nid, const unsigned char *keyExchangeKey,
const unsigned char *ukm, const unsigned char *sessionKey,
unsigned char *wrappedKey)
{
GOST2814789_KEY ctx;
unsigned char kek_ukm[32];
Gost2814789_set_sbox(&ctx, nid);
key_diversify_crypto_pro(&ctx, keyExchangeKey, ukm, kek_ukm);
Gost2814789_set_key(&ctx, kek_ukm, 256);
memcpy(wrappedKey, ukm, 8);
Gost2814789_encrypt(sessionKey + 0, wrappedKey + 8 + 0, &ctx);
Gost2814789_encrypt(sessionKey + 8, wrappedKey + 8 + 8, &ctx);
Gost2814789_encrypt(sessionKey + 16, wrappedKey + 8 + 16, &ctx);
Gost2814789_encrypt(sessionKey + 24, wrappedKey + 8 + 24, &ctx);
GOST2814789IMIT(sessionKey, 32, wrappedKey + 40, nid, kek_ukm, ukm);
return 1;
}
int
gost_key_unwrap_crypto_pro(int nid, const unsigned char *keyExchangeKey,
const unsigned char *wrappedKey, unsigned char *sessionKey)
{
unsigned char kek_ukm[32], cek_mac[4];
GOST2814789_KEY ctx;
Gost2814789_set_sbox(&ctx, nid);
/* First 8 bytes of wrapped Key is ukm */
key_diversify_crypto_pro(&ctx, keyExchangeKey, wrappedKey, kek_ukm);
Gost2814789_set_key(&ctx, kek_ukm, 256);
Gost2814789_decrypt(wrappedKey + 8 + 0, sessionKey + 0, &ctx);
Gost2814789_decrypt(wrappedKey + 8 + 8, sessionKey + 8, &ctx);
Gost2814789_decrypt(wrappedKey + 8 + 16, sessionKey + 16, &ctx);
Gost2814789_decrypt(wrappedKey + 8 + 24, sessionKey + 24, &ctx);
GOST2814789IMIT(sessionKey, 32, cek_mac, nid, kek_ukm, wrappedKey);
if (memcmp(cek_mac, wrappedKey + 40, 4))
return 0;
return 1;
}
#endif

244
crypto/gost/gost89_params.c Normal file
View File

@@ -0,0 +1,244 @@
/* $OpenBSD: gost89_params.c,v 1.3 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <stdlib.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/objects.h>
#include <openssl/gost.h>
#include "gost_local.h"
/* Substitution blocks from test examples for GOST R 34.11-94*/
static const gost_subst_block GostR3411_94_TestParamSet = {
{0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC},
{0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC},
{0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE},
{0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2},
{0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3},
{0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB},
{0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9},
{0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3}
};
/* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */
static const gost_subst_block GostR3411_94_CryptoProParamSet = {
{0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
{0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB},
{0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3},
{0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5},
{0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3},
{0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD},
{0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8},
{0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
};
/* Test paramset from GOST 28147 */
gost_subst_block Gost28147_TestParamSet = {
{0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8},
{0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD},
{0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4},
{0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4},
{0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8},
{0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB},
{0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5},
{0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6}
};
/* 1.2.643.2.2.31.1 */
static const gost_subst_block Gost28147_CryptoProParamSetA = {
{0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4},
{0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE},
{0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6},
{0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6},
{0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6},
{0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9},
{0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1},
{0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5}
};
/* 1.2.643.2.2.31.2 */
static const gost_subst_block Gost28147_CryptoProParamSetB = {
{0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC},
{0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE},
{0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5},
{0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3},
{0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8},
{0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4},
{0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE},
{0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF}
};
/* 1.2.643.2.2.31.3 */
static const gost_subst_block Gost28147_CryptoProParamSetC = {
{0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8},
{0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7},
{0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD},
{0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7},
{0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4},
{0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB},
{0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3},
{0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3}
};
/* 1.2.643.2.2.31.4 */
static const gost_subst_block Gost28147_CryptoProParamSetD = {
{0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE},
{0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7},
{0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6},
{0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1},
{0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8},
{0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2},
{0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1},
{0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3}
};
static const gost_subst_block Gost28147_TC26ParamSetZ = {
{0x1,0x7,0xe,0xd,0x0,0x5,0x8,0x3,0x4,0xf,0xa,0x6,0x9,0xc,0xb,0x2},
{0x8,0xe,0x2,0x5,0x6,0x9,0x1,0xc,0xf,0x4,0xb,0x0,0xd,0xa,0x3,0x7},
{0x5,0xd,0xf,0x6,0x9,0x2,0xc,0xa,0xb,0x7,0x8,0x1,0x4,0x3,0xe,0x0},
{0x7,0xf,0x5,0xa,0x8,0x1,0x6,0xd,0x0,0x9,0x3,0xe,0xb,0x4,0x2,0xc},
{0xc,0x8,0x2,0x1,0xd,0x4,0xf,0x6,0x7,0x0,0xa,0x5,0x3,0xe,0x9,0xb},
{0xb,0x3,0x5,0x8,0x2,0xf,0xa,0xd,0xe,0x1,0x7,0x4,0xc,0x9,0x6,0x0},
{0x6,0x8,0x2,0x3,0x9,0xa,0x5,0xc,0x1,0xe,0x4,0x7,0xb,0xd,0x0,0xf},
{0xc,0x4,0x6,0x2,0xa,0x5,0xb,0x9,0xe,0x8,0xd,0x7,0x0,0x3,0xf,0x1}
};
static const unsigned char CryptoProKeyMeshingKey[] = {
0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
};
static const struct gost89_parameters_info {
int nid;
const gost_subst_block *sblock;
int key_meshing;
} gost_cipher_list[] =
{
{NID_id_Gost28147_89_CryptoPro_A_ParamSet,&Gost28147_CryptoProParamSetA,1},
{NID_id_Gost28147_89_CryptoPro_B_ParamSet,&Gost28147_CryptoProParamSetB,1},
{NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1},
{NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1},
{NID_id_tc26_gost_28147_param_Z,&Gost28147_TC26ParamSetZ,1},
{NID_id_Gost28147_89_TestParamSet,&Gost28147_TestParamSet,0},
{NID_id_GostR3411_94_TestParamSet,&GostR3411_94_TestParamSet,0},
{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},
{NID_undef,NULL,0}
};
int
Gost2814789_set_sbox(GOST2814789_KEY *key, int nid)
{
int i;
const gost_subst_block *b = NULL;
unsigned int t;
for (i = 0; gost_cipher_list[i].nid != NID_undef; i++) {
if (gost_cipher_list[i].nid != nid)
continue;
b = gost_cipher_list[i].sblock;
key->key_meshing = gost_cipher_list[i].key_meshing;
break;
}
if (b == NULL)
return 0;
for (i = 0; i < 256; i++) {
t = (unsigned int)(b->k8[i >> 4] <<4 | b->k7 [i & 15]) << 24;
key->k87[i] = (t << 11) | (t >> 21);
t = (unsigned int)(b->k6[i >> 4] <<4 | b->k5 [i & 15]) << 16;
key->k65[i] = (t << 11) | (t >> 21);
t = (unsigned int)(b->k4[i >> 4] <<4 | b->k3 [i & 15]) << 8;
key->k43[i] = (t << 11) | (t >> 21);
t = (unsigned int)(b->k2[i >> 4] <<4 | b->k1 [i & 15]) << 0;
key->k21[i] = (t << 11) | (t >> 21);
}
return 1;
}
int
Gost2814789_set_key(GOST2814789_KEY *key, const unsigned char *userKey,
const int bits)
{
int i;
if (bits != 256)
return 0;
for (i = 0; i < 8; i++)
c2l(userKey, key->key[i]);
key->count = 0;
return 1;
}
void
Gost2814789_cryptopro_key_mesh(GOST2814789_KEY *key)
{
unsigned char newkey[32];
Gost2814789_decrypt(CryptoProKeyMeshingKey + 0, newkey + 0, key);
Gost2814789_decrypt(CryptoProKeyMeshingKey + 8, newkey + 8, key);
Gost2814789_decrypt(CryptoProKeyMeshingKey + 16, newkey + 16, key);
Gost2814789_decrypt(CryptoProKeyMeshingKey + 24, newkey + 24, key);
Gost2814789_set_key(key, newkey, 256);
}
#endif

View File

@@ -0,0 +1,89 @@
/* $OpenBSD: gost89imit_ameth.c,v 1.4 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/evp.h>
#include "asn1_local.h"
#include "evp_local.h"
static void
mackey_free_gost(EVP_PKEY *pk)
{
free(pk->pkey.ptr);
}
static int
mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
switch (op) {
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
*(int *)arg2 = NID_id_Gost28147_89_MAC;
return 2;
}
return -2;
}
const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth = {
.pkey_id = EVP_PKEY_GOSTIMIT,
.pkey_base_id = EVP_PKEY_GOSTIMIT,
.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
.pem_str = "GOST-MAC",
.info = "GOST 28147-89 MAC",
.pkey_free = mackey_free_gost,
.pkey_ctrl = mac_ctrl_gost,
};
#endif

View File

@@ -0,0 +1,248 @@
/* $OpenBSD: gost89imit_pmeth.c,v 1.5 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/gost.h>
#include <openssl/x509v3.h> /* For string_to_hex */
#include "evp_local.h"
#include "gost_local.h"
struct gost_mac_pmeth_data {
EVP_MD *md;
unsigned char key[32];
unsigned key_set :1;
};
static int
pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
{
struct gost_mac_pmeth_data *data;
data = calloc(1, sizeof(struct gost_mac_pmeth_data));
if (data == NULL)
return 0;
EVP_PKEY_CTX_set_data(ctx, data);
return 1;
}
static void
pkey_gost_mac_cleanup(EVP_PKEY_CTX *ctx)
{
struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
free(data);
}
static int
pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
struct gost_mac_pmeth_data *dst_data, *src_data;
if (pkey_gost_mac_init(dst) == 0)
return 0;
src_data = EVP_PKEY_CTX_get_data(src);
dst_data = EVP_PKEY_CTX_get_data(dst);
*dst_data = *src_data;
return 1;
}
static int
pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
unsigned char *keydata;
if (!data->key_set) {
GOSTerror(GOST_R_MAC_KEY_NOT_SET);
return 0;
}
keydata = malloc(32);
if (keydata == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(keydata, data->key, 32);
EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata);
return 1;
}
static int
pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
switch (type) {
case EVP_PKEY_CTRL_MD:
if (EVP_MD_type(p2) != NID_id_Gost28147_89_MAC) {
GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
return 0;
}
data->md = p2;
return 1;
case EVP_PKEY_CTRL_SET_MAC_KEY:
if (p1 != 32) {
GOSTerror(GOST_R_INVALID_MAC_KEY_LENGTH);
return 0;
}
memcpy(data->key, p2, 32);
data->key_set = 1;
return 1;
case EVP_PKEY_CTRL_DIGESTINIT:
{
EVP_MD_CTX *mctx = p2;
void *key;
if (!data->key_set) {
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (pkey == NULL) {
GOSTerror(GOST_R_MAC_KEY_NOT_SET);
return 0;
}
key = EVP_PKEY_get0(pkey);
if (key == NULL) {
GOSTerror(GOST_R_MAC_KEY_NOT_SET);
return 0;
}
} else {
key = &(data->key);
}
if (mctx->digest->md_ctrl == NULL)
return 0;
return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32 * 8,
key);
}
}
return -2;
}
static int
pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
{
if (value == NULL)
return 0;
if (strcmp(type, "key") == 0) {
void *p = (void *)value;
return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
strlen(value), p);
}
if (strcmp(type, "hexkey") == 0) {
unsigned char *key;
int r;
long keylen;
key = string_to_hex(value, &keylen);
if (key == NULL)
return 0;
r = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen,
key);
free(key);
return r;
}
return -2;
}
static int
pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
{
return 1;
}
static int
pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
EVP_MD_CTX *mctx)
{
/* for platforms where sizeof(int) != sizeof(size_t)*/
unsigned int tmpsiglen = *siglen;
int ret;
if (sig == NULL) {
*siglen = 4;
return 1;
}
ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
*siglen = tmpsiglen;
return ret;
}
const EVP_PKEY_METHOD gostimit_pkey_meth = {
.pkey_id = EVP_PKEY_GOSTIMIT,
.init = pkey_gost_mac_init,
.cleanup = pkey_gost_mac_cleanup,
.copy = pkey_gost_mac_copy,
.keygen = pkey_gost_mac_keygen,
.signctx_init = pkey_gost_mac_signctx_init,
.signctx = pkey_gost_mac_signctx,
.ctrl = pkey_gost_mac_ctrl,
.ctrl_str = pkey_gost_mac_ctrl_str,
};
#endif

295
crypto/gost/gost_asn1.c Normal file
View File

@@ -0,0 +1,295 @@
/**********************************************************************
* gost_keytrans.c *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* ASN1 structure definition for GOST key transport *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/gost.h>
#include "gost_local.h"
#include "gost_asn1.h"
static const ASN1_TEMPLATE GOST_KEY_TRANSPORT_seq_tt[] = {
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_KEY_TRANSPORT, key_info),
.field_name = "key_info",
.item = &GOST_KEY_INFO_it,
},
{
.flags = ASN1_TFLG_IMPLICIT,
.tag = 0,
.offset = offsetof(GOST_KEY_TRANSPORT, key_agreement_info),
.field_name = "key_agreement_info",
.item = &GOST_KEY_AGREEMENT_INFO_it,
},
};
const ASN1_ITEM GOST_KEY_TRANSPORT_it = {
.itype = ASN1_ITYPE_NDEF_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = GOST_KEY_TRANSPORT_seq_tt,
.tcount = sizeof(GOST_KEY_TRANSPORT_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = NULL,
.size = sizeof(GOST_KEY_TRANSPORT),
.sname = "GOST_KEY_TRANSPORT",
};
GOST_KEY_TRANSPORT *
d2i_GOST_KEY_TRANSPORT(GOST_KEY_TRANSPORT **a, const unsigned char **in, long len)
{
return (GOST_KEY_TRANSPORT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&GOST_KEY_TRANSPORT_it);
}
int
i2d_GOST_KEY_TRANSPORT(GOST_KEY_TRANSPORT *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_KEY_TRANSPORT_it);
}
GOST_KEY_TRANSPORT *
GOST_KEY_TRANSPORT_new(void)
{
return (GOST_KEY_TRANSPORT *)ASN1_item_new(&GOST_KEY_TRANSPORT_it);
}
void
GOST_KEY_TRANSPORT_free(GOST_KEY_TRANSPORT *a)
{
ASN1_item_free((ASN1_VALUE *)a, &GOST_KEY_TRANSPORT_it);
}
static const ASN1_TEMPLATE GOST_KEY_INFO_seq_tt[] = {
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_KEY_INFO, encrypted_key),
.field_name = "encrypted_key",
.item = &ASN1_OCTET_STRING_it,
},
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_KEY_INFO, imit),
.field_name = "imit",
.item = &ASN1_OCTET_STRING_it,
},
};
const ASN1_ITEM GOST_KEY_INFO_it = {
.itype = ASN1_ITYPE_NDEF_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = GOST_KEY_INFO_seq_tt,
.tcount = sizeof(GOST_KEY_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = NULL,
.size = sizeof(GOST_KEY_INFO),
.sname = "GOST_KEY_INFO",
};
GOST_KEY_INFO *
d2i_GOST_KEY_INFO(GOST_KEY_INFO **a, const unsigned char **in, long len)
{
return (GOST_KEY_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&GOST_KEY_INFO_it);
}
int
i2d_GOST_KEY_INFO(GOST_KEY_INFO *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_KEY_INFO_it);
}
GOST_KEY_INFO *
GOST_KEY_INFO_new(void)
{
return (GOST_KEY_INFO *)ASN1_item_new(&GOST_KEY_INFO_it);
}
void
GOST_KEY_INFO_free(GOST_KEY_INFO *a)
{
ASN1_item_free((ASN1_VALUE *)a, &GOST_KEY_INFO_it);
}
static const ASN1_TEMPLATE GOST_KEY_AGREEMENT_INFO_seq_tt[] = {
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_KEY_AGREEMENT_INFO, cipher),
.field_name = "cipher",
.item = &ASN1_OBJECT_it,
},
{
.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
.tag = 0,
.offset = offsetof(GOST_KEY_AGREEMENT_INFO, ephem_key),
.field_name = "ephem_key",
.item = &X509_PUBKEY_it,
},
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_KEY_AGREEMENT_INFO, eph_iv),
.field_name = "eph_iv",
.item = &ASN1_OCTET_STRING_it,
},
};
const ASN1_ITEM GOST_KEY_AGREEMENT_INFO_it = {
.itype = ASN1_ITYPE_NDEF_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = GOST_KEY_AGREEMENT_INFO_seq_tt,
.tcount = sizeof(GOST_KEY_AGREEMENT_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = NULL,
.size = sizeof(GOST_KEY_AGREEMENT_INFO),
.sname = "GOST_KEY_AGREEMENT_INFO",
};
GOST_KEY_AGREEMENT_INFO *
d2i_GOST_KEY_AGREEMENT_INFO(GOST_KEY_AGREEMENT_INFO **a, const unsigned char **in, long len)
{
return (GOST_KEY_AGREEMENT_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&GOST_KEY_AGREEMENT_INFO_it);
}
int
i2d_GOST_KEY_AGREEMENT_INFO(GOST_KEY_AGREEMENT_INFO *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_KEY_AGREEMENT_INFO_it);
}
GOST_KEY_AGREEMENT_INFO *
GOST_KEY_AGREEMENT_INFO_new(void)
{
return (GOST_KEY_AGREEMENT_INFO *)ASN1_item_new(&GOST_KEY_AGREEMENT_INFO_it);
}
void
GOST_KEY_AGREEMENT_INFO_free(GOST_KEY_AGREEMENT_INFO *a)
{
ASN1_item_free((ASN1_VALUE *)a, &GOST_KEY_AGREEMENT_INFO_it);
}
static const ASN1_TEMPLATE GOST_KEY_PARAMS_seq_tt[] = {
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_KEY_PARAMS, key_params),
.field_name = "key_params",
.item = &ASN1_OBJECT_it,
},
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_KEY_PARAMS, hash_params),
.field_name = "hash_params",
.item = &ASN1_OBJECT_it,
},
{
.flags = ASN1_TFLG_OPTIONAL,
.tag = 0,
.offset = offsetof(GOST_KEY_PARAMS, cipher_params),
.field_name = "cipher_params",
.item = &ASN1_OBJECT_it,
},
};
const ASN1_ITEM GOST_KEY_PARAMS_it = {
.itype = ASN1_ITYPE_NDEF_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = GOST_KEY_PARAMS_seq_tt,
.tcount = sizeof(GOST_KEY_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = NULL,
.size = sizeof(GOST_KEY_PARAMS),
.sname = "GOST_KEY_PARAMS",
};
GOST_KEY_PARAMS *
d2i_GOST_KEY_PARAMS(GOST_KEY_PARAMS **a, const unsigned char **in, long len)
{
return (GOST_KEY_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&GOST_KEY_PARAMS_it);
}
int
i2d_GOST_KEY_PARAMS(GOST_KEY_PARAMS *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_KEY_PARAMS_it);
}
GOST_KEY_PARAMS *
GOST_KEY_PARAMS_new(void)
{
return (GOST_KEY_PARAMS *)ASN1_item_new(&GOST_KEY_PARAMS_it);
}
void
GOST_KEY_PARAMS_free(GOST_KEY_PARAMS *a)
{
ASN1_item_free((ASN1_VALUE *)a, &GOST_KEY_PARAMS_it);
}
static const ASN1_TEMPLATE GOST_CIPHER_PARAMS_seq_tt[] = {
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_CIPHER_PARAMS, iv),
.field_name = "iv",
.item = &ASN1_OCTET_STRING_it,
},
{
.flags = 0,
.tag = 0,
.offset = offsetof(GOST_CIPHER_PARAMS, enc_param_set),
.field_name = "enc_param_set",
.item = &ASN1_OBJECT_it,
},
};
const ASN1_ITEM GOST_CIPHER_PARAMS_it = {
.itype = ASN1_ITYPE_NDEF_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = GOST_CIPHER_PARAMS_seq_tt,
.tcount = sizeof(GOST_CIPHER_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = NULL,
.size = sizeof(GOST_CIPHER_PARAMS),
.sname = "GOST_CIPHER_PARAMS",
};
GOST_CIPHER_PARAMS *
d2i_GOST_CIPHER_PARAMS(GOST_CIPHER_PARAMS **a, const unsigned char **in, long len)
{
return (GOST_CIPHER_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&GOST_CIPHER_PARAMS_it);
}
int
i2d_GOST_CIPHER_PARAMS(GOST_CIPHER_PARAMS *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_CIPHER_PARAMS_it);
}
GOST_CIPHER_PARAMS *
GOST_CIPHER_PARAMS_new(void)
{
return (GOST_CIPHER_PARAMS *)ASN1_item_new(&GOST_CIPHER_PARAMS_it);
}
void
GOST_CIPHER_PARAMS_free(GOST_CIPHER_PARAMS *a)
{
ASN1_item_free((ASN1_VALUE *)a, &GOST_CIPHER_PARAMS_it);
}
#endif

107
crypto/gost/gost_asn1.h Normal file
View File

@@ -0,0 +1,107 @@
/* $OpenBSD: gost_asn1.h,v 1.3 2016/12/21 15:49:29 jsing Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#ifndef HEADER_GOST_ASN1_H
#define HEADER_GOST_ASN1_H
#include <openssl/asn1.h>
__BEGIN_HIDDEN_DECLS
typedef struct {
ASN1_OCTET_STRING *encrypted_key;
ASN1_OCTET_STRING *imit;
} GOST_KEY_INFO;
GOST_KEY_INFO *GOST_KEY_INFO_new(void);
void GOST_KEY_INFO_free(GOST_KEY_INFO *a);
GOST_KEY_INFO *d2i_GOST_KEY_INFO(GOST_KEY_INFO **a, const unsigned char **in, long len);
int i2d_GOST_KEY_INFO(GOST_KEY_INFO *a, unsigned char **out);
extern const ASN1_ITEM GOST_KEY_INFO_it;
typedef struct {
ASN1_OBJECT *cipher;
X509_PUBKEY *ephem_key;
ASN1_OCTET_STRING *eph_iv;
} GOST_KEY_AGREEMENT_INFO;
GOST_KEY_AGREEMENT_INFO *GOST_KEY_AGREEMENT_INFO_new(void);
void GOST_KEY_AGREEMENT_INFO_free(GOST_KEY_AGREEMENT_INFO *a);
GOST_KEY_AGREEMENT_INFO *d2i_GOST_KEY_AGREEMENT_INFO(GOST_KEY_AGREEMENT_INFO **a, const unsigned char **in, long len);
int i2d_GOST_KEY_AGREEMENT_INFO(GOST_KEY_AGREEMENT_INFO *a, unsigned char **out);
extern const ASN1_ITEM GOST_KEY_AGREEMENT_INFO_it;
typedef struct {
GOST_KEY_INFO *key_info;
GOST_KEY_AGREEMENT_INFO *key_agreement_info;
} GOST_KEY_TRANSPORT;
GOST_KEY_TRANSPORT *GOST_KEY_TRANSPORT_new(void);
void GOST_KEY_TRANSPORT_free(GOST_KEY_TRANSPORT *a);
GOST_KEY_TRANSPORT *d2i_GOST_KEY_TRANSPORT(GOST_KEY_TRANSPORT **a, const unsigned char **in, long len);
int i2d_GOST_KEY_TRANSPORT(GOST_KEY_TRANSPORT *a, unsigned char **out);
extern const ASN1_ITEM GOST_KEY_TRANSPORT_it;
typedef struct {
ASN1_OBJECT *key_params;
ASN1_OBJECT *hash_params;
ASN1_OBJECT *cipher_params;
} GOST_KEY_PARAMS;
GOST_KEY_PARAMS *GOST_KEY_PARAMS_new(void);
void GOST_KEY_PARAMS_free(GOST_KEY_PARAMS *a);
GOST_KEY_PARAMS *d2i_GOST_KEY_PARAMS(GOST_KEY_PARAMS **a, const unsigned char **in, long len);
int i2d_GOST_KEY_PARAMS(GOST_KEY_PARAMS *a, unsigned char **out);
extern const ASN1_ITEM GOST_KEY_PARAMS_it;
__END_HIDDEN_DECLS
#endif

105
crypto/gost/gost_err.c Normal file
View File

@@ -0,0 +1,105 @@
/* crypto/gost/gost_err.c */
/* ====================================================================
* Copyright (c) 1999-2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/gost.h>
#ifndef OPENSSL_NO_ERR
#define ERR_FUNC(func) ERR_PACK(ERR_LIB_GOST,func,0)
#define ERR_REASON(reason) ERR_PACK(ERR_LIB_GOST,0,reason)
static ERR_STRING_DATA GOST_str_functs[]= {
{ERR_FUNC(0xfff), "CRYPTO_internal"},
{0, NULL}
};
static ERR_STRING_DATA GOST_str_reasons[] = {
{ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"},
{ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"},
{ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"},
{ERR_REASON(GOST_R_CTRL_CALL_FAILED) ,"ctrl call failed"},
{ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"},
{ERR_REASON(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"},
{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"},
{ERR_REASON(GOST_R_INCOMPATIBLE_PEER_KEY),"incompatible peer key"},
{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"},
{ERR_REASON(GOST_R_INVALID_IV_LENGTH) ,"invalid iv length"},
{ERR_REASON(GOST_R_INVALID_MAC_KEY_LENGTH),"invalid mac key length"},
{ERR_REASON(GOST_R_KEY_IS_NOT_INITIALIZED),"key is not initialized"},
{ERR_REASON(GOST_R_KEY_PARAMETERS_MISSING),"key parameters missing"},
{ERR_REASON(GOST_R_MAC_KEY_NOT_SET) ,"mac key not set"},
{ERR_REASON(GOST_R_NO_PARAMETERS_SET) ,"no parameters set"},
{ERR_REASON(GOST_R_NO_PEER_KEY) ,"no peer key"},
{ERR_REASON(GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR),"no private part of non ephemeral keypair"},
{ERR_REASON(GOST_R_PUBLIC_KEY_UNDEFINED) ,"public key undefined"},
{ERR_REASON(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED),"random number generator failed"},
{ERR_REASON(GOST_R_SIGNATURE_MISMATCH) ,"signature mismatch"},
{ERR_REASON(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q),"signature parts greater than q"},
{ERR_REASON(GOST_R_UKM_NOT_SET) ,"ukm not set"},
{0, NULL}
};
#endif
void
ERR_load_GOST_strings(void) {
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(GOST_str_functs[0].error) == NULL) {
ERR_load_strings(0,GOST_str_functs);
ERR_load_strings(0,GOST_str_reasons);
}
#endif
}

117
crypto/gost/gost_local.h Normal file
View File

@@ -0,0 +1,117 @@
/* $OpenBSD: gost_local.h,v 1.2 2022/11/26 17:23:18 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#ifndef HEADER_GOST_LOCAL_H
#define HEADER_GOST_LOCAL_H
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
__BEGIN_HIDDEN_DECLS
/* Internal representation of GOST substitution blocks */
typedef struct {
unsigned char k8[16];
unsigned char k7[16];
unsigned char k6[16];
unsigned char k5[16];
unsigned char k4[16];
unsigned char k3[16];
unsigned char k2[16];
unsigned char k1[16];
} gost_subst_block;
#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
# define c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4)
# define l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4)
#else
#define c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<<24))
#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff))
#endif
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);
/* GOST 28147-89 key wrapping */
extern int gost_key_unwrap_crypto_pro(int nid,
const unsigned char *keyExchangeKey, const unsigned char *wrappedKey,
unsigned char *sessionKey);
extern int gost_key_wrap_crypto_pro(int nid,
const unsigned char *keyExchangeKey, const unsigned char *ukm,
const unsigned char *sessionKey, unsigned char *wrappedKey);
/* Pkey part */
extern int gost2001_compute_public(GOST_KEY *ec);
extern ECDSA_SIG *gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey);
extern int gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec);
extern int gost2001_keygen(GOST_KEY *ec);
extern int VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey,
GOST_KEY *priv_key, const BIGNUM *ukm);
extern BIGNUM *GOST_le2bn(const unsigned char *buf, size_t len, BIGNUM *bn);
extern int GOST_bn2le(BIGNUM *bn, unsigned char *buf, int len);
/* GOST R 34.10 parameters */
extern int GostR3410_get_md_digest(int nid);
extern int GostR3410_get_pk_digest(int nid);
extern int GostR3410_256_param_id(const char *value);
extern int GostR3410_512_param_id(const char *value);
__END_HIDDEN_DECLS
#endif /* !HEADER_GOST_LOCAL_H */

403
crypto/gost/gostr341001.c Normal file
View File

@@ -0,0 +1,403 @@
/* $OpenBSD: gostr341001.c,v 1.11 2022/12/01 02:58:31 jsing Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/gost.h>
#include "bn_local.h"
#include "ecs_local.h"
#include "gost_local.h"
/* Convert little-endian byte array into bignum */
BIGNUM *
GOST_le2bn(const unsigned char *buf, size_t len, BIGNUM *bn)
{
unsigned char temp[64];
int i;
if (len > 64)
return NULL;
for (i = 0; i < len; i++) {
temp[len - 1 - i] = buf[i];
}
return BN_bin2bn(temp, len, bn);
}
int
GOST_bn2le(BIGNUM *bn, unsigned char *buf, int len)
{
unsigned char temp[64];
int i, bytes;
bytes = BN_num_bytes(bn);
if (len > 64 || bytes > len)
return 0;
BN_bn2bin(bn, temp);
for (i = 0; i < bytes; i++) {
buf[bytes - 1 - i] = temp[i];
}
memset(buf + bytes, 0, len - bytes);
return 1;
}
int
gost2001_compute_public(GOST_KEY *ec)
{
const EC_GROUP *group = GOST_KEY_get0_group(ec);
EC_POINT *pub_key = NULL;
const BIGNUM *priv_key = NULL;
BN_CTX *ctx = NULL;
int ok = 0;
if (group == NULL) {
GOSTerror(GOST_R_KEY_IS_NOT_INITIALIZED);
return 0;
}
ctx = BN_CTX_new();
if (ctx == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
BN_CTX_start(ctx);
if ((priv_key = GOST_KEY_get0_private_key(ec)) == NULL)
goto err;
pub_key = EC_POINT_new(group);
if (pub_key == NULL)
goto err;
if (EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx) == 0)
goto err;
if (GOST_KEY_set_public_key(ec, pub_key) == 0)
goto err;
ok = 1;
if (ok == 0) {
err:
GOSTerror(ERR_R_EC_LIB);
}
EC_POINT_free(pub_key);
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
return ok;
}
ECDSA_SIG *
gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey)
{
ECDSA_SIG *newsig = NULL;
BIGNUM *order = NULL;
const EC_GROUP *group;
const BIGNUM *priv_key;
BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k =
NULL, *e = NULL;
EC_POINT *C = NULL;
BN_CTX *ctx = BN_CTX_new();
int ok = 0;
if (ctx == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
BN_CTX_start(ctx);
newsig = ECDSA_SIG_new();
if (newsig == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
goto err;
}
s = newsig->s;
r = newsig->r;
group = GOST_KEY_get0_group(eckey);
if ((order = BN_CTX_get(ctx)) == NULL)
goto err;
if (EC_GROUP_get_order(group, order, ctx) == 0)
goto err;
priv_key = GOST_KEY_get0_private_key(eckey);
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
if (BN_mod_ct(e, md, order, ctx) == 0)
goto err;
if (BN_is_zero(e)) {
if (!BN_one(e))
goto err;
}
if ((k = BN_CTX_get(ctx)) == NULL)
goto err;
if ((X = BN_CTX_get(ctx)) == NULL)
goto err;
if ((C = EC_POINT_new(group)) == NULL)
goto err;
do {
do {
if (!BN_rand_range(k, order)) {
GOSTerror(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
goto err;
}
/*
* We do not want timing information to leak the length
* of k, so we compute G*k using an equivalent scalar
* of fixed bit-length.
*/
if (BN_add(k, k, order) == 0)
goto err;
if (BN_num_bits(k) <= BN_num_bits(order))
if (BN_add(k, k, order) == 0)
goto err;
if (EC_POINT_mul(group, C, k, NULL, NULL, ctx) == 0) {
GOSTerror(ERR_R_EC_LIB);
goto err;
}
if (EC_POINT_get_affine_coordinates(group, C, X,
NULL, ctx) == 0) {
GOSTerror(ERR_R_EC_LIB);
goto err;
}
if (BN_nnmod(r, X, order, ctx) == 0)
goto err;
} while (BN_is_zero(r));
/* s = (r*priv_key+k*e) mod order */
if (tmp == NULL) {
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
}
if (BN_mod_mul(tmp, priv_key, r, order, ctx) == 0)
goto err;
if (tmp2 == NULL) {
if ((tmp2 = BN_CTX_get(ctx)) == NULL)
goto err;
}
if (BN_mod_mul(tmp2, k, e, order, ctx) == 0)
goto err;
if (BN_mod_add(s, tmp, tmp2, order, ctx) == 0)
goto err;
} while (BN_is_zero(s));
ok = 1;
err:
EC_POINT_free(C);
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
if (ok == 0) {
ECDSA_SIG_free(newsig);
newsig = NULL;
}
return newsig;
}
int
gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec)
{
BN_CTX *ctx = BN_CTX_new();
const EC_GROUP *group = GOST_KEY_get0_group(ec);
BIGNUM *order;
BIGNUM *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = NULL;
BIGNUM *X = NULL, *tmp = NULL;
EC_POINT *C = NULL;
const EC_POINT *pub_key = NULL;
int ok = 0;
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
if ((order = BN_CTX_get(ctx)) == NULL)
goto err;
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
if ((z1 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((z2 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((tmp = BN_CTX_get(ctx)) == NULL)
goto err;
if ((X = BN_CTX_get(ctx)) == NULL)
goto err;
if ((R = BN_CTX_get(ctx)) == NULL)
goto err;
if ((v = BN_CTX_get(ctx)) == NULL)
goto err;
if (EC_GROUP_get_order(group, order, ctx) == 0)
goto err;
pub_key = GOST_KEY_get0_public_key(ec);
if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
BN_cmp(sig->s, order) >= 1 || BN_cmp(sig->r, order) >= 1) {
GOSTerror(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
goto err;
}
if (BN_mod_ct(e, md, order, ctx) == 0)
goto err;
if (BN_is_zero(e)) {
if (!BN_one(e))
goto err;
}
if ((v = BN_mod_inverse_ct(v, e, order, ctx)) == NULL)
goto err;
if (BN_mod_mul(z1, sig->s, v, order, ctx) == 0)
goto err;
if (BN_sub(tmp, order, sig->r) == 0)
goto err;
if (BN_mod_mul(z2, tmp, v, order, ctx) == 0)
goto err;
if ((C = EC_POINT_new(group)) == NULL)
goto err;
if (EC_POINT_mul(group, C, z1, pub_key, z2, ctx) == 0) {
GOSTerror(ERR_R_EC_LIB);
goto err;
}
if (EC_POINT_get_affine_coordinates(group, C, X, NULL, ctx) == 0) {
GOSTerror(ERR_R_EC_LIB);
goto err;
}
if (BN_mod_ct(R, X, order, ctx) == 0)
goto err;
if (BN_cmp(R, sig->r) != 0) {
GOSTerror(GOST_R_SIGNATURE_MISMATCH);
} else {
ok = 1;
}
err:
EC_POINT_free(C);
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
return ok;
}
/* Implementation of CryptoPro VKO 34.10-2001 algorithm */
int
VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey, GOST_KEY *priv_key,
const BIGNUM *ukm)
{
BIGNUM *p = NULL, *order = NULL;
const BIGNUM *key = GOST_KEY_get0_private_key(priv_key);
const EC_GROUP *group = GOST_KEY_get0_group(priv_key);
const EC_POINT *pub_key = GOST_KEY_get0_public_key(pkey);
EC_POINT *pnt;
BN_CTX *ctx = NULL;
int ok = 0;
pnt = EC_POINT_new(group);
if (pnt == NULL)
goto err;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
if ((p = BN_CTX_get(ctx)) == NULL)
goto err;
if ((order = BN_CTX_get(ctx)) == NULL)
goto err;
if (EC_GROUP_get_order(group, order, ctx) == 0)
goto err;
if (BN_mod_mul(p, key, ukm, order, ctx) == 0)
goto err;
if (EC_POINT_mul(group, pnt, NULL, pub_key, p, ctx) == 0)
goto err;
if (EC_POINT_get_affine_coordinates(group, pnt, X, Y, ctx) == 0)
goto err;
ok = 1;
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
EC_POINT_free(pnt);
return ok;
}
int
gost2001_keygen(GOST_KEY *ec)
{
BIGNUM *order = BN_new(), *d = BN_new();
const EC_GROUP *group = GOST_KEY_get0_group(ec);
int rc = 0;
if (order == NULL || d == NULL)
goto err;
if (EC_GROUP_get_order(group, order, NULL) == 0)
goto err;
do {
if (BN_rand_range(d, order) == 0) {
GOSTerror(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
goto err;
}
} while (BN_is_zero(d));
if (GOST_KEY_set_private_key(ec, d) == 0)
goto err;
rc = gost2001_compute_public(ec);
err:
BN_free(d);
BN_free(order);
return rc;
}
#endif

View File

@@ -0,0 +1,721 @@
/* $OpenBSD: gostr341001_ameth.c,v 1.20 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/gost.h>
#include "asn1_local.h"
#include "evp_local.h"
#include "gost_local.h"
#include "gost_asn1.h"
static void
pkey_free_gost01(EVP_PKEY *key)
{
GOST_KEY_free(key->pkey.gost);
}
/*
* Parses GOST algorithm parameters from X509_ALGOR and
* modifies pkey setting NID and parameters
*/
static int
decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len)
{
int param_nid = NID_undef, digest_nid = NID_undef;
GOST_KEY_PARAMS *gkp = NULL;
EC_GROUP *group;
GOST_KEY *ec;
gkp = d2i_GOST_KEY_PARAMS(NULL, p, len);
if (gkp == NULL) {
GOSTerror(GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
return 0;
}
param_nid = OBJ_obj2nid(gkp->key_params);
digest_nid = OBJ_obj2nid(gkp->hash_params);
GOST_KEY_PARAMS_free(gkp);
ec = pkey->pkey.gost;
if (ec == NULL) {
ec = GOST_KEY_new();
if (ec == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
if (EVP_PKEY_assign_GOST(pkey, ec) == 0)
return 0;
}
group = EC_GROUP_new_by_curve_name(param_nid);
if (group == NULL) {
GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
return 0;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
if (GOST_KEY_set_group(ec, group) == 0) {
EC_GROUP_free(group);
return 0;
}
EC_GROUP_free(group);
if (GOST_KEY_set_digest(ec, digest_nid) == 0)
return 0;
return 1;
}
static ASN1_STRING *
encode_gost01_algor_params(const EVP_PKEY *key)
{
ASN1_STRING *params = ASN1_STRING_new();
GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
int pkey_param_nid = NID_undef;
if (params == NULL || gkp == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(params);
params = NULL;
goto err;
}
pkey_param_nid =
EC_GROUP_get_curve_name(GOST_KEY_get0_group(key->pkey.gost));
gkp->key_params = OBJ_nid2obj(pkey_param_nid);
gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost));
/*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */
params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
if (params->length <= 0) {
GOSTerror(ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(params);
params = NULL;
goto err;
}
params->type = V_ASN1_SEQUENCE;
err:
GOST_KEY_PARAMS_free(gkp);
return params;
}
static int
pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
{
const GOST_KEY *ea = a->pkey.gost;
const GOST_KEY *eb = b->pkey.gost;
const EC_POINT *ka, *kb;
int ret = 0;
if (ea == NULL || eb == NULL)
return 0;
ka = GOST_KEY_get0_public_key(ea);
kb = GOST_KEY_get0_public_key(eb);
if (ka == NULL || kb == NULL)
return 0;
ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL));
return ret;
}
static int
pkey_size_gost01(const EVP_PKEY *pk)
{
if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
return 128;
return 64;
}
static int
pkey_bits_gost01(const EVP_PKEY *pk)
{
if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
return 512;
return 256;
}
static int
pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
{
X509_ALGOR *palg = NULL;
const unsigned char *pubkey_buf = NULL;
const unsigned char *p;
ASN1_OBJECT *palgobj = NULL;
int pub_len;
BIGNUM *X, *Y;
ASN1_OCTET_STRING *octet = NULL;
int len;
int ret;
int ptype = V_ASN1_UNDEF;
ASN1_STRING *pval = NULL;
if (X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub)
== 0)
return 0;
(void)EVP_PKEY_assign_GOST(pk, NULL);
X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
if (ptype != V_ASN1_SEQUENCE) {
GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
return 0;
}
p = pval->data;
if (decode_gost01_algor_params(pk, &p, pval->length) == 0) {
GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
return 0;
}
octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
if (octet == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
len = octet->length / 2;
X = GOST_le2bn(octet->data, len, NULL);
Y = GOST_le2bn(octet->data + len, len, NULL);
ASN1_OCTET_STRING_free(octet);
ret = GOST_KEY_set_public_key_affine_coordinates(pk->pkey.gost, X, Y);
if (ret == 0)
GOSTerror(ERR_R_EC_LIB);
BN_free(X);
BN_free(Y);
return ret;
}
static int
pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
{
ASN1_OBJECT *algobj = NULL;
ASN1_OCTET_STRING *octet = NULL;
ASN1_STRING *params = NULL;
void *pval = NULL;
unsigned char *buf = NULL, *sptr;
int key_size, ret = 0;
const EC_POINT *pub_key;
BIGNUM *X = NULL, *Y = NULL;
const GOST_KEY *ec = pk->pkey.gost;
int ptype = V_ASN1_UNDEF;
algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec)));
if (pk->save_parameters) {
params = encode_gost01_algor_params(pk);
if (params == NULL)
return 0;
pval = params;
ptype = V_ASN1_SEQUENCE;
}
key_size = GOST_KEY_get_size(ec);
pub_key = GOST_KEY_get0_public_key(ec);
if (pub_key == NULL) {
GOSTerror(GOST_R_PUBLIC_KEY_UNDEFINED);
goto err;
}
octet = ASN1_OCTET_STRING_new();
if (octet == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
goto err;
}
ret = ASN1_STRING_set(octet, NULL, 2 * key_size);
if (ret == 0) {
GOSTerror(ERR_R_INTERNAL_ERROR);
goto err;
}
sptr = ASN1_STRING_data(octet);
X = BN_new();
Y = BN_new();
if (X == NULL || Y == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
goto err;
}
if (EC_POINT_get_affine_coordinates(GOST_KEY_get0_group(ec),
pub_key, X, Y, NULL) == 0) {
GOSTerror(ERR_R_EC_LIB);
goto err;
}
GOST_bn2le(X, sptr, key_size);
GOST_bn2le(Y, sptr + key_size, key_size);
BN_free(Y);
BN_free(X);
ret = i2d_ASN1_OCTET_STRING(octet, &buf);
ASN1_BIT_STRING_free(octet);
if (ret < 0)
return 0;
return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
err:
BN_free(Y);
BN_free(X);
ASN1_BIT_STRING_free(octet);
ASN1_STRING_free(params);
return 0;
}
static int
param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
{
int param_nid =
EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
if (BIO_indent(out, indent, 128) == 0)
return 0;
BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
if (BIO_indent(out, indent, 128) == 0)
return 0;
BIO_printf(out, "Digest Algorithm: %s\n",
OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost)));
return 1;
}
static int
pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
{
BN_CTX *ctx = BN_CTX_new();
BIGNUM *X, *Y;
const EC_POINT *pubkey;
const EC_GROUP *group;
if (ctx == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
BN_CTX_start(ctx);
if ((X = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Y = BN_CTX_get(ctx)) == NULL)
goto err;
pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost);
group = GOST_KEY_get0_group(pkey->pkey.gost);
if (EC_POINT_get_affine_coordinates(group, pubkey, X, Y, ctx) == 0) {
GOSTerror(ERR_R_EC_LIB);
goto err;
}
if (BIO_indent(out, indent, 128) == 0)
goto err;
BIO_printf(out, "Public key:\n");
if (BIO_indent(out, indent + 3, 128) == 0)
goto err;
BIO_printf(out, "X:");
BN_print(out, X);
BIO_printf(out, "\n");
if (BIO_indent(out, indent + 3, 128) == 0)
goto err;
BIO_printf(out, "Y:");
BN_print(out, Y);
BIO_printf(out, "\n");
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return param_print_gost01(out, pkey, indent, pctx);
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return 0;
}
static int
priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
{
const BIGNUM *key;
if (BIO_indent(out, indent, 128) == 0)
return 0;
BIO_printf(out, "Private key: ");
key = GOST_KEY_get0_private_key(pkey->pkey.gost);
if (key == NULL)
BIO_printf(out, "<undefined)");
else
BN_print(out, key);
BIO_printf(out, "\n");
return pub_print_gost01(out, pkey, indent, pctx);
}
static int
priv_decode_gost01(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf)
{
const unsigned char *pkey_buf = NULL, *p = NULL;
int priv_len = 0;
BIGNUM *pk_num = NULL;
int ret = 0;
const X509_ALGOR *palg = NULL;
const ASN1_OBJECT *palg_obj = NULL;
ASN1_INTEGER *priv_key = NULL;
GOST_KEY *ec;
int ptype = V_ASN1_UNDEF;
ASN1_STRING *pval = NULL;
if (PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf) == 0) {
GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
return 0;
}
(void)EVP_PKEY_assign_GOST(pk, NULL);
X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
if (ptype != V_ASN1_SEQUENCE) {
GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
return 0;
}
p = pval->data;
if (decode_gost01_algor_params(pk, &p, pval->length) == 0) {
GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
return 0;
}
p = pkey_buf;
if (V_ASN1_OCTET_STRING == *p) {
/* New format - Little endian octet string */
ASN1_OCTET_STRING *s =
d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
if (s == NULL) {
GOSTerror(EVP_R_DECODE_ERROR);
ASN1_STRING_free(s);
return 0;
}
pk_num = GOST_le2bn(s->data, s->length, NULL);
ASN1_STRING_free(s);
} else {
priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
if (priv_key == NULL)
return 0;
ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
ASN1_INTEGER_free(priv_key);
if (ret == 0) {
GOSTerror(EVP_R_DECODE_ERROR);
return 0;
}
}
ec = pk->pkey.gost;
if (ec == NULL) {
ec = GOST_KEY_new();
if (ec == NULL) {
BN_free(pk_num);
return 0;
}
if (EVP_PKEY_assign_GOST(pk, ec) == 0) {
BN_free(pk_num);
GOST_KEY_free(ec);
return 0;
}
}
if (GOST_KEY_set_private_key(ec, pk_num) == 0) {
BN_free(pk_num);
return 0;
}
ret = 0;
if (EVP_PKEY_missing_parameters(pk) == 0)
ret = gost2001_compute_public(ec) != 0;
BN_free(pk_num);
return ret;
}
static int
priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
{
ASN1_OBJECT *algobj =
OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost)));
ASN1_STRING *params = encode_gost01_algor_params(pk);
unsigned char *priv_buf = NULL;
int priv_len;
ASN1_INTEGER *asn1key = NULL;
if (params == NULL)
return 0;
asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost),
NULL);
if (asn1key == NULL) {
ASN1_STRING_free(params);
return 0;
}
priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
ASN1_INTEGER_free(asn1key);
return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf,
priv_len);
}
static int
param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder)
{
ASN1_STRING *params = encode_gost01_algor_params(pkey);
int len;
if (params == NULL)
return 0;
len = params->length;
if (pder != NULL)
memcpy(*pder, params->data, params->length);
ASN1_STRING_free(params);
return len;
}
static int
param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
{
ASN1_OBJECT *obj = NULL;
int nid;
GOST_KEY *ec;
EC_GROUP *group;
int ret;
/* New format */
if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder)
return decode_gost01_algor_params(pkey, pder, derlen);
/* Compatibility */
if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
nid = OBJ_obj2nid(obj);
ASN1_OBJECT_free(obj);
ec = GOST_KEY_new();
if (ec == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
group = EC_GROUP_new_by_curve_name(nid);
if (group == NULL) {
GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
GOST_KEY_free(ec);
return 0;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
if (GOST_KEY_set_group(ec, group) == 0) {
GOSTerror(ERR_R_EC_LIB);
EC_GROUP_free(group);
GOST_KEY_free(ec);
return 0;
}
EC_GROUP_free(group);
if (GOST_KEY_set_digest(ec,
NID_id_GostR3411_94_CryptoProParamSet) == 0) {
GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
GOST_KEY_free(ec);
return 0;
}
ret = EVP_PKEY_assign_GOST(pkey, ec);
if (ret == 0)
GOST_KEY_free(ec);
return ret;
}
static int
param_missing_gost01(const EVP_PKEY *pk)
{
const GOST_KEY *ec = pk->pkey.gost;
if (ec == NULL)
return 1;
if (GOST_KEY_get0_group(ec) == NULL)
return 1;
if (GOST_KEY_get_digest(ec) == NID_undef)
return 1;
return 0;
}
static int
param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
{
GOST_KEY *eto = to->pkey.gost;
const GOST_KEY *efrom = from->pkey.gost;
int ret = 1;
if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
GOSTerror(GOST_R_INCOMPATIBLE_ALGORITHMS);
return 0;
}
if (efrom == NULL) {
GOSTerror(GOST_R_KEY_PARAMETERS_MISSING);
return 0;
}
if (eto == NULL) {
eto = GOST_KEY_new();
if (eto == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) {
GOST_KEY_free(eto);
return 0;
}
}
GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom));
GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom));
if (GOST_KEY_get0_private_key(eto) != NULL)
ret = gost2001_compute_public(eto);
return ret;
}
static int
param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
{
if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) !=
EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost)))
return 0;
if (GOST_KEY_get_digest(a->pkey.gost) !=
GOST_KEY_get_digest(b->pkey.gost))
return 0;
return 1;
}
static int
pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL;
int digest = GOST_KEY_get_digest(pkey->pkey.gost);
switch (op) {
case ASN1_PKEY_CTRL_PKCS7_SIGN:
if (arg1 == 0)
PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
break;
case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
if (arg1 == 0)
PKCS7_RECIP_INFO_get0_alg(arg2, &alg3);
break;
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
*(int *)arg2 = GostR3410_get_md_digest(digest);
return 2;
default:
return -2;
}
if (alg1)
X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0);
if (alg2)
X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0);
if (alg3) {
ASN1_STRING *params = encode_gost01_algor_params(pkey);
if (params == NULL) {
return -1;
}
X509_ALGOR_set0(alg3,
OBJ_nid2obj(GostR3410_get_pk_digest(digest)),
V_ASN1_SEQUENCE, params);
}
return 1;
}
const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[] = {
{
.pkey_id = EVP_PKEY_GOSTR01,
.pkey_base_id = EVP_PKEY_GOSTR01,
.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
.pem_str = "GOST2001",
.info = "GOST R 34.10-2001",
.pkey_free = pkey_free_gost01,
.pkey_ctrl = pkey_ctrl_gost01,
.priv_decode = priv_decode_gost01,
.priv_encode = priv_encode_gost01,
.priv_print = priv_print_gost01,
.param_decode = param_decode_gost01,
.param_encode = param_encode_gost01,
.param_missing = param_missing_gost01,
.param_copy = param_copy_gost01,
.param_cmp = param_cmp_gost01,
.param_print = param_print_gost01,
.pub_decode = pub_decode_gost01,
.pub_encode = pub_encode_gost01,
.pub_cmp = pub_cmp_gost01,
.pub_print = pub_print_gost01,
.pkey_size = pkey_size_gost01,
.pkey_bits = pkey_bits_gost01,
},
{
.pkey_id = EVP_PKEY_GOSTR12_256,
.pkey_base_id = EVP_PKEY_GOSTR01,
.pkey_flags = ASN1_PKEY_ALIAS
},
{
.pkey_id = EVP_PKEY_GOSTR12_512,
.pkey_base_id = EVP_PKEY_GOSTR01,
.pkey_flags = ASN1_PKEY_ALIAS
},
};
#endif

View File

@@ -0,0 +1,321 @@
/* $OpenBSD: gostr341001_key.c,v 1.12 2023/03/07 09:27:10 jsing Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/gost.h>
#include <openssl/objects.h>
#include "gost_local.h"
struct gost_key_st {
EC_GROUP *group;
EC_POINT *pub_key;
BIGNUM *priv_key;
int references;
int digest_nid;
};
GOST_KEY *
GOST_KEY_new(void)
{
GOST_KEY *ret;
ret = malloc(sizeof(GOST_KEY));
if (ret == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->group = NULL;
ret->pub_key = NULL;
ret->priv_key = NULL;
ret->references = 1;
ret->digest_nid = NID_undef;
return (ret);
}
void
GOST_KEY_free(GOST_KEY *r)
{
int i;
if (r == NULL)
return;
i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC);
if (i > 0)
return;
EC_GROUP_free(r->group);
EC_POINT_free(r->pub_key);
BN_free(r->priv_key);
freezero(r, sizeof(GOST_KEY));
}
int
GOST_KEY_check_key(const GOST_KEY *key)
{
int ok = 0;
BN_CTX *ctx = NULL;
BIGNUM *order = NULL;
EC_POINT *point = NULL;
if (key == NULL || key->group == NULL || key->pub_key == NULL) {
GOSTerror(ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (EC_POINT_is_at_infinity(key->group, key->pub_key) != 0) {
GOSTerror(EC_R_POINT_AT_INFINITY);
goto err;
}
if ((ctx = BN_CTX_new()) == NULL)
goto err;
if ((point = EC_POINT_new(key->group)) == NULL)
goto err;
/* testing whether the pub_key is on the elliptic curve */
if (EC_POINT_is_on_curve(key->group, key->pub_key, ctx) == 0) {
GOSTerror(EC_R_POINT_IS_NOT_ON_CURVE);
goto err;
}
/* testing whether pub_key * order is the point at infinity */
if ((order = BN_new()) == NULL)
goto err;
if (EC_GROUP_get_order(key->group, order, ctx) == 0) {
GOSTerror(EC_R_INVALID_GROUP_ORDER);
goto err;
}
if (EC_POINT_mul(key->group, point, NULL, key->pub_key, order,
ctx) == 0) {
GOSTerror(ERR_R_EC_LIB);
goto err;
}
if (EC_POINT_is_at_infinity(key->group, point) == 0) {
GOSTerror(EC_R_WRONG_ORDER);
goto err;
}
/*
* in case the priv_key is present : check if generator * priv_key ==
* pub_key
*/
if (key->priv_key != NULL) {
if (BN_cmp(key->priv_key, order) >= 0) {
GOSTerror(EC_R_WRONG_ORDER);
goto err;
}
if (EC_POINT_mul(key->group, point, key->priv_key, NULL, NULL,
ctx) == 0) {
GOSTerror(ERR_R_EC_LIB);
goto err;
}
if (EC_POINT_cmp(key->group, point, key->pub_key, ctx) != 0) {
GOSTerror(EC_R_INVALID_PRIVATE_KEY);
goto err;
}
}
ok = 1;
err:
BN_free(order);
BN_CTX_free(ctx);
EC_POINT_free(point);
return (ok);
}
int
GOST_KEY_set_public_key_affine_coordinates(GOST_KEY *key, BIGNUM *x, BIGNUM *y)
{
BN_CTX *ctx = NULL;
BIGNUM *tx, *ty;
EC_POINT *point = NULL;
int ok = 0;
if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
GOSTerror(ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
point = EC_POINT_new(key->group);
if (point == NULL)
goto err;
if ((tx = BN_CTX_get(ctx)) == NULL)
goto err;
if ((ty = BN_CTX_get(ctx)) == NULL)
goto err;
if (EC_POINT_set_affine_coordinates(key->group, point, x, y,
ctx) == 0)
goto err;
if (EC_POINT_get_affine_coordinates(key->group, point, tx, ty,
ctx) == 0)
goto err;
/*
* Check if retrieved coordinates match originals: if not, values are
* out of range.
*/
if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) {
GOSTerror(EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
if (GOST_KEY_set_public_key(key, point) == 0)
goto err;
if (GOST_KEY_check_key(key) == 0)
goto err;
ok = 1;
err:
EC_POINT_free(point);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
const EC_GROUP *
GOST_KEY_get0_group(const GOST_KEY *key)
{
return key->group;
}
int
GOST_KEY_set_group(GOST_KEY *key, const EC_GROUP *group)
{
EC_GROUP_free(key->group);
key->group = EC_GROUP_dup(group);
return (key->group == NULL) ? 0 : 1;
}
const BIGNUM *
GOST_KEY_get0_private_key(const GOST_KEY *key)
{
return key->priv_key;
}
int
GOST_KEY_set_private_key(GOST_KEY *key, const BIGNUM *priv_key)
{
BN_free(key->priv_key);
key->priv_key = BN_dup(priv_key);
return (key->priv_key == NULL) ? 0 : 1;
}
const EC_POINT *
GOST_KEY_get0_public_key(const GOST_KEY *key)
{
return key->pub_key;
}
int
GOST_KEY_set_public_key(GOST_KEY *key, const EC_POINT *pub_key)
{
EC_POINT_free(key->pub_key);
key->pub_key = EC_POINT_dup(pub_key, key->group);
return (key->pub_key == NULL) ? 0 : 1;
}
int
GOST_KEY_get_digest(const GOST_KEY *key)
{
return key->digest_nid;
}
int
GOST_KEY_set_digest(GOST_KEY *key, int digest_nid)
{
if (digest_nid == NID_id_GostR3411_94_CryptoProParamSet ||
digest_nid == NID_id_tc26_gost3411_2012_256 ||
digest_nid == NID_id_tc26_gost3411_2012_512) {
key->digest_nid = digest_nid;
return 1;
}
return 0;
}
size_t
GOST_KEY_get_size(const GOST_KEY *r)
{
int i;
BIGNUM *order = NULL;
const EC_GROUP *group;
if (r == NULL)
return 0;
group = GOST_KEY_get0_group(r);
if (group == NULL)
return 0;
if ((order = BN_new()) == NULL)
return 0;
if (EC_GROUP_get_order(group, order, NULL) == 0) {
BN_free(order);
return 0;
}
i = BN_num_bytes(order);
BN_free(order);
return (i);
}
#endif

View File

@@ -0,0 +1,132 @@
/* $OpenBSD: gostr341001_params.c,v 1.5 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/objects.h>
#include <openssl/gost.h>
#include "gost_local.h"
int
GostR3410_get_md_digest(int nid)
{
if (nid == NID_id_GostR3411_94_CryptoProParamSet)
return NID_id_GostR3411_94;
return nid;
}
int
GostR3410_get_pk_digest(int nid)
{
switch (nid) {
case NID_id_GostR3411_94_CryptoProParamSet:
return NID_id_GostR3410_2001;
case NID_id_tc26_gost3411_2012_256:
return NID_id_tc26_gost3410_2012_256;
case NID_id_tc26_gost3411_2012_512:
return NID_id_tc26_gost3410_2012_512;
default:
return NID_undef;
}
}
typedef struct GostR3410_params {
const char *name;
int nid;
} GostR3410_params;
static const GostR3410_params GostR3410_256_params[] = {
{ "A", NID_id_GostR3410_2001_CryptoPro_A_ParamSet },
{ "B", NID_id_GostR3410_2001_CryptoPro_B_ParamSet },
{ "C", NID_id_GostR3410_2001_CryptoPro_C_ParamSet },
{ "0", NID_id_GostR3410_2001_TestParamSet },
{ "XA", NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet },
{ "XB", NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet },
{ NULL, NID_undef },
};
static const GostR3410_params GostR3410_512_params[] = {
{ "A", NID_id_tc26_gost_3410_12_512_paramSetA },
{ "B", NID_id_tc26_gost_3410_12_512_paramSetB },
{ NULL, NID_undef },
};
int
GostR3410_256_param_id(const char *value)
{
int i;
for (i = 0; GostR3410_256_params[i].nid != NID_undef; i++) {
if (strcasecmp(GostR3410_256_params[i].name, value) == 0)
return GostR3410_256_params[i].nid;
}
return NID_undef;
}
int
GostR3410_512_param_id(const char *value)
{
int i;
for (i = 0; GostR3410_512_params[i].nid != NID_undef; i++) {
if (strcasecmp(GostR3410_512_params[i].name, value) == 0)
return GostR3410_512_params[i].nid;
}
return NID_undef;
}
#endif

View File

@@ -0,0 +1,706 @@
/* $OpenBSD: gostr341001_pmeth.c,v 1.17 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/gost.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/x509.h>
#include "ecs_local.h"
#include "evp_local.h"
#include "gost_local.h"
#include "gost_asn1.h"
static ECDSA_SIG *
unpack_signature_cp(const unsigned char *sig, size_t siglen)
{
ECDSA_SIG *s;
s = ECDSA_SIG_new();
if (s == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
BN_bin2bn(sig, siglen / 2, s->s);
BN_bin2bn(sig + siglen / 2, siglen / 2, s->r);
return s;
}
static int
pack_signature_cp(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
{
int r_len = BN_num_bytes(s->r);
int s_len = BN_num_bytes(s->s);
if (r_len > order || s_len > order)
return 0;
*siglen = 2 * order;
memset(sig, 0, *siglen);
BN_bn2bin(s->s, sig + order - s_len);
BN_bn2bin(s->r, sig + 2 * order - r_len);
ECDSA_SIG_free(s);
return 1;
}
static ECDSA_SIG *
unpack_signature_le(const unsigned char *sig, size_t siglen)
{
ECDSA_SIG *s;
s = ECDSA_SIG_new();
if (s == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return NULL;
}
GOST_le2bn(sig, siglen / 2, s->r);
GOST_le2bn(sig + siglen / 2, siglen / 2, s->s);
return s;
}
static int
pack_signature_le(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
{
*siglen = 2 * order;
memset(sig, 0, *siglen);
GOST_bn2le(s->r, sig, order);
GOST_bn2le(s->s, sig + order, order);
ECDSA_SIG_free(s);
return 1;
}
struct gost_pmeth_data {
int sign_param_nid; /* Should be set whenever parameters are filled */
int digest_nid;
EVP_MD *md;
unsigned char *shared_ukm;
int peer_key_used;
int sig_format;
};
static int
pkey_gost01_init(EVP_PKEY_CTX *ctx)
{
struct gost_pmeth_data *data;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
data = calloc(1, sizeof(struct gost_pmeth_data));
if (data == NULL)
return 0;
if (pkey != NULL && pkey->pkey.gost != NULL) {
data->sign_param_nid =
EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
data->digest_nid = GOST_KEY_get_digest(pkey->pkey.gost);
}
EVP_PKEY_CTX_set_data(ctx, data);
return 1;
}
/* Copies contents of gost_pmeth_data structure */
static int
pkey_gost01_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
struct gost_pmeth_data *dst_data, *src_data;
if (pkey_gost01_init(dst) == 0)
return 0;
src_data = EVP_PKEY_CTX_get_data(src);
dst_data = EVP_PKEY_CTX_get_data(dst);
*dst_data = *src_data;
if (src_data->shared_ukm != NULL)
dst_data->shared_ukm = NULL;
return 1;
}
/* Frees up gost_pmeth_data structure */
static void
pkey_gost01_cleanup(EVP_PKEY_CTX *ctx)
{
struct gost_pmeth_data *data;
if ((data = EVP_PKEY_CTX_get_data(ctx)) == NULL)
return;
free(data->shared_ukm);
free(data);
}
static int
pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
EC_GROUP *group = NULL;
GOST_KEY *gost = NULL;
int ret = 0;
if (data->sign_param_nid == NID_undef ||
data->digest_nid == NID_undef) {
GOSTerror(GOST_R_NO_PARAMETERS_SET);
return 0;
}
group = EC_GROUP_new_by_curve_name(data->sign_param_nid);
if (group == NULL)
goto done;
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
gost = GOST_KEY_new();
if (gost == NULL)
goto done;
if (GOST_KEY_set_digest(gost, data->digest_nid) == 0)
goto done;
if (GOST_KEY_set_group(gost, group) != 0)
ret = EVP_PKEY_assign_GOST(pkey, gost);
done:
if (ret == 0)
GOST_KEY_free(gost);
EC_GROUP_free(group);
return ret;
}
static int
pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
if (pkey_gost01_paramgen(ctx, pkey) == 0)
return 0;
return gost2001_keygen(pkey->pkey.gost) != 0;
}
static int
pkey_gost01_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbs_len)
{
ECDSA_SIG *unpacked_sig = NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
BIGNUM *md;
size_t size;
int ret;
if (pkey == NULL || pkey->pkey.gost == NULL)
return 0;
size = GOST_KEY_get_size(pkey->pkey.gost);
if (siglen == NULL)
return 0;
if (sig == NULL) {
*siglen = 2 * size;
return 1;
} else if (*siglen < 2 * size) {
GOSTerror(EC_R_BUFFER_TOO_SMALL);
return 0;
}
if (tbs_len != 32 && tbs_len != 64) {
GOSTerror(EVP_R_BAD_BLOCK_LENGTH);
return 0;
}
md = GOST_le2bn(tbs, tbs_len, NULL);
if (md == NULL)
return 0;
unpacked_sig = gost2001_do_sign(md, pkey->pkey.gost);
BN_free(md);
if (unpacked_sig == NULL) {
return 0;
}
switch (pctx->sig_format) {
case GOST_SIG_FORMAT_SR_BE:
ret = pack_signature_cp(unpacked_sig, size, sig, siglen);
break;
case GOST_SIG_FORMAT_RS_LE:
ret = pack_signature_le(unpacked_sig, size, sig, siglen);
break;
default:
ret = -1;
break;
}
if (ret <= 0)
ECDSA_SIG_free(unpacked_sig);
return ret;
}
static int
pkey_gost01_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbs_len)
{
int ok = 0;
EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
ECDSA_SIG *s = NULL;
BIGNUM *md;
if (pub_key == NULL)
return 0;
switch (pctx->sig_format) {
case GOST_SIG_FORMAT_SR_BE:
s = unpack_signature_cp(sig, siglen);
break;
case GOST_SIG_FORMAT_RS_LE:
s = unpack_signature_le(sig, siglen);
break;
}
if (s == NULL)
return 0;
md = GOST_le2bn(tbs, tbs_len, NULL);
if (md == NULL)
goto err;
ok = gost2001_do_verify(md, s, pub_key->pkey.gost);
err:
BN_free(md);
ECDSA_SIG_free(s);
return ok;
}
static int
gost01_VKO_key(EVP_PKEY *pub_key, EVP_PKEY *priv_key, const unsigned char *ukm,
unsigned char *key)
{
unsigned char hashbuf[128];
int digest_nid;
int ret = 0;
BN_CTX *ctx = BN_CTX_new();
BIGNUM *UKM, *X, *Y;
if (ctx == NULL)
return 0;
BN_CTX_start(ctx);
if ((UKM = BN_CTX_get(ctx)) == NULL)
goto err;
if ((X = BN_CTX_get(ctx)) == NULL)
goto err;
if ((Y = BN_CTX_get(ctx)) == NULL)
goto err;
GOST_le2bn(ukm, 8, UKM);
digest_nid = GOST_KEY_get_digest(priv_key->pkey.gost);
if (VKO_compute_key(X, Y, pub_key->pkey.gost, priv_key->pkey.gost,
UKM) == 0)
goto err;
switch (digest_nid) {
case NID_id_GostR3411_94_CryptoProParamSet:
GOST_bn2le(X, hashbuf, 32);
GOST_bn2le(Y, hashbuf + 32, 32);
GOSTR341194(hashbuf, 64, key, digest_nid);
ret = 1;
break;
case NID_id_tc26_gost3411_2012_256:
GOST_bn2le(X, hashbuf, 32);
GOST_bn2le(Y, hashbuf + 32, 32);
STREEBOG256(hashbuf, 64, key);
ret = 1;
break;
case NID_id_tc26_gost3411_2012_512:
GOST_bn2le(X, hashbuf, 64);
GOST_bn2le(Y, hashbuf + 64, 64);
STREEBOG256(hashbuf, 128, key);
ret = 1;
break;
default:
ret = -2;
break;
}
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ret;
}
int
pkey_gost01_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len,
const unsigned char *in, size_t in_len)
{
const unsigned char *p = in;
EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
GOST_KEY_TRANSPORT *gkt = NULL;
int ret = 0;
unsigned char wrappedKey[44];
unsigned char sharedKey[32];
EVP_PKEY *eph_key = NULL, *peerkey = NULL;
int nid;
if (key == NULL) {
*key_len = 32;
return 1;
}
gkt = d2i_GOST_KEY_TRANSPORT(NULL, (const unsigned char **)&p, in_len);
if (gkt == NULL) {
GOSTerror(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
return -1;
}
/* If key transport structure contains public key, use it */
eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
if (eph_key != NULL) {
if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0) {
GOSTerror(GOST_R_INCOMPATIBLE_PEER_KEY);
goto err;
}
} else {
/* Set control "public key from client certificate used" */
if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
NULL) <= 0) {
GOSTerror(GOST_R_CTRL_CALL_FAILED);
goto err;
}
}
peerkey = EVP_PKEY_CTX_get0_peerkey(pctx);
if (peerkey == NULL) {
GOSTerror(GOST_R_NO_PEER_KEY);
goto err;
}
nid = OBJ_obj2nid(gkt->key_agreement_info->cipher);
if (gkt->key_agreement_info->eph_iv->length != 8) {
GOSTerror(GOST_R_INVALID_IV_LENGTH);
goto err;
}
memcpy(wrappedKey, gkt->key_agreement_info->eph_iv->data, 8);
if (gkt->key_info->encrypted_key->length != 32) {
GOSTerror(EVP_R_BAD_KEY_LENGTH);
goto err;
}
memcpy(wrappedKey + 8, gkt->key_info->encrypted_key->data, 32);
if (gkt->key_info->imit->length != 4) {
GOSTerror(ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(wrappedKey + 40, gkt->key_info->imit->data, 4);
if (gost01_VKO_key(peerkey, priv, wrappedKey, sharedKey) <= 0)
goto err;
if (gost_key_unwrap_crypto_pro(nid, sharedKey, wrappedKey, key) == 0) {
GOSTerror(GOST_R_ERROR_COMPUTING_SHARED_KEY);
goto err;
}
ret = 1;
err:
EVP_PKEY_free(eph_key);
GOST_KEY_TRANSPORT_free(gkt);
return ret;
}
int
pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
{
/*
* Public key of peer in the ctx field peerkey
* Our private key in the ctx pkey
* ukm is in the algorithm specific context data
*/
EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx);
EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
if (data->shared_ukm == NULL) {
GOSTerror(GOST_R_UKM_NOT_SET);
return 0;
}
if (key == NULL) {
*keylen = 32;
return 32;
}
if (gost01_VKO_key(peer_key, my_key, data->shared_ukm, key) <= 0)
return 0;
*keylen = 32;
return 1;
}
int
pkey_gost01_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len,
const unsigned char *key, size_t key_len)
{
GOST_KEY_TRANSPORT *gkt = NULL;
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
unsigned char ukm[8], shared_key[32], crypted_key[44];
int ret = 0;
int key_is_ephemeral;
EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx);
int nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet;
if (data->shared_ukm != NULL) {
memcpy(ukm, data->shared_ukm, 8);
} else /* if (out != NULL) */ {
arc4random_buf(ukm, 8);
}
/* Check for private key in the peer_key of context */
if (sec_key) {
key_is_ephemeral = 0;
if (GOST_KEY_get0_private_key(sec_key->pkey.gost) == 0) {
GOSTerror(GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR);
goto err;
}
} else {
key_is_ephemeral = 1;
if (out != NULL) {
GOST_KEY *tmp_key;
sec_key = EVP_PKEY_new();
if (sec_key == NULL)
goto err;
tmp_key = GOST_KEY_new();
if (tmp_key == NULL)
goto err;
if (EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk),
tmp_key) == 0) {
GOST_KEY_free(tmp_key);
goto err;
}
if (EVP_PKEY_copy_parameters(sec_key, pubk) == 0)
goto err;
if (gost2001_keygen(sec_key->pkey.gost) == 0) {
goto err;
}
}
}
if (out != NULL) {
if (gost01_VKO_key(pubk, sec_key, ukm, shared_key) <= 0)
goto err;
gost_key_wrap_crypto_pro(nid, shared_key, ukm, key,
crypted_key);
}
gkt = GOST_KEY_TRANSPORT_new();
if (gkt == NULL)
goto err;
if (ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8) == 0)
goto err;
if (ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40,
4) == 0)
goto err;
if (ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key, crypted_key + 8,
32) == 0)
goto err;
if (key_is_ephemeral) {
if (X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,
out != NULL ? sec_key : pubk) == 0) {
GOSTerror(GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
goto err;
}
}
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(nid);
if (key_is_ephemeral)
EVP_PKEY_free(sec_key);
else {
/* Set control "public key from client certificate used" */
if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
NULL) <= 0) {
GOSTerror(GOST_R_CTRL_CALL_FAILED);
goto err;
}
}
if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL)) > 0)
ret = 1;
GOST_KEY_TRANSPORT_free(gkt);
return ret;
err:
if (key_is_ephemeral)
EVP_PKEY_free(sec_key);
GOST_KEY_TRANSPORT_free(gkt);
return -1;
}
static int
pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
switch (type) {
case EVP_PKEY_CTRL_MD:
if (EVP_MD_type(p2) !=
GostR3410_get_md_digest(pctx->digest_nid)) {
GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
return 0;
}
pctx->md = p2;
return 1;
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
case EVP_PKEY_CTRL_PKCS7_SIGN:
case EVP_PKEY_CTRL_DIGESTINIT:
return 1;
case EVP_PKEY_CTRL_GOST_PARAMSET:
pctx->sign_param_nid = (int)p1;
return 1;
case EVP_PKEY_CTRL_SET_IV:
{
char *ukm = malloc(p1);
if (ukm == NULL) {
GOSTerror(ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(ukm, p2, p1);
free(pctx->shared_ukm);
pctx->shared_ukm = ukm;
return 1;
}
case EVP_PKEY_CTRL_PEER_KEY:
if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */
return 1;
if (p1 == 2) /* TLS: peer key used? */
return pctx->peer_key_used;
if (p1 == 3) /* TLS: peer key used! */
return (pctx->peer_key_used = 1);
return -2;
case EVP_PKEY_CTRL_GOST_SIG_FORMAT:
switch (p1) {
case GOST_SIG_FORMAT_SR_BE:
case GOST_SIG_FORMAT_RS_LE:
pctx->sig_format = p1;
return 1;
default:
return 0;
}
break;
case EVP_PKEY_CTRL_GOST_SET_DIGEST:
pctx->digest_nid = (int)p1;
return 1;
case EVP_PKEY_CTRL_GOST_GET_DIGEST:
*(int *)p2 = pctx->digest_nid;
return 1;
default:
return -2;
}
}
static int
pkey_gost01_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
{
int param_nid = NID_undef;
int digest_nid = NID_undef;
if (strcmp(type, "paramset") == 0) {
if (value == NULL)
return 0;
if (pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_GET_DIGEST, 0,
&digest_nid) == 0)
return 0;
if (digest_nid == NID_id_tc26_gost3411_2012_512)
param_nid = GostR3410_512_param_id(value);
else
param_nid = GostR3410_256_param_id(value);
if (param_nid == NID_undef)
param_nid = OBJ_txt2nid(value);
if (param_nid == NID_undef)
return 0;
return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
param_nid, NULL);
}
if (strcmp(type, "dgst") == 0) {
if (value == NULL)
return 0;
else if (strcmp(value, "gost94") == 0 ||
strcmp(value, "md_gost94") == 0)
digest_nid = NID_id_GostR3411_94_CryptoProParamSet;
else if (strcmp(value, "streebog256") == 0)
digest_nid = NID_id_tc26_gost3411_2012_256;
else if (strcmp(value, "streebog512") == 0)
digest_nid = NID_id_tc26_gost3411_2012_512;
if (digest_nid == NID_undef)
return 0;
return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_SET_DIGEST,
digest_nid, NULL);
}
return -2;
}
const EVP_PKEY_METHOD gostr01_pkey_meth = {
.pkey_id = EVP_PKEY_GOSTR01,
.init = pkey_gost01_init,
.copy = pkey_gost01_copy,
.cleanup = pkey_gost01_cleanup,
.paramgen = pkey_gost01_paramgen,
.keygen = pkey_gost01_keygen,
.sign = pkey_gost01_sign,
.verify = pkey_gost01_verify,
.encrypt = pkey_gost01_encrypt,
.decrypt = pkey_gost01_decrypt,
.derive = pkey_gost01_derive,
.ctrl = pkey_gost01_ctrl,
.ctrl_str = pkey_gost01_ctrl_str,
};
#endif

273
crypto/gost/gostr341194.c Normal file
View File

@@ -0,0 +1,273 @@
/* $OpenBSD: gostr341194.c,v 1.6 2022/11/26 16:08:53 tb Exp $ */
/*
* Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Copyright (c) 2005-2006 Cryptocom LTD
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <string.h>
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_GOST
#include <openssl/crypto.h>
#include <openssl/objects.h>
#include <openssl/gost.h>
#include "gost_local.h"
/* Following functions are various bit meshing routines used in
* GOST R 34.11-94 algorithms */
static void
swap_bytes(unsigned char *w, unsigned char *k)
{
int i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 8; j++)
k[i + 4 * j] = w[8 * i + j];
}
/* was A_A */
static void
circle_xor8(const unsigned char *w, unsigned char *k)
{
unsigned char buf[8];
int i;
memcpy(buf, w, 8);
memmove(k, w + 8, 24);
for (i = 0; i < 8; i++)
k[i + 24] = buf[i] ^ k[i];
}
/* was R_R */
static void
transform_3(unsigned char *data)
{
unsigned short int acc;
acc = (data[0] ^ data[2] ^ data[4] ^ data[6] ^ data[24] ^ data[30]) |
((data[1] ^ data[3] ^ data[5] ^ data[7] ^ data[25] ^ data[31]) << 8);
memmove(data, data + 2, 30);
data[30] = acc & 0xff;
data[31] = acc >> 8;
}
/* Adds blocks of N bytes modulo 2**(8*n). Returns carry*/
static int
add_blocks(int n, unsigned char *left, const unsigned char *right)
{
int i;
int carry = 0;
int sum;
for (i = 0; i < n; i++) {
sum = (int)left[i] + (int)right[i] + carry;
left[i] = sum & 0xff;
carry = sum >> 8;
}
return carry;
}
/* Xor two sequences of bytes */
static void
xor_blocks(unsigned char *result, const unsigned char *a,
const unsigned char *b, size_t len)
{
size_t i;
for (i = 0; i < len; i++)
result[i] = a[i] ^ b[i];
}
/*
* Calculate H(i+1) = Hash(Hi,Mi)
* Where H and M are 32 bytes long
*/
static int
hash_step(GOSTR341194_CTX *c, unsigned char *H, const unsigned char *M)
{
unsigned char U[32], W[32], V[32], S[32], Key[32];
int i;
/* Compute first key */
xor_blocks(W, H, M, 32);
swap_bytes(W, Key);
/* Encrypt first 8 bytes of H with first key */
Gost2814789_set_key(&c->cipher, Key, 256);
Gost2814789_encrypt(H, S, &c->cipher);
/* Compute second key */
circle_xor8(H, U);
circle_xor8(M, V);
circle_xor8(V, V);
xor_blocks(W, U, V, 32);
swap_bytes(W, Key);
/* encrypt second 8 bytes of H with second key */
Gost2814789_set_key(&c->cipher, Key, 256);
Gost2814789_encrypt(H+8, S+8, &c->cipher);
/* compute third key */
circle_xor8(U, U);
U[31] = ~U[31];
U[29] = ~U[29];
U[28] = ~U[28];
U[24] = ~U[24];
U[23] = ~U[23];
U[20] = ~U[20];
U[18] = ~U[18];
U[17] = ~U[17];
U[14] = ~U[14];
U[12] = ~U[12];
U[10] = ~U[10];
U[8] = ~U[8];
U[7] = ~U[7];
U[5] = ~U[5];
U[3] = ~U[3];
U[1] = ~U[1];
circle_xor8(V, V);
circle_xor8(V, V);
xor_blocks(W, U, V, 32);
swap_bytes(W, Key);
/* encrypt third 8 bytes of H with third key */
Gost2814789_set_key(&c->cipher, Key, 256);
Gost2814789_encrypt(H+16, S+16, &c->cipher);
/* Compute fourth key */
circle_xor8(U, U);
circle_xor8(V, V);
circle_xor8(V, V);
xor_blocks(W, U, V, 32);
swap_bytes(W, Key);
/* Encrypt last 8 bytes with fourth key */
Gost2814789_set_key(&c->cipher, Key, 256);
Gost2814789_encrypt(H+24, S+24, &c->cipher);
for (i = 0; i < 12; i++)
transform_3(S);
xor_blocks(S, S, M, 32);
transform_3(S);
xor_blocks(S, S, H, 32);
for (i = 0; i < 61; i++)
transform_3(S);
memcpy(H, S, 32);
return 1;
}
int
GOSTR341194_Init(GOSTR341194_CTX *c, int nid)
{
memset(c, 0, sizeof(*c));
return Gost2814789_set_sbox(&c->cipher, nid);
}
static void
GOSTR341194_block_data_order(GOSTR341194_CTX *ctx, const unsigned char *p,
size_t num)
{
int i;
for (i = 0; i < num; i++) {
hash_step(ctx, ctx->H, p);
add_blocks(32, ctx->S, p);
p += 32;
}
}
#define DATA_ORDER_IS_LITTLE_ENDIAN
#define HASH_CBLOCK GOSTR341194_CBLOCK
#define HASH_LONG GOSTR341194_LONG
#define HASH_CTX GOSTR341194_CTX
#define HASH_UPDATE GOSTR341194_Update
#define HASH_TRANSFORM GOSTR341194_Transform
#define HASH_NO_FINAL 1
#define HASH_BLOCK_DATA_ORDER GOSTR341194_block_data_order
#include "md32_common.h"
int
GOSTR341194_Final(unsigned char *md, GOSTR341194_CTX * c)
{
unsigned char *p = (unsigned char *)c->data;
unsigned char T[32];
if (c->num > 0) {
memset(p + c->num, 0, 32 - c->num);
hash_step(c, c->H, p);
add_blocks(32, c->S, p);
}
p = T;
HOST_l2c(c->Nl, p);
HOST_l2c(c->Nh, p);
memset(p, 0, 32 - 8);
hash_step(c, c->H, T);
hash_step(c, c->H, c->S);
memcpy(md, c->H, 32);
return 1;
}
unsigned char *
GOSTR341194(const unsigned char *d, size_t n, unsigned char *md, int nid)
{
GOSTR341194_CTX c;
static unsigned char m[GOSTR341194_LENGTH];
if (md == NULL)
md = m;
if (!GOSTR341194_Init(&c, nid))
return 0;
GOSTR341194_Update(&c, d, n);
GOSTR341194_Final(md, &c);
explicit_bzero(&c, sizeof(c));
return (md);
}
#endif

1478
crypto/gost/streebog.c Normal file

File diff suppressed because it is too large Load Diff