]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - crypto/heimdal/lib/krb5/aes-test.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / crypto / heimdal / lib / krb5 / aes-test.c
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 }