xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hcrypto/example_evp_cipher.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1 /*	$NetBSD: example_evp_cipher.c,v 1.4 2023/06/19 21:41:43 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <config.h>
37 #include <krb5/roken.h>
38 
39 #include <krb5/krb5-types.h> /* should really be stdint.h */
40 #include <hcrypto/evp.h>
41 #include <hcrypto/evp-pkcs11.h>
42 #ifdef __APPLE__
43 #include <hcrypto/evp-cc.h>
44 #endif
45 #ifdef _WIN32
46 #include <hcrypto/evp-w32.h>
47 #endif
48 
49 #include <err.h>
50 #include <assert.h>
51 
52 /* key and initial vector */
53 static char key[16] =
54     "\xaa\xbb\x45\xd4\xaa\xbb\x45\xd4"
55     "\xaa\xbb\x45\xd4\xaa\xbb\x45\xd4";
56 static char ivec[16] =
57     "\xaa\xbb\x45\xd4\xaa\xbb\x45\xd4"
58     "\xaa\xbb\x45\xd4\xaa\xbb\x45\xd4";
59 
60 static void
61 usage(int exit_code) __attribute__((noreturn));
62 
63 static void
usage(int exit_code)64 usage(int exit_code)
65 {
66     printf("usage: %s in out [pkcs11 | cc | w32]\n", getprogname());
67     exit(exit_code);
68 }
69 
70 
71 int
main(int argc,char ** argv)72 main(int argc, char **argv)
73 {
74     int encryptp = 1;
75     const char *ifn = NULL, *ofn = NULL;
76     FILE *in, *out;
77     void *ibuf, *obuf;
78     int ilen, olen;
79     size_t block_size = 0;
80     const EVP_CIPHER *c = EVP_aes_128_cbc();
81     EVP_CIPHER_CTX ctx;
82     int ret;
83 
84     setprogname(argv[0]);
85 
86     if (argc == 2) {
87 	if (strcmp(argv[1], "--version") == 0) {
88 	    printf("version");
89 	    exit(0);
90 	}
91 	if (strcmp(argv[1], "--help") == 0)
92 	    usage(0);
93 	usage(1);
94     } else if (argc == 4 || argc == 5) {
95 	block_size = atoi(argv[1]);
96 	if (block_size == 0)
97 	    errx(1, "invalid blocksize %s", argv[1]);
98 	ifn = argv[2];
99 	ofn = argv[3];
100         if (argc == 5) {
101             if (strcmp(argv[4], "pkcs11") == 0)
102                 c = hc_EVP_pkcs11_aes_128_cbc();
103 #ifdef __APPLE__
104             else if (strcmp(argv[4], "cc") == 0)
105                 c = hc_EVP_cc_aes_128_cbc();
106 #endif
107 #ifdef _WIN32
108             else if (strcmp(argv[4], "w32") == 0)
109                 c = hc_EVP_w32crypto_aes_128_cbc();
110 #endif
111             else
112                 usage(1);
113         }
114     } else
115 	usage(1);
116 
117     in = fopen(ifn, "r");
118     if (in == NULL)
119 	errx(1, "failed to open input file");
120     out = fopen(ofn, "w+");
121     if (out == NULL)
122 	errx(1, "failed to open output file");
123 
124     /* Check that key and ivec are long enough */
125     assert(EVP_CIPHER_key_length(c) <= sizeof(key));
126     assert(EVP_CIPHER_iv_length(c) <= sizeof(ivec));
127 
128     /*
129      * Allocate buffer, the output buffer is at least
130      * EVP_CIPHER_block_size() longer
131      */
132     ibuf = malloc(block_size);
133     obuf = malloc(block_size + EVP_CIPHER_block_size(c));
134 
135     /*
136      * Init the memory used for EVP_CIPHER_CTX and set the key and
137      * ivec.
138      */
139     EVP_CIPHER_CTX_init(&ctx);
140     if (!EVP_CipherInit_ex(&ctx, c, NULL, key, ivec, encryptp))
141 	errx(1, "EVP_CipherInit_ex failed");
142 
143     /* read in buffer */
144     while ((ilen = fread(ibuf, 1, block_size, in)) > 0) {
145 	/* encrypto/decrypt */
146 	ret = EVP_CipherUpdate(&ctx, obuf, &olen, ibuf, ilen);
147 	if (ret != 1) {
148 	    EVP_CIPHER_CTX_cleanup(&ctx);
149 	    errx(1, "EVP_CipherUpdate failed");
150 	}
151 	/* write out to output file */
152 	fwrite(obuf, 1, olen, out);
153     }
154     /* done reading */
155     fclose(in);
156 
157     /* clear up any last bytes left in the output buffer */
158     ret = EVP_CipherFinal_ex(&ctx, obuf, &olen);
159     EVP_CIPHER_CTX_cleanup(&ctx);
160     if (ret != 1)
161 	errx(1, "EVP_CipherFinal_ex failed");
162 
163     /* write the last bytes out and close */
164     fwrite(obuf, 1, olen, out);
165     fclose(out);
166 
167     return 0;
168 }
169