xref: /onnv-gate/usr/src/lib/libkmsagent/common/ieee80211_crypto.c (revision 12720:3db6e0082404)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10)
27 #include "rijndael.h"
28 #else
29 #include <stdlib.h>
30 #include <aes_impl.h>
31 #endif
32 
33 #ifdef METAWARE
34 #include "sizet.h"
35 typedef unsigned char		uint8_t;
36 typedef unsigned short		uint16_t;
37 typedef unsigned int		uint32_t;
38 typedef unsigned long long	uint64_t;
39 #include <string.h>
40 #else
41 #ifndef WIN32
42 #include <strings.h>
43 #endif
44 #endif
45 
46 #include "KMSAgentAESKeyWrap.h"
47 
48 #ifndef TRUE
49 #define TRUE 1
50 #endif
51 
52 #ifndef FALSE
53 #define FALSE 0
54 #endif
55 
56 #ifdef WIN32
57 #define ovbcopy(x, y, z) memmove(y, x, z);
58 #else
59 #define ovbcopy(x, y, z) bcopy(x, y, z);
60 #endif
61 
62 #ifndef K_SOLARIS_PLATFORM
63 /* similar to iovec except that it accepts const pointers */
64 struct vector {
65 	const void	*base;
66 	size_t		len;
67 };
68 
69 #ifdef METAWARE
70 #define bcopy(s1, s2, n)  memcpy(s2, s1, n)
71 #endif
72 
73 /*
74  * AES Key Wrap (see RFC 3394).
75  */
76 #endif /* K_SOLARIS_PLATFORM */
77 
78 static const uint8_t aes_key_wrap_iv[8] =
79 	{ 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
80 
aes_key_wrap(const uint8_t * kek,size_t kek_len,const uint8_t * pt,size_t len,uint8_t * ct)81 void aes_key_wrap (const uint8_t *kek,
82                    size_t kek_len,
83                    const uint8_t *pt,
84                    size_t len,
85                    uint8_t *ct)
86 {
87 #if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10)
88 	rijndael_ctx ctx;
89 #else
90 	void *ks;
91 	size_t ks_size;
92 #endif
93 	uint8_t *a, *r, ar[16], t, b[16];
94 	size_t i;
95 	int j;
96 
97 	/*
98 	 * Only allow lengths for 't' values that fit within a byte.  This
99 	 * covers all reasonable uses of AES Key Wrap
100 	 */
101 	if (len > (255 / 6)) {
102 		return;
103 	}
104 
105 	/* allow ciphertext and plaintext to overlap (ct == pt) */
106 	ovbcopy(pt, ct + 8, len * 8);
107 
108 	a = ct;
109 	memcpy(a, aes_key_wrap_iv, 8);	/* default IV */
110 
111 #if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10)
112 	rijndael_set_key_enc_only(&ctx, (uint8_t *)kek, kek_len * 8);
113 #else
114 	ks = aes_alloc_keysched(&ks_size, 0);
115 	if (ks == NULL)
116 		return;
117 	aes_init_keysched(kek, kek_len * 8, ks);
118 #endif
119 
120 	for (j = 0, t = 1; j < 6; j++) {
121 		r = ct + 8;
122 		for (i = 0; i < len; i++, t++) {
123 			memcpy(ar, a, 8);
124 			memcpy(ar + 8, r, 8);
125 #if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10)
126 			rijndael_encrypt(&ctx, ar, b);
127 #else
128 			(void) aes_encrypt_block(ks, ar, b);
129 #endif
130 
131 			b[7] ^= t;
132 			memcpy(a, &b[0], 8);
133 			memcpy(r, &b[8], 8);
134 
135 			r += 8;
136 		}
137 	}
138 #if defined(K_SOLARIS_PLATFORM) && !defined(SOLARIS10)
139 	free(ks);
140 #endif
141 }
142 
aes_key_unwrap(const uint8_t * kek,size_t kek_len,const uint8_t * ct,uint8_t * pt,size_t len)143 int aes_key_unwrap (const uint8_t *kek,
144                     size_t kek_len,
145                     const uint8_t *ct,
146                     uint8_t *pt,
147                     size_t len)
148 {
149 #if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10)
150 	rijndael_ctx ctx;
151 #else
152 	void *ks;
153 	size_t ks_size;
154 #endif
155 	uint8_t a[8], *r, b[16], t, ar[16];
156 	size_t i;
157 	int j;
158 
159 	/*
160 	 * Only allow lengths for 't' values that fit within a byte.  This
161 	 * covers all reasonable uses of AES Key Wrap
162 	 */
163 	if (len > (255 / 6)) {
164 		return (-1);
165 	}
166 
167 	memcpy(a, ct, 8);
168 	/* allow ciphertext and plaintext to overlap (ct == pt) */
169 	ovbcopy(ct + 8, pt, len * 8);
170 
171 #if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10)
172 	rijndael_set_key(&ctx, (uint8_t *)kek, kek_len * 8);
173 #else
174 	ks = aes_alloc_keysched(&ks_size, 0);
175 	if (ks == NULL)
176 		return (-1);
177 	aes_init_keysched(kek, kek_len * 8, ks);
178 #endif
179 
180 	for (j = 0, t = 6 * len; j < 6; j++) {
181 		r = pt + (len - 1) * 8;
182 		for (i = 0; i < len; i++, t--) {
183 			memcpy(&ar[0], a, 8);
184 			ar[7] ^= t;
185 			memcpy(&ar[8], r, 8);
186 #if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10)
187 			rijndael_decrypt(&ctx, ar, b);
188 #else
189 			(void) aes_decrypt_block(ks, ar, b);
190 #endif
191 			memcpy(a, b, 8);
192 			memcpy(r, b + 8, 8);
193 			r -= 8;
194 		}
195 	}
196 #if defined(K_SOLARIS_PLATFORM) && !defined(SOLARIS10)
197 	free(ks);
198 #endif
199 
200 	return memcmp(a, aes_key_wrap_iv, 8) != 0;
201 }
202