1*0Sstevel@tonic-gate /* apps/enc.c */ 2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*0Sstevel@tonic-gate * All rights reserved. 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * This package is an SSL implementation written 6*0Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 7*0Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 10*0Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 11*0Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 12*0Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*0Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 14*0Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 17*0Sstevel@tonic-gate * the code are not to be removed. 18*0Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 19*0Sstevel@tonic-gate * as the author of the parts of the library used. 20*0Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 21*0Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 32*0Sstevel@tonic-gate * must display the following acknowledgement: 33*0Sstevel@tonic-gate * "This product includes cryptographic software written by 34*0Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 35*0Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 36*0Sstevel@tonic-gate * being used are not cryptographic related :-). 37*0Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 38*0Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 39*0Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*0Sstevel@tonic-gate * SUCH DAMAGE. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 54*0Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 55*0Sstevel@tonic-gate * copied and put under another distribution licence 56*0Sstevel@tonic-gate * [including the GNU Public Licence.] 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include <stdio.h> 60*0Sstevel@tonic-gate #include <stdlib.h> 61*0Sstevel@tonic-gate #include <string.h> 62*0Sstevel@tonic-gate #include "apps.h" 63*0Sstevel@tonic-gate #include <openssl/bio.h> 64*0Sstevel@tonic-gate #include <openssl/err.h> 65*0Sstevel@tonic-gate #include <openssl/evp.h> 66*0Sstevel@tonic-gate #include <openssl/objects.h> 67*0Sstevel@tonic-gate #include <openssl/x509.h> 68*0Sstevel@tonic-gate #include <openssl/rand.h> 69*0Sstevel@tonic-gate #include <openssl/pem.h> 70*0Sstevel@tonic-gate #include <ctype.h> 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate int set_hex(char *in,unsigned char *out,int size); 73*0Sstevel@tonic-gate #undef SIZE 74*0Sstevel@tonic-gate #undef BSIZE 75*0Sstevel@tonic-gate #undef PROG 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate #define SIZE (512) 78*0Sstevel@tonic-gate #define BSIZE (8*1024) 79*0Sstevel@tonic-gate #define PROG enc_main 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate static void show_ciphers(const OBJ_NAME *name,void *bio_) 82*0Sstevel@tonic-gate { 83*0Sstevel@tonic-gate BIO *bio=bio_; 84*0Sstevel@tonic-gate static int n; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate if(!islower((unsigned char)*name->name)) 87*0Sstevel@tonic-gate return; 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate BIO_printf(bio,"-%-25s",name->name); 90*0Sstevel@tonic-gate if(++n == 3) 91*0Sstevel@tonic-gate { 92*0Sstevel@tonic-gate BIO_printf(bio,"\n"); 93*0Sstevel@tonic-gate n=0; 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate else 96*0Sstevel@tonic-gate BIO_printf(bio," "); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate int MAIN(int, char **); 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate int MAIN(int argc, char **argv) 102*0Sstevel@tonic-gate { 103*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 104*0Sstevel@tonic-gate ENGINE *e = NULL; 105*0Sstevel@tonic-gate #endif 106*0Sstevel@tonic-gate static const char magic[]="Salted__"; 107*0Sstevel@tonic-gate char mbuf[sizeof magic-1]; 108*0Sstevel@tonic-gate char *strbuf=NULL; 109*0Sstevel@tonic-gate unsigned char *buff=NULL,*bufsize=NULL; 110*0Sstevel@tonic-gate int bsize=BSIZE,verbose=0; 111*0Sstevel@tonic-gate int ret=1,inl; 112*0Sstevel@tonic-gate int nopad = 0; 113*0Sstevel@tonic-gate unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH]; 114*0Sstevel@tonic-gate unsigned char salt[PKCS5_SALT_LEN]; 115*0Sstevel@tonic-gate char *str=NULL, *passarg = NULL, *pass = NULL; 116*0Sstevel@tonic-gate char *hkey=NULL,*hiv=NULL,*hsalt = NULL; 117*0Sstevel@tonic-gate int enc=1,printkey=0,i,base64=0; 118*0Sstevel@tonic-gate int debug=0,olb64=0,nosalt=0; 119*0Sstevel@tonic-gate const EVP_CIPHER *cipher=NULL,*c; 120*0Sstevel@tonic-gate char *inf=NULL,*outf=NULL; 121*0Sstevel@tonic-gate BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL; 122*0Sstevel@tonic-gate #define PROG_NAME_SIZE 39 123*0Sstevel@tonic-gate char pname[PROG_NAME_SIZE+1]; 124*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 125*0Sstevel@tonic-gate char *engine = NULL; 126*0Sstevel@tonic-gate #endif 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate apps_startup(); 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate if (bio_err == NULL) 131*0Sstevel@tonic-gate if ((bio_err=BIO_new(BIO_s_file())) != NULL) 132*0Sstevel@tonic-gate BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate if (!load_config(bio_err, NULL)) 135*0Sstevel@tonic-gate goto end; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* first check the program name */ 138*0Sstevel@tonic-gate program_name(argv[0],pname,sizeof pname); 139*0Sstevel@tonic-gate if (strcmp(pname,"base64") == 0) 140*0Sstevel@tonic-gate base64=1; 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate cipher=EVP_get_cipherbyname(pname); 143*0Sstevel@tonic-gate if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0)) 144*0Sstevel@tonic-gate { 145*0Sstevel@tonic-gate BIO_printf(bio_err,"%s is an unknown cipher\n",pname); 146*0Sstevel@tonic-gate goto bad; 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate argc--; 150*0Sstevel@tonic-gate argv++; 151*0Sstevel@tonic-gate while (argc >= 1) 152*0Sstevel@tonic-gate { 153*0Sstevel@tonic-gate if (strcmp(*argv,"-e") == 0) 154*0Sstevel@tonic-gate enc=1; 155*0Sstevel@tonic-gate else if (strcmp(*argv,"-in") == 0) 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate if (--argc < 1) goto bad; 158*0Sstevel@tonic-gate inf= *(++argv); 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate else if (strcmp(*argv,"-out") == 0) 161*0Sstevel@tonic-gate { 162*0Sstevel@tonic-gate if (--argc < 1) goto bad; 163*0Sstevel@tonic-gate outf= *(++argv); 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate else if (strcmp(*argv,"-pass") == 0) 166*0Sstevel@tonic-gate { 167*0Sstevel@tonic-gate if (--argc < 1) goto bad; 168*0Sstevel@tonic-gate passarg= *(++argv); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 171*0Sstevel@tonic-gate else if (strcmp(*argv,"-engine") == 0) 172*0Sstevel@tonic-gate { 173*0Sstevel@tonic-gate if (--argc < 1) goto bad; 174*0Sstevel@tonic-gate engine= *(++argv); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate #endif 177*0Sstevel@tonic-gate else if (strcmp(*argv,"-d") == 0) 178*0Sstevel@tonic-gate enc=0; 179*0Sstevel@tonic-gate else if (strcmp(*argv,"-p") == 0) 180*0Sstevel@tonic-gate printkey=1; 181*0Sstevel@tonic-gate else if (strcmp(*argv,"-v") == 0) 182*0Sstevel@tonic-gate verbose=1; 183*0Sstevel@tonic-gate else if (strcmp(*argv,"-nopad") == 0) 184*0Sstevel@tonic-gate nopad=1; 185*0Sstevel@tonic-gate else if (strcmp(*argv,"-salt") == 0) 186*0Sstevel@tonic-gate nosalt=0; 187*0Sstevel@tonic-gate else if (strcmp(*argv,"-nosalt") == 0) 188*0Sstevel@tonic-gate nosalt=1; 189*0Sstevel@tonic-gate else if (strcmp(*argv,"-debug") == 0) 190*0Sstevel@tonic-gate debug=1; 191*0Sstevel@tonic-gate else if (strcmp(*argv,"-P") == 0) 192*0Sstevel@tonic-gate printkey=2; 193*0Sstevel@tonic-gate else if (strcmp(*argv,"-A") == 0) 194*0Sstevel@tonic-gate olb64=1; 195*0Sstevel@tonic-gate else if (strcmp(*argv,"-a") == 0) 196*0Sstevel@tonic-gate base64=1; 197*0Sstevel@tonic-gate else if (strcmp(*argv,"-base64") == 0) 198*0Sstevel@tonic-gate base64=1; 199*0Sstevel@tonic-gate else if (strcmp(*argv,"-bufsize") == 0) 200*0Sstevel@tonic-gate { 201*0Sstevel@tonic-gate if (--argc < 1) goto bad; 202*0Sstevel@tonic-gate bufsize=(unsigned char *)*(++argv); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate else if (strcmp(*argv,"-k") == 0) 205*0Sstevel@tonic-gate { 206*0Sstevel@tonic-gate if (--argc < 1) goto bad; 207*0Sstevel@tonic-gate str= *(++argv); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate else if (strcmp(*argv,"-kfile") == 0) 210*0Sstevel@tonic-gate { 211*0Sstevel@tonic-gate static char buf[128]; 212*0Sstevel@tonic-gate FILE *infile; 213*0Sstevel@tonic-gate char *file; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate if (--argc < 1) goto bad; 216*0Sstevel@tonic-gate file= *(++argv); 217*0Sstevel@tonic-gate infile=fopen(file,"r"); 218*0Sstevel@tonic-gate if (infile == NULL) 219*0Sstevel@tonic-gate { 220*0Sstevel@tonic-gate BIO_printf(bio_err,"unable to read key from '%s'\n", 221*0Sstevel@tonic-gate file); 222*0Sstevel@tonic-gate goto bad; 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate buf[0]='\0'; 225*0Sstevel@tonic-gate fgets(buf,sizeof buf,infile); 226*0Sstevel@tonic-gate fclose(infile); 227*0Sstevel@tonic-gate i=strlen(buf); 228*0Sstevel@tonic-gate if ((i > 0) && 229*0Sstevel@tonic-gate ((buf[i-1] == '\n') || (buf[i-1] == '\r'))) 230*0Sstevel@tonic-gate buf[--i]='\0'; 231*0Sstevel@tonic-gate if ((i > 0) && 232*0Sstevel@tonic-gate ((buf[i-1] == '\n') || (buf[i-1] == '\r'))) 233*0Sstevel@tonic-gate buf[--i]='\0'; 234*0Sstevel@tonic-gate if (i < 1) 235*0Sstevel@tonic-gate { 236*0Sstevel@tonic-gate BIO_printf(bio_err,"zero length password\n"); 237*0Sstevel@tonic-gate goto bad; 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate str=buf; 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate else if (strcmp(*argv,"-K") == 0) 242*0Sstevel@tonic-gate { 243*0Sstevel@tonic-gate if (--argc < 1) goto bad; 244*0Sstevel@tonic-gate hkey= *(++argv); 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate else if (strcmp(*argv,"-S") == 0) 247*0Sstevel@tonic-gate { 248*0Sstevel@tonic-gate if (--argc < 1) goto bad; 249*0Sstevel@tonic-gate hsalt= *(++argv); 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate else if (strcmp(*argv,"-iv") == 0) 252*0Sstevel@tonic-gate { 253*0Sstevel@tonic-gate if (--argc < 1) goto bad; 254*0Sstevel@tonic-gate hiv= *(++argv); 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate else if ((argv[0][0] == '-') && 257*0Sstevel@tonic-gate ((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL)) 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate cipher=c; 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate else if (strcmp(*argv,"-none") == 0) 262*0Sstevel@tonic-gate cipher=NULL; 263*0Sstevel@tonic-gate else 264*0Sstevel@tonic-gate { 265*0Sstevel@tonic-gate BIO_printf(bio_err,"unknown option '%s'\n",*argv); 266*0Sstevel@tonic-gate bad: 267*0Sstevel@tonic-gate BIO_printf(bio_err,"options are\n"); 268*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s input file\n","-in <file>"); 269*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s output file\n","-out <file>"); 270*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s pass phrase source\n","-pass <arg>"); 271*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s encrypt\n","-e"); 272*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s decrypt\n","-d"); 273*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s base64 encode/decode, depending on encryption flag\n","-a/-base64"); 274*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s key is the next argument\n","-k"); 275*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s key is the first line of the file argument\n","-kfile"); 276*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s key/iv in hex is the next argument\n","-K/-iv"); 277*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s print the iv/key (then exit if -P)\n","-[pP]"); 278*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s buffer size\n","-bufsize <n>"); 279*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 280*0Sstevel@tonic-gate BIO_printf(bio_err,"%-14s use engine e, possibly a hardware device.\n","-engine e"); 281*0Sstevel@tonic-gate #endif 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate BIO_printf(bio_err,"Cipher Types\n"); 284*0Sstevel@tonic-gate OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, 285*0Sstevel@tonic-gate show_ciphers, 286*0Sstevel@tonic-gate bio_err); 287*0Sstevel@tonic-gate BIO_printf(bio_err,"\n"); 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate goto end; 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate argc--; 292*0Sstevel@tonic-gate argv++; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE 296*0Sstevel@tonic-gate e = setup_engine(bio_err, engine, 0); 297*0Sstevel@tonic-gate #endif 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate if (bufsize != NULL) 300*0Sstevel@tonic-gate { 301*0Sstevel@tonic-gate unsigned long n; 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate for (n=0; *bufsize; bufsize++) 304*0Sstevel@tonic-gate { 305*0Sstevel@tonic-gate i= *bufsize; 306*0Sstevel@tonic-gate if ((i <= '9') && (i >= '0')) 307*0Sstevel@tonic-gate n=n*10+i-'0'; 308*0Sstevel@tonic-gate else if (i == 'k') 309*0Sstevel@tonic-gate { 310*0Sstevel@tonic-gate n*=1024; 311*0Sstevel@tonic-gate bufsize++; 312*0Sstevel@tonic-gate break; 313*0Sstevel@tonic-gate } 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate if (*bufsize != '\0') 316*0Sstevel@tonic-gate { 317*0Sstevel@tonic-gate BIO_printf(bio_err,"invalid 'bufsize' specified.\n"); 318*0Sstevel@tonic-gate goto end; 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* It must be large enough for a base64 encoded line */ 322*0Sstevel@tonic-gate if (n < 80) n=80; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate bsize=(int)n; 325*0Sstevel@tonic-gate if (verbose) BIO_printf(bio_err,"bufsize=%d\n",bsize); 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate strbuf=OPENSSL_malloc(SIZE); 329*0Sstevel@tonic-gate buff=(unsigned char *)OPENSSL_malloc(EVP_ENCODE_LENGTH(bsize)); 330*0Sstevel@tonic-gate if ((buff == NULL) || (strbuf == NULL)) 331*0Sstevel@tonic-gate { 332*0Sstevel@tonic-gate BIO_printf(bio_err,"OPENSSL_malloc failure %ld\n",(long)EVP_ENCODE_LENGTH(bsize)); 333*0Sstevel@tonic-gate goto end; 334*0Sstevel@tonic-gate } 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate in=BIO_new(BIO_s_file()); 337*0Sstevel@tonic-gate out=BIO_new(BIO_s_file()); 338*0Sstevel@tonic-gate if ((in == NULL) || (out == NULL)) 339*0Sstevel@tonic-gate { 340*0Sstevel@tonic-gate ERR_print_errors(bio_err); 341*0Sstevel@tonic-gate goto end; 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate if (debug) 344*0Sstevel@tonic-gate { 345*0Sstevel@tonic-gate BIO_set_callback(in,BIO_debug_callback); 346*0Sstevel@tonic-gate BIO_set_callback(out,BIO_debug_callback); 347*0Sstevel@tonic-gate BIO_set_callback_arg(in,bio_err); 348*0Sstevel@tonic-gate BIO_set_callback_arg(out,bio_err); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate if (inf == NULL) 352*0Sstevel@tonic-gate BIO_set_fp(in,stdin,BIO_NOCLOSE); 353*0Sstevel@tonic-gate else 354*0Sstevel@tonic-gate { 355*0Sstevel@tonic-gate if (BIO_read_filename(in,inf) <= 0) 356*0Sstevel@tonic-gate { 357*0Sstevel@tonic-gate perror(inf); 358*0Sstevel@tonic-gate goto end; 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate if(!str && passarg) { 363*0Sstevel@tonic-gate if(!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { 364*0Sstevel@tonic-gate BIO_printf(bio_err, "Error getting password\n"); 365*0Sstevel@tonic-gate goto end; 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate str = pass; 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate for (;;) 373*0Sstevel@tonic-gate { 374*0Sstevel@tonic-gate char buf[200]; 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate BIO_snprintf(buf,sizeof buf,"enter %s %s password:", 377*0Sstevel@tonic-gate OBJ_nid2ln(EVP_CIPHER_nid(cipher)), 378*0Sstevel@tonic-gate (enc)?"encryption":"decryption"); 379*0Sstevel@tonic-gate strbuf[0]='\0'; 380*0Sstevel@tonic-gate i=EVP_read_pw_string((char *)strbuf,SIZE,buf,enc); 381*0Sstevel@tonic-gate if (i == 0) 382*0Sstevel@tonic-gate { 383*0Sstevel@tonic-gate if (strbuf[0] == '\0') 384*0Sstevel@tonic-gate { 385*0Sstevel@tonic-gate ret=1; 386*0Sstevel@tonic-gate goto end; 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate str=strbuf; 389*0Sstevel@tonic-gate break; 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate if (i < 0) 392*0Sstevel@tonic-gate { 393*0Sstevel@tonic-gate BIO_printf(bio_err,"bad password read\n"); 394*0Sstevel@tonic-gate goto end; 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate if (outf == NULL) 401*0Sstevel@tonic-gate { 402*0Sstevel@tonic-gate BIO_set_fp(out,stdout,BIO_NOCLOSE); 403*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_VMS 404*0Sstevel@tonic-gate { 405*0Sstevel@tonic-gate BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 406*0Sstevel@tonic-gate out = BIO_push(tmpbio, out); 407*0Sstevel@tonic-gate } 408*0Sstevel@tonic-gate #endif 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate else 411*0Sstevel@tonic-gate { 412*0Sstevel@tonic-gate if (BIO_write_filename(out,outf) <= 0) 413*0Sstevel@tonic-gate { 414*0Sstevel@tonic-gate perror(outf); 415*0Sstevel@tonic-gate goto end; 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate rbio=in; 420*0Sstevel@tonic-gate wbio=out; 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate if (base64) 423*0Sstevel@tonic-gate { 424*0Sstevel@tonic-gate if ((b64=BIO_new(BIO_f_base64())) == NULL) 425*0Sstevel@tonic-gate goto end; 426*0Sstevel@tonic-gate if (debug) 427*0Sstevel@tonic-gate { 428*0Sstevel@tonic-gate BIO_set_callback(b64,BIO_debug_callback); 429*0Sstevel@tonic-gate BIO_set_callback_arg(b64,bio_err); 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate if (olb64) 432*0Sstevel@tonic-gate BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL); 433*0Sstevel@tonic-gate if (enc) 434*0Sstevel@tonic-gate wbio=BIO_push(b64,wbio); 435*0Sstevel@tonic-gate else 436*0Sstevel@tonic-gate rbio=BIO_push(b64,rbio); 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate if (cipher != NULL) 440*0Sstevel@tonic-gate { 441*0Sstevel@tonic-gate /* Note that str is NULL if a key was passed on the command 442*0Sstevel@tonic-gate * line, so we get no salt in that case. Is this a bug? 443*0Sstevel@tonic-gate */ 444*0Sstevel@tonic-gate if (str != NULL) 445*0Sstevel@tonic-gate { 446*0Sstevel@tonic-gate /* Salt handling: if encrypting generate a salt and 447*0Sstevel@tonic-gate * write to output BIO. If decrypting read salt from 448*0Sstevel@tonic-gate * input BIO. 449*0Sstevel@tonic-gate */ 450*0Sstevel@tonic-gate unsigned char *sptr; 451*0Sstevel@tonic-gate if(nosalt) sptr = NULL; 452*0Sstevel@tonic-gate else { 453*0Sstevel@tonic-gate if(enc) { 454*0Sstevel@tonic-gate if(hsalt) { 455*0Sstevel@tonic-gate if(!set_hex(hsalt,salt,sizeof salt)) { 456*0Sstevel@tonic-gate BIO_printf(bio_err, 457*0Sstevel@tonic-gate "invalid hex salt value\n"); 458*0Sstevel@tonic-gate goto end; 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate } else if (RAND_pseudo_bytes(salt, sizeof salt) < 0) 461*0Sstevel@tonic-gate goto end; 462*0Sstevel@tonic-gate /* If -P option then don't bother writing */ 463*0Sstevel@tonic-gate if((printkey != 2) 464*0Sstevel@tonic-gate && (BIO_write(wbio,magic, 465*0Sstevel@tonic-gate sizeof magic-1) != sizeof magic-1 466*0Sstevel@tonic-gate || BIO_write(wbio, 467*0Sstevel@tonic-gate (char *)salt, 468*0Sstevel@tonic-gate sizeof salt) != sizeof salt)) { 469*0Sstevel@tonic-gate BIO_printf(bio_err,"error writing output file\n"); 470*0Sstevel@tonic-gate goto end; 471*0Sstevel@tonic-gate } 472*0Sstevel@tonic-gate } else if(BIO_read(rbio,mbuf,sizeof mbuf) != sizeof mbuf 473*0Sstevel@tonic-gate || BIO_read(rbio, 474*0Sstevel@tonic-gate (unsigned char *)salt, 475*0Sstevel@tonic-gate sizeof salt) != sizeof salt) { 476*0Sstevel@tonic-gate BIO_printf(bio_err,"error reading input file\n"); 477*0Sstevel@tonic-gate goto end; 478*0Sstevel@tonic-gate } else if(memcmp(mbuf,magic,sizeof magic-1)) { 479*0Sstevel@tonic-gate BIO_printf(bio_err,"bad magic number\n"); 480*0Sstevel@tonic-gate goto end; 481*0Sstevel@tonic-gate } 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate sptr = salt; 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate EVP_BytesToKey(cipher,EVP_md5(),sptr, 487*0Sstevel@tonic-gate (unsigned char *)str, 488*0Sstevel@tonic-gate strlen(str),1,key,iv); 489*0Sstevel@tonic-gate /* zero the complete buffer or the string 490*0Sstevel@tonic-gate * passed from the command line 491*0Sstevel@tonic-gate * bug picked up by 492*0Sstevel@tonic-gate * Larry J. Hughes Jr. <hughes@indiana.edu> */ 493*0Sstevel@tonic-gate if (str == strbuf) 494*0Sstevel@tonic-gate OPENSSL_cleanse(str,SIZE); 495*0Sstevel@tonic-gate else 496*0Sstevel@tonic-gate OPENSSL_cleanse(str,strlen(str)); 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate if ((hiv != NULL) && !set_hex(hiv,iv,sizeof iv)) 499*0Sstevel@tonic-gate { 500*0Sstevel@tonic-gate BIO_printf(bio_err,"invalid hex iv value\n"); 501*0Sstevel@tonic-gate goto end; 502*0Sstevel@tonic-gate } 503*0Sstevel@tonic-gate if ((hiv == NULL) && (str == NULL)) 504*0Sstevel@tonic-gate { 505*0Sstevel@tonic-gate /* No IV was explicitly set and no IV was generated 506*0Sstevel@tonic-gate * during EVP_BytesToKey. Hence the IV is undefined, 507*0Sstevel@tonic-gate * making correct decryption impossible. */ 508*0Sstevel@tonic-gate BIO_printf(bio_err, "iv undefined\n"); 509*0Sstevel@tonic-gate goto end; 510*0Sstevel@tonic-gate } 511*0Sstevel@tonic-gate if ((hkey != NULL) && !set_hex(hkey,key,sizeof key)) 512*0Sstevel@tonic-gate { 513*0Sstevel@tonic-gate BIO_printf(bio_err,"invalid hex key value\n"); 514*0Sstevel@tonic-gate goto end; 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate if ((benc=BIO_new(BIO_f_cipher())) == NULL) 518*0Sstevel@tonic-gate goto end; 519*0Sstevel@tonic-gate BIO_set_cipher(benc,cipher,key,iv,enc); 520*0Sstevel@tonic-gate if (nopad) 521*0Sstevel@tonic-gate { 522*0Sstevel@tonic-gate EVP_CIPHER_CTX *ctx; 523*0Sstevel@tonic-gate BIO_get_cipher_ctx(benc, &ctx); 524*0Sstevel@tonic-gate EVP_CIPHER_CTX_set_padding(ctx, 0); 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate if (debug) 527*0Sstevel@tonic-gate { 528*0Sstevel@tonic-gate BIO_set_callback(benc,BIO_debug_callback); 529*0Sstevel@tonic-gate BIO_set_callback_arg(benc,bio_err); 530*0Sstevel@tonic-gate } 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate if (printkey) 533*0Sstevel@tonic-gate { 534*0Sstevel@tonic-gate if (!nosalt) 535*0Sstevel@tonic-gate { 536*0Sstevel@tonic-gate printf("salt="); 537*0Sstevel@tonic-gate for (i=0; i<sizeof salt; i++) 538*0Sstevel@tonic-gate printf("%02X",salt[i]); 539*0Sstevel@tonic-gate printf("\n"); 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate if (cipher->key_len > 0) 542*0Sstevel@tonic-gate { 543*0Sstevel@tonic-gate printf("key="); 544*0Sstevel@tonic-gate for (i=0; i<cipher->key_len; i++) 545*0Sstevel@tonic-gate printf("%02X",key[i]); 546*0Sstevel@tonic-gate printf("\n"); 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate if (cipher->iv_len > 0) 549*0Sstevel@tonic-gate { 550*0Sstevel@tonic-gate printf("iv ="); 551*0Sstevel@tonic-gate for (i=0; i<cipher->iv_len; i++) 552*0Sstevel@tonic-gate printf("%02X",iv[i]); 553*0Sstevel@tonic-gate printf("\n"); 554*0Sstevel@tonic-gate } 555*0Sstevel@tonic-gate if (printkey == 2) 556*0Sstevel@tonic-gate { 557*0Sstevel@tonic-gate ret=0; 558*0Sstevel@tonic-gate goto end; 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate /* Only encrypt/decrypt as we write the file */ 564*0Sstevel@tonic-gate if (benc != NULL) 565*0Sstevel@tonic-gate wbio=BIO_push(benc,wbio); 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate for (;;) 568*0Sstevel@tonic-gate { 569*0Sstevel@tonic-gate inl=BIO_read(rbio,(char *)buff,bsize); 570*0Sstevel@tonic-gate if (inl <= 0) break; 571*0Sstevel@tonic-gate if (BIO_write(wbio,(char *)buff,inl) != inl) 572*0Sstevel@tonic-gate { 573*0Sstevel@tonic-gate BIO_printf(bio_err,"error writing output file\n"); 574*0Sstevel@tonic-gate goto end; 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate } 577*0Sstevel@tonic-gate if (!BIO_flush(wbio)) 578*0Sstevel@tonic-gate { 579*0Sstevel@tonic-gate BIO_printf(bio_err,"bad decrypt\n"); 580*0Sstevel@tonic-gate goto end; 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate ret=0; 584*0Sstevel@tonic-gate if (verbose) 585*0Sstevel@tonic-gate { 586*0Sstevel@tonic-gate BIO_printf(bio_err,"bytes read :%8ld\n",BIO_number_read(in)); 587*0Sstevel@tonic-gate BIO_printf(bio_err,"bytes written:%8ld\n",BIO_number_written(out)); 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate end: 590*0Sstevel@tonic-gate ERR_print_errors(bio_err); 591*0Sstevel@tonic-gate if (strbuf != NULL) OPENSSL_free(strbuf); 592*0Sstevel@tonic-gate if (buff != NULL) OPENSSL_free(buff); 593*0Sstevel@tonic-gate if (in != NULL) BIO_free(in); 594*0Sstevel@tonic-gate if (out != NULL) BIO_free_all(out); 595*0Sstevel@tonic-gate if (benc != NULL) BIO_free(benc); 596*0Sstevel@tonic-gate if (b64 != NULL) BIO_free(b64); 597*0Sstevel@tonic-gate if(pass) OPENSSL_free(pass); 598*0Sstevel@tonic-gate apps_shutdown(); 599*0Sstevel@tonic-gate OPENSSL_EXIT(ret); 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate int set_hex(char *in, unsigned char *out, int size) 603*0Sstevel@tonic-gate { 604*0Sstevel@tonic-gate int i,n; 605*0Sstevel@tonic-gate unsigned char j; 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate n=strlen(in); 608*0Sstevel@tonic-gate if (n > (size*2)) 609*0Sstevel@tonic-gate { 610*0Sstevel@tonic-gate BIO_printf(bio_err,"hex string is too long\n"); 611*0Sstevel@tonic-gate return(0); 612*0Sstevel@tonic-gate } 613*0Sstevel@tonic-gate memset(out,0,size); 614*0Sstevel@tonic-gate for (i=0; i<n; i++) 615*0Sstevel@tonic-gate { 616*0Sstevel@tonic-gate j=(unsigned char)*in; 617*0Sstevel@tonic-gate *(in++)='\0'; 618*0Sstevel@tonic-gate if (j == 0) break; 619*0Sstevel@tonic-gate if ((j >= '0') && (j <= '9')) 620*0Sstevel@tonic-gate j-='0'; 621*0Sstevel@tonic-gate else if ((j >= 'A') && (j <= 'F')) 622*0Sstevel@tonic-gate j=j-'A'+10; 623*0Sstevel@tonic-gate else if ((j >= 'a') && (j <= 'f')) 624*0Sstevel@tonic-gate j=j-'a'+10; 625*0Sstevel@tonic-gate else 626*0Sstevel@tonic-gate { 627*0Sstevel@tonic-gate BIO_printf(bio_err,"non-hex digit\n"); 628*0Sstevel@tonic-gate return(0); 629*0Sstevel@tonic-gate } 630*0Sstevel@tonic-gate if (i&1) 631*0Sstevel@tonic-gate out[i/2]|=j; 632*0Sstevel@tonic-gate else 633*0Sstevel@tonic-gate out[i/2]=(j<<4); 634*0Sstevel@tonic-gate } 635*0Sstevel@tonic-gate return(1); 636*0Sstevel@tonic-gate } 637