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