1 /* $NetBSD: example_evp_cipher.c,v 1.2 2017/01/28 21:31:47 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 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 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 EVP_CipherInit_ex(&ctx, c, NULL, key, ivec, encryptp); 141 142 /* read in buffer */ 143 while ((ilen = fread(ibuf, 1, block_size, in)) > 0) { 144 /* encrypto/decrypt */ 145 ret = EVP_CipherUpdate(&ctx, obuf, &olen, ibuf, ilen); 146 if (ret != 1) { 147 EVP_CIPHER_CTX_cleanup(&ctx); 148 errx(1, "EVP_CipherUpdate failed"); 149 } 150 /* write out to output file */ 151 fwrite(obuf, 1, olen, out); 152 } 153 /* done reading */ 154 fclose(in); 155 156 /* clear up any last bytes left in the output buffer */ 157 ret = EVP_CipherFinal_ex(&ctx, obuf, &olen); 158 EVP_CIPHER_CTX_cleanup(&ctx); 159 if (ret != 1) 160 errx(1, "EVP_CipherFinal_ex failed"); 161 162 /* write the last bytes out and close */ 163 fwrite(obuf, 1, olen, out); 164 fclose(out); 165 166 return 0; 167 } 168