xref: /freebsd/crypto/krb5/src/lib/crypto/crypto_tests/t_encrypt.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/crypto/crypto_tests/t_encrypt.c */
3 /*
4  * Copyright 2001, 2008 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 
27 /*
28  *
29  * <<< Description >>>
30  */
31 /*
32  * Some black-box tests of crypto systems.  Make sure that we can decrypt things we encrypt, etc.
33  */
34 
35 #include "crypto_int.h"
36 #include <stdio.h>
37 
38 /* What enctypes should we test?*/
39 krb5_enctype interesting_enctypes[] = {
40     ENCTYPE_DES3_CBC_SHA1,
41     ENCTYPE_ARCFOUR_HMAC,
42     ENCTYPE_ARCFOUR_HMAC_EXP,
43     ENCTYPE_AES256_CTS_HMAC_SHA1_96,
44     ENCTYPE_AES128_CTS_HMAC_SHA1_96,
45     ENCTYPE_CAMELLIA128_CTS_CMAC,
46     ENCTYPE_CAMELLIA256_CTS_CMAC,
47     ENCTYPE_AES128_CTS_HMAC_SHA256_128,
48     ENCTYPE_AES256_CTS_HMAC_SHA384_192,
49     0
50 };
51 
52 static void
test(const char * msg,krb5_error_code retval)53 test(const char *msg, krb5_error_code retval)
54 {
55     printf("%s: . . . ", msg);
56     if (retval) {
57         printf("Failed: %s\n", error_message(retval));
58         abort();
59     } else
60         printf("OK\n");
61 }
62 
compare_results(krb5_data * d1,krb5_data * d2)63 static int compare_results(krb5_data *d1, krb5_data *d2)
64 {
65     if (d1->length != d2->length) {
66         /* Decryption can leave a little trailing cruft.
67            For the current cryptosystems, this can be up to 7 bytes.  */
68         if (d1->length + 8 <= d2->length)
69             return EINVAL;
70         if (d1->length > d2->length)
71             return EINVAL;
72     }
73     if (memcmp(d1->data, d2->data, d1->length)) {
74         return EINVAL;
75     }
76     return 0;
77 }
78 
79 static void
display(const char * msg,const krb5_data * d)80 display(const char *msg, const krb5_data *d)
81 {
82     unsigned int i;
83 
84     printf("%s:", msg);
85     for (i = 0; i < d->length; i++)
86         printf(" %02X", (unsigned char) d->data[i]);
87     printf("\n");
88 }
89 
90 int
main(void)91 main(void)
92 {
93     krb5_context context = 0;
94     krb5_data  in, in2, out, out2, check, check2, state, signdata;
95     krb5_crypto_iov iov[5];
96     int i, j, pos;
97     unsigned int dummy;
98     size_t len;
99     krb5_enc_data enc_out, enc_out2;
100     krb5_keyblock *keyblock;
101     krb5_key key;
102 
103     memset(iov, 0, sizeof(iov));
104 
105     in.data = "This is a test.\n";
106     in.length = strlen (in.data);
107     in2.data = "This is another test.\n";
108     in2.length = strlen (in2.data);
109 
110     test ("Seeding random number generator",
111           krb5_c_random_seed (context, &in));
112 
113     /* Set up output buffers. */
114     out.data = malloc(2048);
115     out2.data = malloc(2048);
116     check.data = malloc(2048);
117     check2.data = malloc(2048);
118     if (out.data == NULL || out2.data == NULL
119         || check.data == NULL || check2.data == NULL)
120         abort();
121     out.magic = KV5M_DATA;
122     out.length = 2048;
123     out2.magic = KV5M_DATA;
124     out2.length = 2048;
125     check.length = 2048;
126     check2.length = 2048;
127 
128     for (i = 0; interesting_enctypes[i]; i++) {
129         krb5_enctype enctype = interesting_enctypes [i];
130 
131         printf ("Testing enctype %d\n", enctype);
132         test ("Initializing a keyblock",
133               krb5_init_keyblock (context, enctype, 0, &keyblock));
134         test ("Generating random keyblock",
135               krb5_c_make_random_key (context, enctype, keyblock));
136         test ("Creating opaque key from keyblock",
137               krb5_k_create_key (context, keyblock, &key));
138 
139         enc_out.ciphertext = out;
140         enc_out2.ciphertext = out2;
141         /* We use an intermediate `len' because size_t may be different size
142            than `int' */
143         krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len);
144         enc_out.ciphertext.length = len;
145 
146         /* Encrypt, decrypt, and see if we got the plaintext back again. */
147         test ("Encrypting (c)",
148               krb5_c_encrypt (context, keyblock, 7, 0, &in, &enc_out));
149         display ("Enc output", &enc_out.ciphertext);
150         test ("Decrypting",
151               krb5_c_decrypt (context, keyblock, 7, 0, &enc_out, &check));
152         test ("Comparing", compare_results (&in, &check));
153 
154         /* Try again with the opaque-key-using variants. */
155         memset(out.data, 0, out.length);
156         test ("Encrypting (k)",
157               krb5_k_encrypt (context, key, 7, 0, &in, &enc_out));
158         display ("Enc output", &enc_out.ciphertext);
159         test ("Decrypting",
160               krb5_k_decrypt (context, key, 7, 0, &enc_out, &check));
161         test ("Comparing", compare_results (&in, &check));
162 
163         /* Check if this enctype supports IOV encryption. */
164         if ( krb5_c_crypto_length(context, keyblock->enctype,
165                                   KRB5_CRYPTO_TYPE_HEADER, &dummy) == 0 ){
166             /* Set up iovecs for stream decryption. */
167             memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length);
168             iov[0].flags= KRB5_CRYPTO_TYPE_STREAM;
169             iov[0].data.data = out2.data;
170             iov[0].data.length = enc_out.ciphertext.length;
171             iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
172 
173             /* Decrypt the encrypted data from above and check it. */
174             test("IOV stream decrypting (c)",
175                  krb5_c_decrypt_iov( context, keyblock, 7, 0, iov, 2));
176             test("Comparing results",
177                  compare_results(&in, &iov[1].data));
178 
179             /* Try again with the opaque-key-using variant. */
180             memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length);
181             test("IOV stream decrypting (k)",
182                  krb5_k_decrypt_iov( context, key, 7, 0, iov, 2));
183             test("Comparing results",
184                  compare_results(&in, &iov[1].data));
185 
186             /* Set up iovecs for AEAD encryption. */
187             signdata.magic = KV5M_DATA;
188             signdata.data = (char *) "This should be signed";
189             signdata.length = strlen(signdata.data);
190             iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
191             iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
192             iov[1].data = in; /*We'll need to copy memory before encrypt*/
193             iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
194             iov[2].data = signdata;
195             iov[3].flags = KRB5_CRYPTO_TYPE_PADDING;
196             iov[4].flags = KRB5_CRYPTO_TYPE_TRAILER;
197 
198             /* "Allocate" data for the iovec buffers from the "out" buffer. */
199             test("Setting up iov lengths",
200                  krb5_c_crypto_length_iov(context, keyblock->enctype, iov, 5));
201             for (j=0,pos=0; j <= 4; j++ ){
202                 if (iov[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
203                     continue;
204                 iov[j].data.data = &out.data[pos];
205                 pos += iov[j].data.length;
206             }
207             assert (iov[1].data.length == in.length);
208             memcpy(iov[1].data.data, in.data, in.length);
209 
210             /* Encrypt and decrypt in place, and check the result. */
211             test("iov encrypting (c)",
212                  krb5_c_encrypt_iov(context, keyblock, 7, 0, iov, 5));
213             assert(iov[1].data.length == in.length);
214             display("Header", &iov[0].data);
215             display("Data", &iov[1].data);
216             display("Padding", &iov[3].data);
217             display("Trailer", &iov[4].data);
218             test("iov decrypting",
219                  krb5_c_decrypt_iov(context, keyblock, 7, 0, iov, 5));
220             test("Comparing results",
221                  compare_results(&in, &iov[1].data));
222 
223             /* Try again with opaque-key-using variants. */
224             test("iov encrypting (k)",
225                  krb5_k_encrypt_iov(context, key, 7, 0, iov, 5));
226             assert(iov[1].data.length == in.length);
227             display("Header", &iov[0].data);
228             display("Data", &iov[1].data);
229             display("Padding", &iov[3].data);
230             display("Trailer", &iov[4].data);
231             test("iov decrypting",
232                  krb5_k_decrypt_iov(context, key, 7, 0, iov, 5));
233             test("Comparing results",
234                  compare_results(&in, &iov[1].data));
235         }
236 
237         enc_out.ciphertext.length = out.length;
238         check.length = 2048;
239 
240         test ("init_state",
241               krb5_c_init_state (context, keyblock, 7, &state));
242         test ("Encrypting with state",
243               krb5_c_encrypt (context, keyblock, 7, &state, &in, &enc_out));
244         display ("Enc output", &enc_out.ciphertext);
245         test ("Encrypting again with state",
246               krb5_c_encrypt (context, keyblock, 7, &state, &in2, &enc_out2));
247         display ("Enc output", &enc_out2.ciphertext);
248         test ("free_state",
249               krb5_c_free_state (context, keyblock, &state));
250         test ("init_state",
251               krb5_c_init_state (context, keyblock, 7, &state));
252         test ("Decrypting with state",
253               krb5_c_decrypt (context, keyblock, 7, &state, &enc_out, &check));
254         test ("Decrypting again with state",
255               krb5_c_decrypt (context, keyblock, 7, &state, &enc_out2, &check2));
256         test ("free_state",
257               krb5_c_free_state (context, keyblock, &state));
258         test ("Comparing",
259               compare_results (&in, &check));
260         test ("Comparing",
261               compare_results (&in2, &check2));
262 
263         krb5_free_keyblock (context, keyblock);
264         krb5_k_free_key (context, key);
265     }
266 
267     /* Test the RC4 decrypt fallback from key usage 9 to 8. */
268     test ("Initializing an RC4 keyblock",
269           krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &keyblock));
270     test ("Generating random RC4 key",
271           krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, keyblock));
272     enc_out.ciphertext = out;
273     krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len);
274     enc_out.ciphertext.length = len;
275     check.length = 2048;
276     test ("Encrypting with RC4 key usage 8",
277           krb5_c_encrypt (context, keyblock, 8, 0, &in, &enc_out));
278     display ("Enc output", &enc_out.ciphertext);
279     test ("Decrypting with RC4 key usage 9",
280           krb5_c_decrypt (context, keyblock, 9, 0, &enc_out, &check));
281     test ("Comparing", compare_results (&in, &check));
282 
283     krb5_free_keyblock (context, keyblock);
284     free(out.data);
285     free(out2.data);
286     free(check.data);
287     free(check2.data);
288     return 0;
289 }
290