1 /* $OpenBSD: gost89_keywrap.c,v 1.3 2014/11/09 19:28:44 miod Exp $ */
2 /*
3  * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
4  * Copyright (c) 2005-2006 Cryptocom LTD
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. All advertising materials mentioning features or use of this
19  *    software must display the following acknowledgment:
20  *    "This product includes software developed by the OpenSSL Project
21  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
22  *
23  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
24  *    endorse or promote products derived from this software without
25  *    prior written permission. For written permission, please contact
26  *    openssl-core@openssl.org.
27  *
28  * 5. Products derived from this software may not be called "OpenSSL"
29  *    nor may "OpenSSL" appear in their names without prior written
30  *    permission of the OpenSSL Project.
31  *
32  * 6. Redistributions of any form whatsoever must retain the following
33  *    acknowledgment:
34  *    "This product includes software developed by the OpenSSL Project
35  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
38  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48  * OF THE POSSIBILITY OF SUCH DAMAGE.
49  * ====================================================================
50  */
51 
52 #include <string.h>
53 
54 #include <openssl/opensslconf.h>
55 
56 #ifndef OPENSSL_NO_GOST
57 
58 #include <openssl/gost.h>
59 
60 #include "gost_locl.h"
61 
62 static void
key_diversify_crypto_pro(GOST2814789_KEY * ctx,const unsigned char * inputKey,const unsigned char * ukm,unsigned char * outputKey)63 key_diversify_crypto_pro(GOST2814789_KEY *ctx, const unsigned char *inputKey,
64     const unsigned char *ukm, unsigned char *outputKey)
65 {
66 	unsigned long k, s1, s2;
67 	int i, mask;
68 	unsigned char S[8];
69 	unsigned char *p;
70 
71 	memcpy(outputKey, inputKey, 32);
72 	for (i = 0; i < 8; i++) {
73 		/* Make array of integers from key */
74 		/* Compute IV S */
75 		s1 = 0, s2 = 0;
76 		p = outputKey;
77 		for (mask = 1; mask < 256; mask <<= 1) {
78 			c2l(p, k);
79 			if (mask & ukm[i]) {
80 				s1 += k;
81 			} else {
82 				s2 += k;
83 			}
84 		}
85 		p = S;
86 		l2c (s1, p);
87 		l2c (s2, p);
88 		Gost2814789_set_key(ctx, outputKey, 256);
89 		mask = 0;
90 		Gost2814789_cfb64_encrypt(outputKey, outputKey, 32, ctx, S,
91 		    &mask, 1);
92 	}
93 }
94 
95 int
gost_key_wrap_crypto_pro(int nid,const unsigned char * keyExchangeKey,const unsigned char * ukm,const unsigned char * sessionKey,unsigned char * wrappedKey)96 gost_key_wrap_crypto_pro(int nid, const unsigned char *keyExchangeKey,
97     const unsigned char *ukm, const unsigned char *sessionKey,
98     unsigned char *wrappedKey)
99 {
100 	GOST2814789_KEY ctx;
101 	unsigned char kek_ukm[32];
102 
103 	Gost2814789_set_sbox(&ctx, nid);
104 	key_diversify_crypto_pro(&ctx, keyExchangeKey, ukm, kek_ukm);
105 	Gost2814789_set_key(&ctx, kek_ukm, 256);
106 	memcpy(wrappedKey, ukm, 8);
107 	Gost2814789_encrypt(sessionKey +  0, wrappedKey + 8 +  0, &ctx);
108 	Gost2814789_encrypt(sessionKey +  8, wrappedKey + 8 +  8, &ctx);
109 	Gost2814789_encrypt(sessionKey + 16, wrappedKey + 8 + 16, &ctx);
110 	Gost2814789_encrypt(sessionKey + 24, wrappedKey + 8 + 24, &ctx);
111 	GOST2814789IMIT(sessionKey, 32, wrappedKey + 40, nid, kek_ukm, ukm);
112 	return 1;
113 }
114 
115 int
gost_key_unwrap_crypto_pro(int nid,const unsigned char * keyExchangeKey,const unsigned char * wrappedKey,unsigned char * sessionKey)116 gost_key_unwrap_crypto_pro(int nid, const unsigned char *keyExchangeKey,
117     const unsigned char *wrappedKey, unsigned char *sessionKey)
118 {
119 	unsigned char kek_ukm[32], cek_mac[4];
120 	GOST2814789_KEY ctx;
121 
122 	Gost2814789_set_sbox(&ctx, nid);
123 	/* First 8 bytes of wrapped Key is ukm */
124 	key_diversify_crypto_pro(&ctx, keyExchangeKey, wrappedKey, kek_ukm);
125 	Gost2814789_set_key(&ctx, kek_ukm, 256);
126 	Gost2814789_decrypt(wrappedKey + 8 +  0, sessionKey +  0, &ctx);
127 	Gost2814789_decrypt(wrappedKey + 8 +  8, sessionKey +  8, &ctx);
128 	Gost2814789_decrypt(wrappedKey + 8 + 16, sessionKey + 16, &ctx);
129 	Gost2814789_decrypt(wrappedKey + 8 + 24, sessionKey + 24, &ctx);
130 
131 	GOST2814789IMIT(sessionKey, 32, cek_mac, nid, kek_ukm, wrappedKey);
132 	if (memcmp(cek_mac, wrappedKey + 40, 4))
133 		return 0;
134 
135 	return 1;
136 }
137 
138 #endif
139