xref: /freebsd/crypto/heimdal/lib/krb5/aes-test.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
1 /*
2  * Copyright (c) 2003 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
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 the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of KTH nor the names of its contributors may be
18  *    used to endorse or promote products derived from this software without
19  *    specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32 
33 #include "krb5_locl.h"
34 #include <hex.h>
35 #include <err.h>
36 #include <assert.h>
37 
38 #ifdef HAVE_OPENSSL
39 #include <openssl/evp.h>
40 #endif
41 
42 static int verbose = 0;
43 
44 static void
45 hex_dump_data(const void *data, size_t length)
46 {
47     char *p;
48 
49     hex_encode(data, length, &p);
50     printf("%s\n", p);
51     free(p);
52 }
53 
54 struct {
55     char *password;
56     char *salt;
57     int saltlen;
58     int iterations;
59     krb5_enctype enctype;
60     size_t keylen;
61     char *pbkdf2;
62     char *key;
63 } keys[] = {
64     {
65 	"password", "ATHENA.MIT.EDUraeburn", -1,
66 	1,
67 	ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
68 	"\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15",
69 	"\x42\x26\x3c\x6e\x89\xf4\xfc\x28\xb8\xdf\x68\xee\x09\x79\x9f\x15"
70     },
71     {
72 	"password", "ATHENA.MIT.EDUraeburn", -1,
73 	1,
74 	ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
75 	"\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15"
76 	"\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3\x33\xec\xc0\xe2\xe1\xf7\x08\x37",
77 	"\xfe\x69\x7b\x52\xbc\x0d\x3c\xe1\x44\x32\xba\x03\x6a\x92\xe6\x5b"
78 	"\xbb\x52\x28\x09\x90\xa2\xfa\x27\x88\x39\x98\xd7\x2a\xf3\x01\x61"
79     },
80     {
81 	"password", "ATHENA.MIT.EDUraeburn", -1,
82 	2,
83 	ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
84 	"\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d",
85 	"\xc6\x51\xbf\x29\xe2\x30\x0a\xc2\x7f\xa4\x69\xd6\x93\xbd\xda\x13"
86     },
87     {
88 	"password", "ATHENA.MIT.EDUraeburn", -1,
89 	2,
90 	ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
91 	"\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d"
92 	"\xa0\x53\x78\xb9\x32\x44\xec\x8f\x48\xa9\x9e\x61\xad\x79\x9d\x86",
93 	"\xa2\xe1\x6d\x16\xb3\x60\x69\xc1\x35\xd5\xe9\xd2\xe2\x5f\x89\x61"
94 	"\x02\x68\x56\x18\xb9\x59\x14\xb4\x67\xc6\x76\x22\x22\x58\x24\xff"
95     },
96     {
97 	"password", "ATHENA.MIT.EDUraeburn", -1,
98 	1200,
99 	ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
100 	"\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b",
101 	"\x4c\x01\xcd\x46\xd6\x32\xd0\x1e\x6d\xbe\x23\x0a\x01\xed\x64\x2a"
102     },
103     {
104 	"password", "ATHENA.MIT.EDUraeburn", -1,
105 	1200,
106 	ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
107 	"\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b"
108 	"\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f\x70\x8a\x31\xe2\xe6\x2b\x1e\x13",
109 	"\x55\xa6\xac\x74\x0a\xd1\x7b\x48\x46\x94\x10\x51\xe1\xe8\xb0\xa7"
110 	"\x54\x8d\x93\xb0\xab\x30\xa8\xbc\x3f\xf1\x62\x80\x38\x2b\x8c\x2a"
111     },
112     {
113 	"password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8,
114 	5,
115 	ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
116 	"\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49",
117 	"\xe9\xb2\x3d\x52\x27\x37\x47\xdd\x5c\x35\xcb\x55\xbe\x61\x9d\x8e"
118     },
119     {
120 	"password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8,
121 	5,
122 	ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
123 	"\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49"
124 	"\x3f\x98\xd2\x03\xe6\xbe\x49\xa6\xad\xf4\xfa\x57\x4b\x6e\x64\xee",
125 	"\x97\xa4\xe7\x86\xbe\x20\xd8\x1a\x38\x2d\x5e\xbc\x96\xd5\x90\x9c"
126 	"\xab\xcd\xad\xc8\x7c\xa4\x8f\x57\x45\x04\x15\x9f\x16\xc3\x6e\x31"
127     },
128     {
129 	"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
130 	"pass phrase equals block size", -1,
131 	1200,
132 	ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
133 	"\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9",
134 	"\x59\xd1\xbb\x78\x9a\x82\x8b\x1a\xa5\x4e\xf9\xc2\x88\x3f\x69\xed"
135     },
136     {
137 	"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
138 	"pass phrase equals block size", -1,
139 	1200,
140 	ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
141 	"\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9"
142 	"\xc5\xec\x59\xf1\xa4\x52\xf5\xcc\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1",
143 	"\x89\xad\xee\x36\x08\xdb\x8b\xc7\x1f\x1b\xfb\xfe\x45\x94\x86\xb0"
144 	"\x56\x18\xb7\x0c\xba\xe2\x20\x92\x53\x4e\x56\xc5\x53\xba\x4b\x34"
145     },
146     {
147 	"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
148 	"pass phrase exceeds block size", -1,
149 	1200,
150 	ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
151 	"\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61",
152 	"\xcb\x80\x05\xdc\x5f\x90\x17\x9a\x7f\x02\x10\x4c\x00\x18\x75\x1d"
153     },
154     {
155 	"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
156 	"pass phrase exceeds block size", -1,
157 	1200,
158 	ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
159 	"\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61"
160 	"\x1a\x8b\x4d\x28\x26\x01\xdb\x3b\x36\xbe\x92\x46\x91\x5e\xc8\x2a",
161 	"\xd7\x8c\x5c\x9c\xb8\x72\xa8\xc9\xda\xd4\x69\x7f\x0b\xb5\xb2\xd2"
162 	"\x14\x96\xc8\x2b\xeb\x2c\xae\xda\x21\x12\xfc\xee\xa0\x57\x40\x1b"
163 
164     },
165     {
166 	"\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1,
167 	50,
168 	ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
169 	"\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39",
170 	"\xf1\x49\xc1\xf2\xe1\x54\xa7\x34\x52\xd4\x3e\x7f\xe6\x2a\x56\xe5"
171     },
172     {
173 	"\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1,
174 	50,
175 	ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
176 	"\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39"
177 	"\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2\x81\xff\x30\x69\xe1\xe9\x4f\x52",
178 	"\x4b\x6d\x98\x39\xf8\x44\x06\xdf\x1f\x09\xcc\x16\x6d\xb4\xb8\x3c"
179 	"\x57\x18\x48\xb7\x84\xa3\xd6\xbd\xc3\x46\x58\x9a\x3e\x39\x3f\x9e"
180     },
181     {
182 	"foo", "", -1,
183 	0,
184 	ETYPE_ARCFOUR_HMAC_MD5, 16,
185 	NULL,
186 	"\xac\x8e\x65\x7f\x83\xdf\x82\xbe\xea\x5d\x43\xbd\xaf\x78\x00\xcc"
187     },
188     {
189 	"test", "", -1,
190 	0,
191 	ETYPE_ARCFOUR_HMAC_MD5, 16,
192 	NULL,
193 	"\x0c\xb6\x94\x88\x05\xf7\x97\xbf\x2a\x82\x80\x79\x73\xb8\x95\x37"
194     }
195 };
196 
197 static int
198 string_to_key_test(krb5_context context)
199 {
200     krb5_data password, opaque;
201     krb5_error_code ret;
202     krb5_salt salt;
203     int i, val = 0;
204     char iter[4];
205 
206     for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
207 
208 	password.data = keys[i].password;
209 	password.length = strlen(password.data);
210 
211 	salt.salttype = KRB5_PW_SALT;
212 	salt.saltvalue.data = keys[i].salt;
213 	if (keys[i].saltlen == -1)
214 	    salt.saltvalue.length = strlen(salt.saltvalue.data);
215 	else
216 	    salt.saltvalue.length = keys[i].saltlen;
217 
218 	opaque.data = iter;
219 	opaque.length = sizeof(iter);
220 	_krb5_put_int(iter, keys[i].iterations, 4);
221 
222 	if (keys[i].pbkdf2) {
223 	    unsigned char keyout[32];
224 
225 	    if (keys[i].keylen > sizeof(keyout))
226 		abort();
227 
228 	    PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
229 				   salt.saltvalue.data, salt.saltvalue.length,
230 				   keys[i].iterations,
231 				   keys[i].keylen, keyout);
232 
233 	    if (memcmp(keyout, keys[i].pbkdf2, keys[i].keylen) != 0) {
234 		krb5_warnx(context, "%d: pbkdf2", i);
235 		val = 1;
236 		continue;
237 	    }
238 
239 	    if (verbose) {
240 		printf("PBKDF2:\n");
241 		hex_dump_data(keyout, keys[i].keylen);
242 	    }
243 	}
244 
245 	{
246 	    krb5_keyblock key;
247 
248 	    ret = krb5_string_to_key_data_salt_opaque (context,
249 						       keys[i].enctype,
250 						       password,
251 						       salt,
252 						       opaque,
253 						       &key);
254 	    if (ret) {
255 		krb5_warn(context, ret, "%d: string_to_key_data_salt_opaque",
256 			  i);
257 		val = 1;
258 		continue;
259 	    }
260 
261 	    if (key.keyvalue.length != keys[i].keylen) {
262 		krb5_warnx(context, "%d: key wrong length (%lu/%lu)",
263 			   i, (unsigned long)key.keyvalue.length,
264 			   (unsigned long)keys[i].keylen);
265 		val = 1;
266 		continue;
267 	    }
268 
269 	    if (memcmp(key.keyvalue.data, keys[i].key, keys[i].keylen) != 0) {
270 		krb5_warnx(context, "%d: key wrong", i);
271 		val = 1;
272 		continue;
273 	    }
274 
275 	    if (verbose) {
276 		printf("key:\n");
277 		hex_dump_data(key.keyvalue.data, key.keyvalue.length);
278 	    }
279 	    krb5_free_keyblock_contents(context, &key);
280 	}
281     }
282     return val;
283 }
284 
285 static int
286 krb_enc(krb5_context context,
287 	krb5_crypto crypto,
288 	unsigned usage,
289 	krb5_data *cipher,
290 	krb5_data *clear)
291 {
292     krb5_data decrypt;
293     krb5_error_code ret;
294 
295     krb5_data_zero(&decrypt);
296 
297     ret = krb5_decrypt(context,
298 		       crypto,
299 		       usage,
300 		       cipher->data,
301 		       cipher->length,
302 		       &decrypt);
303 
304     if (ret) {
305 	krb5_warn(context, ret, "krb5_decrypt");
306 	return ret;
307     }
308 
309     if (decrypt.length != clear->length ||
310 	memcmp(decrypt.data, clear->data, decrypt.length) != 0) {
311 	krb5_warnx(context, "clear text not same");
312 	return EINVAL;
313     }
314 
315     krb5_data_free(&decrypt);
316 
317     return 0;
318 }
319 
320 static int
321 krb_enc_iov2(krb5_context context,
322 	     krb5_crypto crypto,
323 	     unsigned usage,
324 	     size_t cipher_len,
325 	     krb5_data *clear)
326 {
327     krb5_crypto_iov iov[4];
328     krb5_data decrypt;
329     int ret;
330     char *p, *q;
331     size_t len, i;
332 
333     p = clear->data;
334     len = clear->length;
335 
336     iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
337     krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length);
338     iov[0].data.data = emalloc(iov[0].data.length);
339 
340     iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
341     iov[1].data.length = len;
342     iov[1].data.data = emalloc(iov[1].data.length);
343     memcpy(iov[1].data.data, p, iov[1].data.length);
344 
345     /* padding buffer */
346     iov[2].flags = KRB5_CRYPTO_TYPE_PADDING;
347     krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_PADDING, &iov[2].data.length);
348     iov[2].data.data = emalloc(iov[2].data.length);
349 
350     iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER;
351     krb5_crypto_length(context, crypto, iov[3].flags, &iov[3].data.length);
352     iov[3].data.data = emalloc(iov[3].data.length);
353 
354     ret = krb5_encrypt_iov_ivec(context, crypto, usage,
355 				iov, sizeof(iov)/sizeof(iov[0]), NULL);
356     if (ret)
357 	errx(1, "encrypt iov failed: %d", ret);
358 
359     /* check len */
360     for (i = 0, len = 0; i < sizeof(iov)/sizeof(iov[0]); i++)
361 	len += iov[i].data.length;
362     if (len != cipher_len)
363 	errx(1, "cipher len wrong");
364 
365     /*
366      * Plain decrypt
367      */
368 
369     p = q = emalloc(len);
370     for (i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) {
371 	memcpy(q, iov[i].data.data, iov[i].data.length);
372 	q += iov[i].data.length;
373     }
374 
375     ret = krb5_decrypt(context, crypto, usage, p, len, &decrypt);
376     if (ret)
377 	krb5_err(context, 1, ret, "krb5_decrypt");
378     else
379 	krb5_data_free(&decrypt);
380 
381     free(p);
382 
383     /*
384      * Now decrypt use iov
385      */
386 
387     /* padding turn into data */
388     p = q = emalloc(iov[1].data.length + iov[2].data.length);
389 
390     memcpy(q, iov[1].data.data, iov[1].data.length);
391     q += iov[1].data.length;
392     memcpy(q, iov[2].data.data, iov[2].data.length);
393 
394     free(iov[1].data.data);
395     free(iov[2].data.data);
396 
397     iov[1].data.data = p;
398     iov[1].data.length += iov[2].data.length;
399 
400     iov[2].flags = KRB5_CRYPTO_TYPE_EMPTY;
401     iov[2].data.length = 0;
402 
403     ret = krb5_decrypt_iov_ivec(context, crypto, usage,
404 				iov, sizeof(iov)/sizeof(iov[0]), NULL);
405     free(iov[0].data.data);
406     free(iov[3].data.data);
407 
408     if (ret)
409 	krb5_err(context, 1, ret, "decrypt iov failed: %d", ret);
410 
411     if (clear->length != iov[1].data.length)
412 	errx(1, "length incorrect");
413 
414     p = clear->data;
415     if (memcmp(iov[1].data.data, p, iov[1].data.length) != 0)
416 	errx(1, "iov[1] incorrect");
417 
418     free(iov[1].data.data);
419 
420     return 0;
421 }
422 
423 
424 static int
425 krb_enc_iov(krb5_context context,
426 	    krb5_crypto crypto,
427 	    unsigned usage,
428 	    krb5_data *cipher,
429 	    krb5_data *clear)
430 {
431     krb5_crypto_iov iov[3];
432     int ret;
433     char *p;
434     size_t len;
435 
436     p = cipher->data;
437     len = cipher->length;
438 
439     iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
440     krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length);
441     iov[0].data.data = emalloc(iov[0].data.length);
442     memcpy(iov[0].data.data, p, iov[0].data.length);
443     p += iov[0].data.length;
444     len -= iov[0].data.length;
445 
446     iov[1].flags = KRB5_CRYPTO_TYPE_TRAILER;
447     krb5_crypto_length(context, crypto, iov[1].flags, &iov[1].data.length);
448     iov[1].data.data = emalloc(iov[1].data.length);
449     memcpy(iov[1].data.data, p + len - iov[1].data.length, iov[1].data.length);
450     len -= iov[1].data.length;
451 
452     iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
453     iov[2].data.length = len;
454     iov[2].data.data = emalloc(len);
455     memcpy(iov[2].data.data, p, len);
456 
457     ret = krb5_decrypt_iov_ivec(context, crypto, usage,
458 				iov, sizeof(iov)/sizeof(iov[0]), NULL);
459     if (ret)
460 	krb5_err(context, 1, ret, "krb_enc_iov decrypt iov failed: %d", ret);
461 
462     if (clear->length != iov[2].data.length)
463 	errx(1, "length incorrect");
464 
465     p = clear->data;
466     if (memcmp(iov[2].data.data, p, iov[2].data.length) != 0)
467 	errx(1, "iov[2] incorrect");
468 
469     free(iov[0].data.data);
470     free(iov[1].data.data);
471     free(iov[2].data.data);
472 
473 
474     return 0;
475 }
476 
477 static int
478 krb_checksum_iov(krb5_context context,
479 		 krb5_crypto crypto,
480 		 unsigned usage,
481 		 krb5_data *plain)
482 {
483     krb5_crypto_iov iov[4];
484     int ret;
485     char *p;
486     size_t len;
487 
488     p = plain->data;
489     len = plain->length;
490 
491     iov[0].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
492     krb5_crypto_length(context, crypto, iov[0].flags, &iov[0].data.length);
493     iov[0].data.data = emalloc(iov[0].data.length);
494 
495     iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
496     iov[1].data.length = len;
497     iov[1].data.data = p;
498 
499     iov[2].flags = KRB5_CRYPTO_TYPE_TRAILER;
500     krb5_crypto_length(context, crypto, iov[0].flags, &iov[2].data.length);
501     iov[2].data.data = malloc(iov[2].data.length);
502 
503     ret = krb5_create_checksum_iov(context, crypto, usage,
504 				   iov, sizeof(iov)/sizeof(iov[0]), NULL);
505     if (ret)
506 	krb5_err(context, 1, ret, "krb5_create_checksum_iov failed");
507 
508     ret = krb5_verify_checksum_iov(context, crypto, usage, iov, sizeof(iov)/sizeof(iov[0]), NULL);
509     if (ret)
510 	krb5_err(context, 1, ret, "krb5_verify_checksum_iov");
511 
512     free(iov[0].data.data);
513     free(iov[2].data.data);
514 
515     return 0;
516 }
517 
518 
519 static int
520 krb_enc_mit(krb5_context context,
521 	    krb5_enctype enctype,
522 	    krb5_keyblock *key,
523 	    unsigned usage,
524 	    krb5_data *cipher,
525 	    krb5_data *clear)
526 {
527 #ifndef HEIMDAL_SMALLER
528     krb5_error_code ret;
529     krb5_enc_data e;
530     krb5_data decrypt;
531     size_t len;
532 
533     e.kvno = 0;
534     e.enctype = enctype;
535     e.ciphertext = *cipher;
536 
537     ret = krb5_c_decrypt(context, *key, usage, NULL, &e, &decrypt);
538     if (ret)
539 	return ret;
540 
541     if (decrypt.length != clear->length ||
542 	memcmp(decrypt.data, clear->data, decrypt.length) != 0) {
543 	krb5_warnx(context, "clear text not same");
544 	return EINVAL;
545     }
546 
547     krb5_data_free(&decrypt);
548 
549     ret = krb5_c_encrypt_length(context, enctype, clear->length, &len);
550     if (ret)
551 	return ret;
552 
553     if (len != cipher->length) {
554 	krb5_warnx(context, "c_encrypt_length wrong %lu != %lu",
555 		   (unsigned long)len, (unsigned long)cipher->length);
556 	return EINVAL;
557     }
558 #endif /* HEIMDAL_SMALLER */
559     return 0;
560 }
561 
562 
563 struct {
564     krb5_enctype enctype;
565     unsigned usage;
566     size_t keylen;
567     void *key;
568     size_t elen;
569     void* edata;
570     size_t plen;
571     void *pdata;
572 } krbencs[] =  {
573     {
574 	ETYPE_AES256_CTS_HMAC_SHA1_96,
575 	7,
576 	32,
577 	"\x47\x75\x69\x64\x65\x6c\x69\x6e\x65\x73\x20\x74\x6f\x20\x41\x75"
578 	"\x74\x68\x6f\x72\x73\x20\x6f\x66\x20\x49\x6e\x74\x65\x72\x6e\x65",
579 	44,
580 	"\xcf\x79\x8f\x0d\x76\xf3\xe0\xbe\x8e\x66\x94\x70\xfa\xcc\x9e\x91"
581 	"\xa9\xec\x1c\x5c\x21\xfb\x6e\xef\x1a\x7a\xc8\xc1\xcc\x5a\x95\x24"
582 	"\x6f\x9f\xf4\xd5\xbe\x5d\x59\x97\x44\xd8\x47\xcd",
583 	16,
584 	"\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x2e\x0a"
585     }
586 };
587 
588 
589 static int
590 krb_enc_test(krb5_context context)
591 {
592     krb5_error_code ret;
593     krb5_crypto crypto;
594     krb5_keyblock kb;
595     krb5_data cipher, plain;
596     int i;
597 
598     for (i = 0; i < sizeof(krbencs)/sizeof(krbencs[0]); i++) {
599 
600 	kb.keytype = krbencs[i].enctype;
601 	kb.keyvalue.length = krbencs[i].keylen;
602 	kb.keyvalue.data = krbencs[i].key;
603 
604 	ret = krb5_crypto_init(context, &kb, krbencs[i].enctype, &crypto);
605 
606 	cipher.length = krbencs[i].elen;
607 	cipher.data = krbencs[i].edata;
608 	plain.length = krbencs[i].plen;
609 	plain.data = krbencs[i].pdata;
610 
611 	ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain);
612 
613 	if (ret)
614 	    errx(1, "krb_enc failed with %d for test %d", ret, i);
615 
616 	ret = krb_enc_iov(context, crypto, krbencs[i].usage, &cipher, &plain);
617 	if (ret)
618 	    errx(1, "krb_enc_iov failed with %d for test %d", ret, i);
619 
620 	ret = krb_enc_iov2(context, crypto, krbencs[i].usage,
621 			   cipher.length, &plain);
622 	if (ret)
623 	    errx(1, "krb_enc_iov2 failed with %d for test %d", ret, i);
624 
625 	ret = krb_checksum_iov(context, crypto, krbencs[i].usage, &plain);
626 	if (ret)
627 	    errx(1, "krb_checksum_iov failed with %d for test %d", ret, i);
628 
629 	krb5_crypto_destroy(context, crypto);
630 
631 	ret = krb_enc_mit(context, krbencs[i].enctype, &kb,
632 			  krbencs[i].usage, &cipher, &plain);
633 	if (ret)
634 	    errx(1, "krb_enc_mit failed with %d for test %d", ret, i);
635     }
636 
637     return 0;
638 }
639 
640 static int
641 iov_test(krb5_context context)
642 {
643     krb5_enctype enctype = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
644     krb5_error_code ret;
645     krb5_crypto crypto;
646     krb5_keyblock key;
647     krb5_data signonly, in, in2;
648     krb5_crypto_iov iov[6];
649     size_t len, i;
650     unsigned char *base, *p;
651 
652     ret = krb5_generate_random_keyblock(context, enctype, &key);
653     if (ret)
654 	krb5_err(context, 1, ret, "krb5_generate_random_keyblock");
655 
656     ret = krb5_crypto_init(context, &key, 0, &crypto);
657     if (ret)
658 	krb5_err(context, 1, ret, "krb5_crypto_init");
659 
660 
661     ret = krb5_crypto_length(context, crypto, KRB5_CRYPTO_TYPE_HEADER, &len);
662     if (ret)
663 	krb5_err(context, 1, ret, "krb5_crypto_length");
664 
665     signonly.data = "This should be signed";
666     signonly.length = strlen(signonly.data);
667     in.data = "inputdata";
668     in.length = strlen(in.data);
669 
670     in2.data = "INPUTDATA";
671     in2.length = strlen(in2.data);
672 
673 
674     memset(iov, 0, sizeof(iov));
675 
676     iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
677     iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
678     iov[1].data = in;
679     iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
680     iov[2].data = signonly;
681     iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY;
682     iov[4].flags = KRB5_CRYPTO_TYPE_PADDING;
683     iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER;
684 
685     ret = krb5_crypto_length_iov(context, crypto, iov,
686 				 sizeof(iov)/sizeof(iov[0]));
687     if (ret)
688 	krb5_err(context, 1, ret, "krb5_crypto_length_iov");
689 
690     for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) {
691 	if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
692 	    continue;
693 	len += iov[i].data.length;
694     }
695 
696     base = emalloc(len);
697 
698     /*
699      * Allocate data for the fields
700      */
701 
702     for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) {
703 	if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
704 	    continue;;
705 	iov[i].data.data = p;
706 	p += iov[i].data.length;
707     }
708     assert(iov[1].data.length == in.length);
709     memcpy(iov[1].data.data, in.data, iov[1].data.length);
710 
711     /*
712      * Encrypt
713      */
714 
715     ret = krb5_encrypt_iov_ivec(context, crypto, 7, iov,
716 				sizeof(iov)/sizeof(iov[0]), NULL);
717     if (ret)
718 	krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec");
719 
720     /*
721      * Decrypt
722      */
723 
724     ret = krb5_decrypt_iov_ivec(context, crypto, 7,
725 				iov, sizeof(iov)/sizeof(iov[0]), NULL);
726     if (ret)
727 	krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec");
728 
729     /*
730      * Verify data
731      */
732 
733     if (krb5_data_cmp(&iov[1].data, &in) != 0)
734 	krb5_errx(context, 1, "decrypted data not same");
735 
736     /*
737      * Free memory
738      */
739 
740     free(base);
741 
742     /* Set up for second try */
743 
744     iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
745     iov[3].data = in;
746 
747     ret = krb5_crypto_length_iov(context, crypto,
748 				 iov, sizeof(iov)/sizeof(iov[0]));
749     if (ret)
750 	krb5_err(context, 1, ret, "krb5_crypto_length_iov");
751 
752     for (len = 0, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) {
753 	if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
754 	    continue;
755 	len += iov[i].data.length;
756     }
757 
758     base = emalloc(len);
759 
760     /*
761      * Allocate data for the fields
762      */
763 
764     for (p = base, i = 0; i < sizeof(iov)/sizeof(iov[0]); i++) {
765 	if (iov[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
766 	    continue;;
767 	iov[i].data.data = p;
768 	p += iov[i].data.length;
769     }
770     assert(iov[1].data.length == in.length);
771     memcpy(iov[1].data.data, in.data, iov[1].data.length);
772 
773     assert(iov[3].data.length == in2.length);
774     memcpy(iov[3].data.data, in2.data, iov[3].data.length);
775 
776 
777 
778     /*
779      * Encrypt
780      */
781 
782     ret = krb5_encrypt_iov_ivec(context, crypto, 7,
783 				iov, sizeof(iov)/sizeof(iov[0]), NULL);
784     if (ret)
785 	krb5_err(context, 1, ret, "krb5_encrypt_iov_ivec");
786 
787     /*
788      * Decrypt
789      */
790 
791     ret = krb5_decrypt_iov_ivec(context, crypto, 7,
792 				iov, sizeof(iov)/sizeof(iov[0]), NULL);
793     if (ret)
794 	krb5_err(context, 1, ret, "krb5_decrypt_iov_ivec");
795 
796     /*
797      * Verify data
798      */
799 
800     if (krb5_data_cmp(&iov[1].data, &in) != 0)
801 	krb5_errx(context, 1, "decrypted data 2.1 not same");
802 
803     if (krb5_data_cmp(&iov[3].data, &in2) != 0)
804 	krb5_errx(context, 1, "decrypted data 2.2 not same");
805 
806     /*
807      * Free memory
808      */
809 
810     free(base);
811 
812     krb5_crypto_destroy(context, crypto);
813 
814     krb5_free_keyblock_contents(context, &key);
815 
816     return 0;
817 }
818 
819 
820 
821 static int
822 random_to_key(krb5_context context)
823 {
824     krb5_error_code ret;
825     krb5_keyblock key;
826 
827     ret = krb5_random_to_key(context,
828 			     ETYPE_DES3_CBC_SHA1,
829 			     "\x21\x39\x04\x58\x6A\xBD\x7F"
830 			     "\x21\x39\x04\x58\x6A\xBD\x7F"
831 			     "\x21\x39\x04\x58\x6A\xBD\x7F",
832 			     21,
833 			     &key);
834     if (ret){
835 	krb5_warn(context, ret, "random_to_key");
836 	return 1;
837     }
838     if (key.keyvalue.length != 24)
839 	return 1;
840 
841     if (memcmp(key.keyvalue.data,
842 	       "\x20\x38\x04\x58\x6b\xbc\x7f\xc7"
843 	       "\x20\x38\x04\x58\x6b\xbc\x7f\xc7"
844 	       "\x20\x38\x04\x58\x6b\xbc\x7f\xc7",
845 	       24) != 0)
846 	return 1;
847 
848     krb5_free_keyblock_contents(context, &key);
849 
850     return 0;
851 }
852 
853 int
854 main(int argc, char **argv)
855 {
856     krb5_error_code ret;
857     krb5_context context;
858     int val = 0;
859 
860     ret = krb5_init_context (&context);
861     if (ret)
862 	errx (1, "krb5_init_context failed: %d", ret);
863 
864     val |= string_to_key_test(context);
865 
866     val |= krb_enc_test(context);
867     val |= random_to_key(context);
868     val |= iov_test(context);
869 
870     if (verbose && val == 0)
871 	printf("all ok\n");
872     if (val)
873 	printf("tests failed\n");
874 
875     krb5_free_context(context);
876 
877     return val;
878 }
879