check in v3.8.0 source
This commit is contained in:
472
crypto/gost/gost2814789.c
Normal file
472
crypto/gost/gost2814789.c
Normal 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
|
138
crypto/gost/gost89_keywrap.c
Normal file
138
crypto/gost/gost89_keywrap.c
Normal 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
244
crypto/gost/gost89_params.c
Normal 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
|
89
crypto/gost/gost89imit_ameth.c
Normal file
89
crypto/gost/gost89imit_ameth.c
Normal 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
|
248
crypto/gost/gost89imit_pmeth.c
Normal file
248
crypto/gost/gost89imit_pmeth.c
Normal 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
295
crypto/gost/gost_asn1.c
Normal 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
107
crypto/gost/gost_asn1.h
Normal 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
105
crypto/gost/gost_err.c
Normal 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
117
crypto/gost/gost_local.h
Normal 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
403
crypto/gost/gostr341001.c
Normal 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
|
721
crypto/gost/gostr341001_ameth.c
Normal file
721
crypto/gost/gostr341001_ameth.c
Normal 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, ¶ms->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
|
321
crypto/gost/gostr341001_key.c
Normal file
321
crypto/gost/gostr341001_key.c
Normal 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
|
132
crypto/gost/gostr341001_params.c
Normal file
132
crypto/gost/gostr341001_params.c
Normal 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
|
706
crypto/gost/gostr341001_pmeth.c
Normal file
706
crypto/gost/gostr341001_pmeth.c
Normal 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
273
crypto/gost/gostr341194.c
Normal 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
1478
crypto/gost/streebog.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user