1123870Sume/* crypto/aes/aes_wrap.c */
2121748Sume/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3121748Sume * project.
4121748Sume */
5121748Sume/* ====================================================================
6121748Sume * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
7121748Sume *
8121748Sume * Redistribution and use in source and binary forms, with or without
9121748Sume * modification, are permitted provided that the following conditions
10121748Sume * are met:
11121748Sume *
12121748Sume * 1. Redistributions of source code must retain the above copyright
13121748Sume *    notice, this list of conditions and the following disclaimer.
14121748Sume *
15121748Sume * 2. Redistributions in binary form must reproduce the above copyright
16121748Sume *    notice, this list of conditions and the following disclaimer in
17121748Sume *    the documentation and/or other materials provided with the
18121748Sume *    distribution.
19121748Sume *
20121748Sume * 3. All advertising materials mentioning features or use of this
21121748Sume *    software must display the following acknowledgment:
22121748Sume *    "This product includes software developed by the OpenSSL Project
23121748Sume *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24121748Sume *
25121748Sume * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26121748Sume *    endorse or promote products derived from this software without
27121748Sume *    prior written permission. For written permission, please contact
28121748Sume *    licensing@OpenSSL.org.
29121748Sume *
30121748Sume * 5. Products derived from this software may not be called "OpenSSL"
31121748Sume *    nor may "OpenSSL" appear in their names without prior written
32121748Sume *    permission of the OpenSSL Project.
33121748Sume *
34121748Sume * 6. Redistributions of any form whatsoever must retain the following
35121748Sume *    acknowledgment:
36121748Sume *    "This product includes software developed by the OpenSSL Project
37121748Sume *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38121748Sume *
39121748Sume * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40121748Sume * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41121748Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42121748Sume * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43121748Sume * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44121748Sume * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45121748Sume * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46121748Sume * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47121748Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48121748Sume * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49121748Sume * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50121748Sume * OF THE POSSIBILITY OF SUCH DAMAGE.
51121748Sume * ====================================================================
52121748Sume */
53121748Sume
54121748Sume#include <openssl/local/cryptlib.h>
55121748Sume#include <openssl/aes.h>
56121748Sume#include <openssl/bio.h>
57121748Sume
58121748Sumestatic const unsigned char default_iv[] = {
59121748Sume  0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
60121748Sume};
61121748Sume
62241737Sedint AES_wrap_key(AES_KEY *key, const unsigned char *iv,
63121748Sume		unsigned char *out,
64173412Skevlo		const unsigned char *in, unsigned int inlen)
65173412Skevlo	{
66173412Skevlo	unsigned char *A, B[16], *R;
67173412Skevlo	unsigned int i, j, t;
68173412Skevlo	if ((inlen & 0x7) || (inlen < 8))
69173412Skevlo		return -1;
70173412Skevlo	A = B;
71173412Skevlo	t = 1;
72173412Skevlo	memcpy(out + 8, in, inlen);
73173412Skevlo	if (!iv)
74241134Seadler		iv = default_iv;
75121748Sume
76121748Sume	memcpy(A, iv, 8);
77241134Seadler
78121748Sume	for (j = 0; j < 6; j++)
79121748Sume		{
80121748Sume		R = out + 8;
81121748Sume		for (i = 0; i < inlen; i += 8, t++, R += 8)
82121748Sume			{
83121748Sume			memcpy(B + 8, R, 8);
84121748Sume			AES_encrypt(B, B, key);
85121748Sume			A[7] ^= (unsigned char)(t & 0xff);
86121748Sume			if (t > 0xff)
87121748Sume				{
88123714Ssuz				A[6] ^= (unsigned char)((t >> 8) & 0xff);
89121748Sume				A[5] ^= (unsigned char)((t >> 16) & 0xff);
90121748Sume				A[4] ^= (unsigned char)((t >> 24) & 0xff);
91121748Sume				}
92121748Sume			memcpy(R, B + 8, 8);
93121748Sume			}
94121748Sume		}
95121748Sume	memcpy(out, A, 8);
96121748Sume	return inlen + 8;
97121748Sume	}
98121748Sume
99121748Sumeint AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
100121748Sume		unsigned char *out,
101121748Sume		const unsigned char *in, unsigned int inlen)
102121748Sume	{
103121748Sume	unsigned char *A, B[16], *R;
104121748Sume	unsigned int i, j, t;
105121748Sume	inlen -= 8;
106121748Sume	if (inlen & 0x7)
107121748Sume		return -1;
108241134Seadler	if (inlen < 8)
109121748Sume		return -1;
110121748Sume	A = B;
111121748Sume	t =  6 * (inlen >> 3);
112241134Seadler	memcpy(A, in, 8);
113121748Sume	memcpy(out, in + 8, inlen);
114121748Sume	for (j = 0; j < 6; j++)
115121748Sume		{
116121748Sume		R = out + inlen - 8;
117121748Sume		for (i = 0; i < inlen; i += 8, t--, R -= 8)
118121748Sume			{
119123870Sume			A[7] ^= (unsigned char)(t & 0xff);
120123870Sume			if (t > 0xff)
121123870Sume				{
122123870Sume				A[6] ^= (unsigned char)((t >> 8) & 0xff);
123121748Sume				A[5] ^= (unsigned char)((t >> 16) & 0xff);
124121748Sume				A[4] ^= (unsigned char)((t >> 24) & 0xff);
125121748Sume				}
126121748Sume			memcpy(B + 8, R, 8);
127121748Sume			AES_decrypt(B, B, key);
128121748Sume			memcpy(R, B + 8, 8);
129121748Sume			}
130121748Sume		}
131121748Sume	if (!iv)
132241134Seadler		iv = default_iv;
133241134Seadler	if (memcmp(A, iv, 8))
134121748Sume		{
135121748Sume		OPENSSL_cleanse(out, inlen);
136121748Sume		return 0;
137121748Sume		}
138121748Sume	return inlen;
139121748Sume	}
140121748Sume
141121748Sume#ifdef AES_WRAP_TEST
142121748Sume
143121748Sumeint AES_wrap_unwrap_test(const unsigned char *kek, int keybits,
144121748Sume			 const unsigned char *iv,
145121748Sume			 const unsigned char *eout,
146241134Seadler			 const unsigned char *key, int keylen)
147121748Sume	{
148121748Sume	unsigned char *otmp = NULL, *ptmp = NULL;
149121748Sume	int r, ret = 0;
150121748Sume	AES_KEY wctx;
151121748Sume	otmp = OPENSSL_malloc(keylen + 8);
152121748Sume	ptmp = OPENSSL_malloc(keylen);
153121748Sume	if (!otmp || !ptmp)
154121748Sume		return 0;
155121748Sume	if (AES_set_encrypt_key(kek, keybits, &wctx))
156121748Sume		goto err;
157121748Sume	r = AES_wrap_key(&wctx, iv, otmp, key, keylen);
158121748Sume	if (r <= 0)
159121748Sume		goto err;
160121748Sume
161121748Sume	if (eout && memcmp(eout, otmp, keylen))
162121748Sume		goto err;
163121748Sume
164121748Sume	if (AES_set_decrypt_key(kek, keybits, &wctx))
165121748Sume		goto err;
166121748Sume	r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r);
167121748Sume
168121748Sume	if (memcmp(key, ptmp, keylen))
169121748Sume		goto err;
170121748Sume
171121748Sume	ret = 1;
172121748Sume
173121748Sume	err:
174121748Sume	if (otmp)
175121748Sume		OPENSSL_free(otmp);
176121748Sume	if (ptmp)
177121748Sume		OPENSSL_free(ptmp);
178121748Sume
179121748Sume	return ret;
180121748Sume
181121748Sume	}
182121748Sume
183121748Sume
184121748Sume
185121748Sumeint main(int argc, char **argv)
186121748Sume{
187121748Sume
188121748Sumestatic const unsigned char kek[] = {
189121748Sume  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
190121748Sume  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
191121748Sume  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
192121748Sume  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
193121748Sume};
194121748Sume
195121748Sumestatic const unsigned char key[] = {
196121748Sume  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
197121748Sume  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
198121748Sume  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
199121748Sume  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
200121748Sume};
201121748Sume
202241134Seadlerstatic const unsigned char e1[] = {
203121748Sume  0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47,
204121748Sume  0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82,
205121748Sume  0x9d, 0x3e, 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5
206121748Sume};
207121748Sume
208121748Sumestatic const unsigned char e2[] = {
209121748Sume  0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35,
210121748Sume  0xf9, 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2,
211121748Sume  0x46, 0x8a, 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d
212121748Sume};
213121748Sume
214121748Sumestatic const unsigned char e3[] = {
215121748Sume  0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2,
216121748Sume  0x63, 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a,
217121748Sume  0x93, 0xc8, 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7
218121748Sume};
219121748Sume
220121748Sumestatic const unsigned char e4[] = {
221121748Sume  0x03, 0x1d, 0x33, 0x26, 0x4e, 0x15, 0xd3, 0x32,
222121748Sume  0x68, 0xf2, 0x4e, 0xc2, 0x60, 0x74, 0x3e, 0xdc,
223121748Sume  0xe1, 0xc6, 0xc7, 0xdd, 0xee, 0x72, 0x5a, 0x93,
224121748Sume  0x6b, 0xa8, 0x14, 0x91, 0x5c, 0x67, 0x62, 0xd2
225121748Sume};
226121748Sume
227121748Sumestatic const unsigned char e5[] = {
228121748Sume  0xa8, 0xf9, 0xbc, 0x16, 0x12, 0xc6, 0x8b, 0x3f,
229121748Sume  0xf6, 0xe6, 0xf4, 0xfb, 0xe3, 0x0e, 0x71, 0xe4,
230121748Sume  0x76, 0x9c, 0x8b, 0x80, 0xa3, 0x2c, 0xb8, 0x95,
231121748Sume  0x8c, 0xd5, 0xd1, 0x7d, 0x6b, 0x25, 0x4d, 0xa1
232121748Sume};
233121748Sume
234121748Sumestatic const unsigned char e6[] = {
235121748Sume  0x28, 0xc9, 0xf4, 0x04, 0xc4, 0xb8, 0x10, 0xf4,
236121748Sume  0xcb, 0xcc, 0xb3, 0x5c, 0xfb, 0x87, 0xf8, 0x26,
237121748Sume  0x3f, 0x57, 0x86, 0xe2, 0xd8, 0x0e, 0xd3, 0x26,
238121748Sume  0xcb, 0xc7, 0xf0, 0xe7, 0x1a, 0x99, 0xf4, 0x3b,
239121748Sume  0xfb, 0x98, 0x8b, 0x9b, 0x7a, 0x02, 0xdd, 0x21
240121748Sume};
241121748Sume
242121748Sume	AES_KEY wctx, xctx;
243121748Sume	int ret;
244121748Sume	ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16);
245121748Sume	fprintf(stderr, "Key test result %d\n", ret);
246121748Sume	ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16);
247121748Sume	fprintf(stderr, "Key test result %d\n", ret);
248121748Sume	ret = AES_wrap_unwrap_test(kek, 256, NULL, e3, key, 16);
249121748Sume	fprintf(stderr, "Key test result %d\n", ret);
250121748Sume	ret = AES_wrap_unwrap_test(kek, 192, NULL, e4, key, 24);
251121748Sume	fprintf(stderr, "Key test result %d\n", ret);
252121748Sume	ret = AES_wrap_unwrap_test(kek, 256, NULL, e5, key, 24);
253121748Sume	fprintf(stderr, "Key test result %d\n", ret);
254121748Sume	ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32);
255121748Sume	fprintf(stderr, "Key test result %d\n", ret);
256121748Sume}
257241134Seadler
258121748Sume
259121748Sume#endif
260121748Sume