/* {{{ proto string Crypto\Base64::encode(string $data) Encodes string $data to base64 encoding */ PHP_CRYPTO_METHOD(Base64, encode) { char *in; phpc_str_size_t in_len; int real_len, final_len, update_len; PHPC_STR_DECLARE(out); EVP_ENCODE_CTX *ctx; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in, &in_len) == FAILURE) { return; } ctx = EVP_ENCODE_CTX_new(); php_crypto_base64_encode_init(ctx); real_len = EVP_ENCODE_LENGTH(in_len); PHPC_STR_ALLOC(out, real_len); if (php_crypto_base64_encode_update( ctx, PHPC_STR_VAL(out), &update_len, in, in_len TSRMLS_CC) == FAILURE) { PHPC_STR_RELEASE(out); EVP_ENCODE_CTX_free(ctx); RETURN_NULL(); } php_crypto_base64_encode_finish(ctx, PHPC_STR_VAL(out) + update_len, &final_len); EVP_ENCODE_CTX_free(ctx); final_len += update_len; if (real_len > final_len) { PHPC_STR_REALLOC(out, final_len); } PHPC_STR_VAL(out)[final_len] = '\0'; PHPC_STR_RETURN(out); }
/* {{{ proto Crypto\Base64::encode(string $data) Encodes block of characters from $data and saves the reminder of the last block to the encoding context */ PHP_CRYPTO_METHOD(Base64, encodeUpdate) { char *in; phpc_str_size_t in_len; int update_len, real_len; PHPC_STR_DECLARE(out); PHPC_THIS_DECLARE(crypto_base64); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in, &in_len) == FAILURE) { return; } PHPC_THIS_FETCH(crypto_base64); if (PHPC_THIS->status == PHP_CRYPTO_BASE64_STATUS_DECODE) { php_crypto_error(PHP_CRYPTO_ERROR_ARGS(Base64, ENCODE_UPDATE_FORBIDDEN)); RETURN_FALSE; } if (PHPC_THIS->status == PHP_CRYPTO_BASE64_STATUS_CLEAR) { php_crypto_base64_encode_init(PHPC_THIS->ctx); PHPC_THIS->status = PHP_CRYPTO_BASE64_STATUS_ENCODE; } real_len = EVP_ENCODE_LENGTH(in_len); PHPC_STR_ALLOC(out, real_len); if (php_crypto_base64_encode_update(PHPC_THIS->ctx, PHPC_STR_VAL(out), &update_len, in, in_len TSRMLS_CC) == FAILURE) { PHPC_STR_RELEASE(out); RETURN_NULL(); } if (real_len > update_len) { PHPC_STR_REALLOC(out, update_len); } PHPC_STR_VAL(out)[update_len] = '\0'; PHPC_STR_RETURN(out); }
int MAIN(int argc, char **argv) { static const char magic[]="Salted__"; char mbuf[sizeof magic-1]; char *strbuf=NULL; unsigned char *buff=NULL,*bufsize=NULL; int bsize=BSIZE,verbose=0; int ret=1,inl; int nopad = 0; unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH]; unsigned char salt[PKCS5_SALT_LEN]; char *str=NULL, *passarg = NULL, *pass = NULL; char *hkey=NULL,*hiv=NULL,*hsalt = NULL; char *md=NULL; int enc=1,printkey=0,i,base64=0; #ifdef ZLIB int do_zlib=0; BIO *bzl = NULL; #endif int debug=0,olb64=0,nosalt=0; const EVP_CIPHER *cipher=NULL,*c; EVP_CIPHER_CTX *ctx = NULL; char *inf=NULL,*outf=NULL; BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL; #define PROG_NAME_SIZE 39 char pname[PROG_NAME_SIZE+1]; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif const EVP_MD *dgst=NULL; int non_fips_allow = 0; apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; /* first check the program name */ program_name(argv[0],pname,sizeof pname); if (strcmp(pname,"base64") == 0) base64=1; #ifdef ZLIB if (strcmp(pname,"zlib") == 0) do_zlib=1; #endif cipher=EVP_get_cipherbyname(pname); #ifdef ZLIB if (!do_zlib && !base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0)) #else if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0)) #endif { BIO_printf(bio_err,"%s is an unknown cipher\n",pname); goto bad; } argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-e") == 0) enc=1; else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; inf= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outf= *(++argv); } else if (strcmp(*argv,"-pass") == 0) { if (--argc < 1) goto bad; passarg= *(++argv); } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-d") == 0) enc=0; else if (strcmp(*argv,"-p") == 0) printkey=1; else if (strcmp(*argv,"-v") == 0) verbose=1; else if (strcmp(*argv,"-nopad") == 0) nopad=1; else if (strcmp(*argv,"-salt") == 0) nosalt=0; else if (strcmp(*argv,"-nosalt") == 0) nosalt=1; else if (strcmp(*argv,"-debug") == 0) debug=1; else if (strcmp(*argv,"-P") == 0) printkey=2; else if (strcmp(*argv,"-A") == 0) olb64=1; else if (strcmp(*argv,"-a") == 0) base64=1; else if (strcmp(*argv,"-base64") == 0) base64=1; #ifdef ZLIB else if (strcmp(*argv,"-z") == 0) do_zlib=1; #endif else if (strcmp(*argv,"-bufsize") == 0) { if (--argc < 1) goto bad; bufsize=(unsigned char *)*(++argv); } else if (strcmp(*argv,"-k") == 0) { if (--argc < 1) goto bad; str= *(++argv); } else if (strcmp(*argv,"-kfile") == 0) { static char buf[128]; FILE *infile; char *file; if (--argc < 1) goto bad; file= *(++argv); infile=fopen(file,"r"); if (infile == NULL) { BIO_printf(bio_err,"unable to read key from '%s'\n", file); goto bad; } buf[0]='\0'; if (!fgets(buf,sizeof buf,infile)) { BIO_printf(bio_err,"unable to read key from '%s'\n", file); goto bad; } fclose(infile); i=strlen(buf); if ((i > 0) && ((buf[i-1] == '\n') || (buf[i-1] == '\r'))) buf[--i]='\0'; if ((i > 0) && ((buf[i-1] == '\n') || (buf[i-1] == '\r'))) buf[--i]='\0'; if (i < 1) { BIO_printf(bio_err,"zero length password\n"); goto bad; } str=buf; } else if (strcmp(*argv,"-K") == 0) { if (--argc < 1) goto bad; hkey= *(++argv); } else if (strcmp(*argv,"-S") == 0) { if (--argc < 1) goto bad; hsalt= *(++argv); } else if (strcmp(*argv,"-iv") == 0) { if (--argc < 1) goto bad; hiv= *(++argv); } else if (strcmp(*argv,"-md") == 0) { if (--argc < 1) goto bad; md= *(++argv); } else if (strcmp(*argv,"-non-fips-allow") == 0) non_fips_allow = 1; else if ((argv[0][0] == '-') && ((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL)) { cipher=c; } else if (strcmp(*argv,"-none") == 0) cipher=NULL; else { BIO_printf(bio_err,"unknown option '%s'\n",*argv); bad: BIO_printf(bio_err,"options are\n"); BIO_printf(bio_err,"%-14s input file\n","-in <file>"); BIO_printf(bio_err,"%-14s output file\n","-out <file>"); BIO_printf(bio_err,"%-14s pass phrase source\n","-pass <arg>"); BIO_printf(bio_err,"%-14s encrypt\n","-e"); BIO_printf(bio_err,"%-14s decrypt\n","-d"); BIO_printf(bio_err,"%-14s base64 encode/decode, depending on encryption flag\n","-a/-base64"); BIO_printf(bio_err,"%-14s passphrase is the next argument\n","-k"); BIO_printf(bio_err,"%-14s passphrase is the first line of the file argument\n","-kfile"); BIO_printf(bio_err,"%-14s the next argument is the md to use to create a key\n","-md"); BIO_printf(bio_err,"%-14s from a passphrase. One of md2, md5, sha or sha1\n",""); BIO_printf(bio_err,"%-14s salt in hex is the next argument\n","-S"); BIO_printf(bio_err,"%-14s key/iv in hex is the next argument\n","-K/-iv"); BIO_printf(bio_err,"%-14s print the iv/key (then exit if -P)\n","-[pP]"); BIO_printf(bio_err,"%-14s buffer size\n","-bufsize <n>"); BIO_printf(bio_err,"%-14s disable standard block padding\n","-nopad"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err,"%-14s use engine e, possibly a hardware device.\n","-engine e"); #endif BIO_printf(bio_err,"Cipher Types\n"); OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_ciphers, bio_err); BIO_printf(bio_err,"\n"); goto end; } argc--; argv++; } #ifndef OPENSSL_NO_ENGINE setup_engine(bio_err, engine, 0); #endif if (md && (dgst=EVP_get_digestbyname(md)) == NULL) { BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); goto end; } if (dgst == NULL) { dgst = EVP_md5(); } if (bufsize != NULL) { unsigned long n; for (n=0; *bufsize; bufsize++) { i= *bufsize; if ((i <= '9') && (i >= '0')) n=n*10+i-'0'; else if (i == 'k') { n*=1024; bufsize++; break; } } if (*bufsize != '\0') { BIO_printf(bio_err,"invalid 'bufsize' specified.\n"); goto end; } /* It must be large enough for a base64 encoded line */ if (base64 && n < 80) n=80; bsize=(int)n; if (verbose) BIO_printf(bio_err,"bufsize=%d\n",bsize); } strbuf=OPENSSL_malloc(SIZE); buff=(unsigned char *)OPENSSL_malloc(EVP_ENCODE_LENGTH(bsize)); if ((buff == NULL) || (strbuf == NULL)) { BIO_printf(bio_err,"OPENSSL_malloc failure %ld\n",(long)EVP_ENCODE_LENGTH(bsize)); goto end; } in=BIO_new(BIO_s_file()); out=BIO_new(BIO_s_file()); if ((in == NULL) || (out == NULL)) { ERR_print_errors(bio_err); goto end; } if (debug) { BIO_set_callback(in,BIO_debug_callback); BIO_set_callback(out,BIO_debug_callback); BIO_set_callback_arg(in,(char *)bio_err); BIO_set_callback_arg(out,(char *)bio_err); } if (inf == NULL) { #ifndef OPENSSL_NO_SETVBUF_IONBF if (bufsize != NULL) setvbuf(stdin, (char *)NULL, _IONBF, 0); #endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ BIO_set_fp(in,stdin,BIO_NOCLOSE); } else { if (BIO_read_filename(in,inf) <= 0) { perror(inf); goto end; } } if(!str && passarg) { if(!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } str = pass; } if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) { for (;;) { char buf[200]; BIO_snprintf(buf,sizeof buf,"enter %s %s password:"******"encryption":"decryption"); strbuf[0]='\0'; i=EVP_read_pw_string((char *)strbuf,SIZE,buf,enc); if (i == 0) { if (strbuf[0] == '\0') { ret=1; goto end; } str=strbuf; break; } if (i < 0) { BIO_printf(bio_err,"bad password read\n"); goto end; } } } if (outf == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifndef OPENSSL_NO_SETVBUF_IONBF if (bufsize != NULL) setvbuf(stdout, (char *)NULL, _IONBF, 0); #endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outf) <= 0) { perror(outf); goto end; } } rbio=in; wbio=out; #ifdef ZLIB if (do_zlib) { if ((bzl=BIO_new(BIO_f_zlib())) == NULL) goto end; if (enc) wbio=BIO_push(bzl,wbio); else rbio=BIO_push(bzl,rbio); } #endif if (base64) { if ((b64=BIO_new(BIO_f_base64())) == NULL) goto end; if (debug) { BIO_set_callback(b64,BIO_debug_callback); BIO_set_callback_arg(b64,(char *)bio_err); } if (olb64) BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL); if (enc) wbio=BIO_push(b64,wbio); else rbio=BIO_push(b64,rbio); } if (cipher != NULL) { /* Note that str is NULL if a key was passed on the command * line, so we get no salt in that case. Is this a bug? */ if (str != NULL) { /* Salt handling: if encrypting generate a salt and * write to output BIO. If decrypting read salt from * input BIO. */ unsigned char *sptr; if(nosalt) sptr = NULL; else { if(enc) { if(hsalt) { if(!set_hex(hsalt,salt,sizeof salt)) { BIO_printf(bio_err, "invalid hex salt value\n"); goto end; } } else if (RAND_pseudo_bytes(salt, sizeof salt) < 0) goto end; /* If -P option then don't bother writing */ if((printkey != 2) && (BIO_write(wbio,magic, sizeof magic-1) != sizeof magic-1 || BIO_write(wbio, (char *)salt, sizeof salt) != sizeof salt)) { BIO_printf(bio_err,"error writing output file\n"); goto end; } } else if(BIO_read(rbio,mbuf,sizeof mbuf) != sizeof mbuf || BIO_read(rbio, (unsigned char *)salt, sizeof salt) != sizeof salt) { BIO_printf(bio_err,"error reading input file\n"); goto end; } else if(memcmp(mbuf,magic,sizeof magic-1)) { BIO_printf(bio_err,"bad magic number\n"); goto end; } sptr = salt; } EVP_BytesToKey(cipher,dgst,sptr, (unsigned char *)str, strlen(str),1,key,iv); /* zero the complete buffer or the string * passed from the command line * bug picked up by * Larry J. Hughes Jr. <*****@*****.**> */ if (str == strbuf) OPENSSL_cleanse(str,SIZE); else OPENSSL_cleanse(str,strlen(str)); } if ((hiv != NULL) && !set_hex(hiv,iv,sizeof iv)) { BIO_printf(bio_err,"invalid hex iv value\n"); goto end; } if ((hiv == NULL) && (str == NULL) && EVP_CIPHER_iv_length(cipher) != 0) { /* No IV was explicitly set and no IV was generated * during EVP_BytesToKey. Hence the IV is undefined, * making correct decryption impossible. */ BIO_printf(bio_err, "iv undefined\n"); goto end; } if ((hkey != NULL) && !set_hex(hkey,key,sizeof key)) { BIO_printf(bio_err,"invalid hex key value\n"); goto end; } if ((benc=BIO_new(BIO_f_cipher())) == NULL) goto end; /* Since we may be changing parameters work on the encryption * context rather than calling BIO_set_cipher(). */ BIO_get_cipher_ctx(benc, &ctx); if (non_fips_allow) EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW); if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", EVP_CIPHER_name(cipher)); ERR_print_errors(bio_err); goto end; } if (nopad) EVP_CIPHER_CTX_set_padding(ctx, 0); if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", EVP_CIPHER_name(cipher)); ERR_print_errors(bio_err); goto end; } if (debug) { BIO_set_callback(benc,BIO_debug_callback); BIO_set_callback_arg(benc,(char *)bio_err); } if (printkey) { if (!nosalt) { printf("salt="); for (i=0; i<(int)sizeof(salt); i++) printf("%02X",salt[i]); printf("\n"); } if (cipher->key_len > 0) { printf("key="); for (i=0; i<cipher->key_len; i++) printf("%02X",key[i]); printf("\n"); } if (cipher->iv_len > 0) { printf("iv ="); for (i=0; i<cipher->iv_len; i++) printf("%02X",iv[i]); printf("\n"); } if (printkey == 2) { ret=0; goto end; } } } /* Only encrypt/decrypt as we write the file */ if (benc != NULL) wbio=BIO_push(benc,wbio); for (;;) { inl=BIO_read(rbio,(char *)buff,bsize); if (inl <= 0) break; if (BIO_write(wbio,(char *)buff,inl) != inl) { BIO_printf(bio_err,"error writing output file\n"); goto end; } } if (!BIO_flush(wbio)) { BIO_printf(bio_err,"bad decrypt\n"); goto end; } ret=0; if (verbose) { BIO_printf(bio_err,"bytes read :%8ld\n",BIO_number_read(in)); BIO_printf(bio_err,"bytes written:%8ld\n",BIO_number_written(out)); } end: ERR_print_errors(bio_err); if (strbuf != NULL) OPENSSL_free(strbuf); if (buff != NULL) OPENSSL_free(buff); if (in != NULL) BIO_free(in); if (out != NULL) BIO_free_all(out); if (benc != NULL) BIO_free(benc); if (b64 != NULL) BIO_free(b64); #ifdef ZLIB if (bzl != NULL) BIO_free(bzl); #endif if(pass) OPENSSL_free(pass); apps_shutdown(); OPENSSL_EXIT(ret); }
int enc_main(int argc, char **argv) { static const char magic[] = "Salted__"; char mbuf[sizeof magic - 1]; char *strbuf = NULL, *pass = NULL; unsigned char *buff = NULL; int bsize = BSIZE; int ret = 1, inl; unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; unsigned char salt[PKCS5_SALT_LEN]; #ifdef ZLIB BIO *bzl = NULL; #endif EVP_CIPHER_CTX *ctx = NULL; const EVP_MD *dgst = NULL; BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL; BIO *rbio = NULL, *wbio = NULL; #define PROG_NAME_SIZE 39 char pname[PROG_NAME_SIZE + 1]; int i; if (single_execution) { if (pledge("stdio rpath wpath cpath tty", NULL) == -1) { perror("pledge"); exit(1); } } memset(&enc_config, 0, sizeof(enc_config)); enc_config.enc = 1; /* first check the program name */ program_name(argv[0], pname, sizeof(pname)); if (strcmp(pname, "base64") == 0) enc_config.base64 = 1; #ifdef ZLIB if (strcmp(pname, "zlib") == 0) enc_config.do_zlib = 1; #endif enc_config.cipher = EVP_get_cipherbyname(pname); #ifdef ZLIB if (!enc_config.do_zlib && !enc_config.base64 && enc_config.cipher == NULL && strcmp(pname, "enc") != 0) #else if (!enc_config.base64 && enc_config.cipher == NULL && strcmp(pname, "enc") != 0) #endif { BIO_printf(bio_err, "%s is an unknown cipher\n", pname); goto end; } if (options_parse(argc, argv, enc_options, NULL, NULL) != 0) { enc_usage(); goto end; } if (enc_config.keyfile != NULL) { static char buf[128]; FILE *infile; infile = fopen(enc_config.keyfile, "r"); if (infile == NULL) { BIO_printf(bio_err, "unable to read key from '%s'\n", enc_config.keyfile); goto end; } buf[0] = '\0'; if (!fgets(buf, sizeof buf, infile)) { BIO_printf(bio_err, "unable to read key from '%s'\n", enc_config.keyfile); fclose(infile); goto end; } fclose(infile); i = strlen(buf); if ((i > 0) && ((buf[i - 1] == '\n') || (buf[i - 1] == '\r'))) buf[--i] = '\0'; if ((i > 0) && ((buf[i - 1] == '\n') || (buf[i - 1] == '\r'))) buf[--i] = '\0'; if (i < 1) { BIO_printf(bio_err, "zero length password\n"); goto end; } enc_config.keystr = buf; } if (enc_config.md != NULL && (dgst = EVP_get_digestbyname(enc_config.md)) == NULL) { BIO_printf(bio_err, "%s is an unsupported message digest type\n", enc_config.md); goto end; } if (dgst == NULL) { dgst = EVP_md5(); /* XXX */ } if (enc_config.bufsize != NULL) { char *p = enc_config.bufsize; unsigned long n; /* XXX - provide an OPTION_ARG_DISKUNIT. */ for (n = 0; *p != '\0'; p++) { i = *p; if ((i <= '9') && (i >= '0')) n = n * 10 + i - '0'; else if (i == 'k') { n *= 1024; p++; break; } } if (*p != '\0') { BIO_printf(bio_err, "invalid 'bufsize' specified.\n"); goto end; } /* It must be large enough for a base64 encoded line. */ if (enc_config.base64 && n < 80) n = 80; bsize = (int)n; if (enc_config.verbose) BIO_printf(bio_err, "bufsize=%d\n", bsize); } strbuf = malloc(SIZE); buff = malloc(EVP_ENCODE_LENGTH(bsize)); if ((buff == NULL) || (strbuf == NULL)) { BIO_printf(bio_err, "malloc failure %ld\n", (long) EVP_ENCODE_LENGTH(bsize)); goto end; } in = BIO_new(BIO_s_file()); out = BIO_new(BIO_s_file()); if ((in == NULL) || (out == NULL)) { ERR_print_errors(bio_err); goto end; } if (enc_config.debug) { BIO_set_callback(in, BIO_debug_callback); BIO_set_callback(out, BIO_debug_callback); BIO_set_callback_arg(in, (char *) bio_err); BIO_set_callback_arg(out, (char *) bio_err); } if (enc_config.inf == NULL) { if (enc_config.bufsize != NULL) setvbuf(stdin, (char *) NULL, _IONBF, 0); BIO_set_fp(in, stdin, BIO_NOCLOSE); } else { if (BIO_read_filename(in, enc_config.inf) <= 0) { perror(enc_config.inf); goto end; } } if (!enc_config.keystr && enc_config.passarg) { if (!app_passwd(bio_err, enc_config.passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } enc_config.keystr = pass; } if (enc_config.keystr == NULL && enc_config.cipher != NULL && enc_config.hkey == NULL) { for (;;) { char buf[200]; int retval; retval = snprintf(buf, sizeof buf, "enter %s %s password:"******"encryption" : "decryption"); if ((size_t)retval >= sizeof buf) { BIO_printf(bio_err, "Password prompt too long\n"); goto end; } strbuf[0] = '\0'; i = EVP_read_pw_string((char *)strbuf, SIZE, buf, enc_config.enc); if (i == 0) { if (strbuf[0] == '\0') { ret = 1; goto end; } enc_config.keystr = strbuf; break; } if (i < 0) { BIO_printf(bio_err, "bad password read\n"); goto end; } } } if (enc_config.outf == NULL) { BIO_set_fp(out, stdout, BIO_NOCLOSE); if (enc_config.bufsize != NULL) setvbuf(stdout, (char *)NULL, _IONBF, 0); } else { if (BIO_write_filename(out, enc_config.outf) <= 0) { perror(enc_config.outf); goto end; } } rbio = in; wbio = out; #ifdef ZLIB if (do_zlib) { if ((bzl = BIO_new(BIO_f_zlib())) == NULL) goto end; if (enc) wbio = BIO_push(bzl, wbio); else rbio = BIO_push(bzl, rbio); } #endif if (enc_config.base64) { if ((b64 = BIO_new(BIO_f_base64())) == NULL) goto end; if (enc_config.debug) { BIO_set_callback(b64, BIO_debug_callback); BIO_set_callback_arg(b64, (char *) bio_err); } if (enc_config.olb64) BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); if (enc_config.enc) wbio = BIO_push(b64, wbio); else rbio = BIO_push(b64, rbio); } if (enc_config.cipher != NULL) { /* * Note that keystr is NULL if a key was passed on the command * line, so we get no salt in that case. Is this a bug? */ if (enc_config.keystr != NULL) { /* * Salt handling: if encrypting generate a salt and * write to output BIO. If decrypting read salt from * input BIO. */ unsigned char *sptr; if (enc_config.nosalt) sptr = NULL; else { if (enc_config.enc) { if (enc_config.hsalt) { if (!set_hex(enc_config.hsalt, salt, sizeof salt)) { BIO_printf(bio_err, "invalid hex salt value\n"); goto end; } } else arc4random_buf(salt, sizeof(salt)); /* * If -P option then don't bother * writing */ if ((enc_config.printkey != 2) && (BIO_write(wbio, magic, sizeof magic - 1) != sizeof magic - 1 || BIO_write(wbio, (char *) salt, sizeof salt) != sizeof salt)) { BIO_printf(bio_err, "error writing output file\n"); goto end; } } else if (BIO_read(rbio, mbuf, sizeof mbuf) != sizeof mbuf || BIO_read(rbio, (unsigned char *) salt, sizeof salt) != sizeof salt) { BIO_printf(bio_err, "error reading input file\n"); goto end; } else if (memcmp(mbuf, magic, sizeof magic - 1)) { BIO_printf(bio_err, "bad magic number\n"); goto end; } sptr = salt; } EVP_BytesToKey(enc_config.cipher, dgst, sptr, (unsigned char *)enc_config.keystr, strlen(enc_config.keystr), 1, key, iv); /* * zero the complete buffer or the string passed from * the command line bug picked up by Larry J. Hughes * Jr. <*****@*****.**> */ if (enc_config.keystr == strbuf) explicit_bzero(enc_config.keystr, SIZE); else explicit_bzero(enc_config.keystr, strlen(enc_config.keystr)); } if (enc_config.hiv != NULL && !set_hex(enc_config.hiv, iv, sizeof iv)) { BIO_printf(bio_err, "invalid hex iv value\n"); goto end; } if (enc_config.hiv == NULL && enc_config.keystr == NULL && EVP_CIPHER_iv_length(enc_config.cipher) != 0) { /* * No IV was explicitly set and no IV was generated * during EVP_BytesToKey. Hence the IV is undefined, * making correct decryption impossible. */ BIO_printf(bio_err, "iv undefined\n"); goto end; } if (enc_config.hkey != NULL && !set_hex(enc_config.hkey, key, sizeof key)) { BIO_printf(bio_err, "invalid hex key value\n"); goto end; } if ((benc = BIO_new(BIO_f_cipher())) == NULL) goto end; /* * Since we may be changing parameters work on the encryption * context rather than calling BIO_set_cipher(). */ BIO_get_cipher_ctx(benc, &ctx); if (!EVP_CipherInit_ex(ctx, enc_config.cipher, NULL, NULL, NULL, enc_config.enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", EVP_CIPHER_name(enc_config.cipher)); ERR_print_errors(bio_err); goto end; } if (enc_config.nopad) EVP_CIPHER_CTX_set_padding(ctx, 0); if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc_config.enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", EVP_CIPHER_name(enc_config.cipher)); ERR_print_errors(bio_err); goto end; } if (enc_config.debug) { BIO_set_callback(benc, BIO_debug_callback); BIO_set_callback_arg(benc, (char *) bio_err); } if (enc_config.printkey) { if (!enc_config.nosalt) { printf("salt="); for (i = 0; i < (int) sizeof(salt); i++) printf("%02X", salt[i]); printf("\n"); } if (enc_config.cipher->key_len > 0) { printf("key="); for (i = 0; i < enc_config.cipher->key_len; i++) printf("%02X", key[i]); printf("\n"); } if (enc_config.cipher->iv_len > 0) { printf("iv ="); for (i = 0; i < enc_config.cipher->iv_len; i++) printf("%02X", iv[i]); printf("\n"); } if (enc_config.printkey == 2) { ret = 0; goto end; } } } /* Only encrypt/decrypt as we write the file */ if (benc != NULL) wbio = BIO_push(benc, wbio); for (;;) { inl = BIO_read(rbio, (char *) buff, bsize); if (inl <= 0) break; if (BIO_write(wbio, (char *) buff, inl) != inl) { BIO_printf(bio_err, "error writing output file\n"); goto end; } } if (!BIO_flush(wbio)) { BIO_printf(bio_err, "bad decrypt\n"); goto end; } ret = 0; if (enc_config.verbose) { BIO_printf(bio_err, "bytes read :%8ld\n", BIO_number_read(in)); BIO_printf(bio_err, "bytes written:%8ld\n", BIO_number_written(out)); } end: ERR_print_errors(bio_err); free(strbuf); free(buff); BIO_free(in); if (out != NULL) BIO_free_all(out); BIO_free(benc); BIO_free(b64); #ifdef ZLIB BIO_free(bzl); #endif free(pass); return (ret); }
int enc_main(int argc, char **argv) { static char buf[128]; static const char magic[] = "Salted__"; BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio = NULL, *wbio = NULL; EVP_CIPHER_CTX *ctx = NULL; const EVP_CIPHER *cipher = NULL, *c; const EVP_MD *dgst = NULL; char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p; char *infile = NULL, *outfile = NULL, *prog; char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL; char mbuf[sizeof magic - 1]; OPTION_CHOICE o; int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0; int enc = 1, printkey = 0, i, k; int base64 = 0, informat = FORMAT_BINARY, outformat = FORMAT_BINARY; int ret = 1, inl, nopad = 0, non_fips_allow = 0; unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; unsigned char *buff = NULL, salt[PKCS5_SALT_LEN]; unsigned long n; #ifdef ZLIB int do_zlib = 0; BIO *bzl = NULL; #endif /* first check the program name */ prog = opt_progname(argv[0]); if (strcmp(prog, "base64") == 0) base64 = 1; #ifdef ZLIB else if (strcmp(prog, "zlib") == 0) do_zlib = 1; #endif else { cipher = EVP_get_cipherbyname(prog); if (cipher == NULL && strcmp(prog, "enc") != 0) { BIO_printf(bio_err, "%s is not a known cipher\n", prog); goto end; } } prog = opt_init(argc, argv, enc_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(enc_options); ret = 0; BIO_printf(bio_err, "Cipher Types\n"); OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_ciphers, bio_err); BIO_printf(bio_err, "\n"); goto end; case OPT_E: enc = 1; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUT: outfile = opt_arg(); break; case OPT_PASS: passarg = opt_arg(); break; case OPT_ENGINE: (void)setup_engine(opt_arg(), 0); break; case OPT_D: enc = 0; break; case OPT_P: printkey = 1; break; case OPT_V: verbose = 1; break; case OPT_NOPAD: nopad = 1; break; case OPT_SALT: nosalt = 0; break; case OPT_NOSALT: nosalt = 1; break; case OPT_DEBUG: debug = 1; break; case OPT_UPPER_P: printkey = 2; break; case OPT_UPPER_A: olb64 = 1; break; case OPT_A: base64 = 1; break; case OPT_Z: #ifdef ZLIB do_zlib = 1; #endif break; case OPT_BUFSIZE: p = opt_arg(); i = (int)strlen(p) - 1; k = i >= 1 && p[i] == 'k'; if (k) p[i] = '\0'; if (!opt_ulong(opt_arg(), &n)) goto opthelp; if (k) n *= 1024; bsize = (int)n; break; case OPT_K: str = opt_arg(); break; case OPT_KFILE: in = bio_open_default(opt_arg(), 'r', FORMAT_TEXT); if (in == NULL) goto opthelp; i = BIO_gets(in, buf, sizeof buf); BIO_free(in); in = NULL; if (i <= 0) { BIO_printf(bio_err, "%s Can't read key from %s\n", prog, opt_arg()); goto opthelp; } while (--i > 0 && (buf[i] == '\r' || buf[i] == '\n')) buf[i] = '\0'; if (i <= 0) { BIO_printf(bio_err, "%s: zero length password\n", prog); goto opthelp; } str = buf; break; case OPT_UPPER_K: hkey = opt_arg(); break; case OPT_UPPER_S: hsalt = opt_arg(); break; case OPT_IV: hiv = opt_arg(); break; case OPT_MD: if (!opt_md(opt_arg(), &dgst)) goto opthelp; break; case OPT_NON_FIPS_ALLOW: non_fips_allow = 1; break; case OPT_CIPHER: if (!opt_cipher(opt_unknown(), &c)) goto opthelp; cipher = c; break; case OPT_NONE: cipher = NULL; break; } } argc = opt_num_rest(); argv = opt_rest(); if (cipher && EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) { BIO_printf(bio_err, "%s: AEAD ciphers not supported\n", prog); goto end; } if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) { BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog); goto end; } if (dgst == NULL) dgst = EVP_sha256(); /* It must be large enough for a base64 encoded line */ if (base64 && bsize < 80) bsize = 80; if (verbose) BIO_printf(bio_err, "bufsize=%d\n", bsize); if (base64) { if (enc) outformat = FORMAT_BASE64; else informat = FORMAT_BASE64; } strbuf = app_malloc(SIZE, "strbuf"); buff = app_malloc(EVP_ENCODE_LENGTH(bsize), "evp buffer"); if (debug) { BIO_set_callback(in, BIO_debug_callback); BIO_set_callback(out, BIO_debug_callback); BIO_set_callback_arg(in, (char *)bio_err); BIO_set_callback_arg(out, (char *)bio_err); } if (infile == NULL) { unbuffer(stdin); in = dup_bio_in(informat); } else in = bio_open_default(infile, 'r', informat); if (in == NULL) goto end; if (!str && passarg) { if (!app_passwd(passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } str = pass; } if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) { for (;;) { char prompt[200]; BIO_snprintf(prompt, sizeof prompt, "enter %s %s password:"******"encryption" : "decryption"); strbuf[0] = '\0'; i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc); if (i == 0) { if (strbuf[0] == '\0') { ret = 1; goto end; } str = strbuf; break; } if (i < 0) { BIO_printf(bio_err, "bad password read\n"); goto end; } } } out = bio_open_default(outfile, 'w', outformat); if (out == NULL) goto end; rbio = in; wbio = out; #ifdef ZLIB if (do_zlib) { if ((bzl = BIO_new(BIO_f_zlib())) == NULL) goto end; if (enc) wbio = BIO_push(bzl, wbio); else rbio = BIO_push(bzl, rbio); } #endif if (base64) { if ((b64 = BIO_new(BIO_f_base64())) == NULL) goto end; if (debug) { BIO_set_callback(b64, BIO_debug_callback); BIO_set_callback_arg(b64, (char *)bio_err); } if (olb64) BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); if (enc) wbio = BIO_push(b64, wbio); else rbio = BIO_push(b64, rbio); } if (cipher != NULL) { /* * Note that str is NULL if a key was passed on the command line, so * we get no salt in that case. Is this a bug? */ if (str != NULL) { /* * Salt handling: if encrypting generate a salt and write to * output BIO. If decrypting read salt from input BIO. */ unsigned char *sptr; if (nosalt) sptr = NULL; else { if (enc) { if (hsalt) { if (!set_hex(hsalt, salt, sizeof salt)) { BIO_printf(bio_err, "invalid hex salt value\n"); goto end; } } else if (RAND_bytes(salt, sizeof salt) <= 0) goto end; /* * If -P option then don't bother writing */ if ((printkey != 2) && (BIO_write(wbio, magic, sizeof magic - 1) != sizeof magic - 1 || BIO_write(wbio, (char *)salt, sizeof salt) != sizeof salt)) { BIO_printf(bio_err, "error writing output file\n"); goto end; } } else if (BIO_read(rbio, mbuf, sizeof mbuf) != sizeof mbuf || BIO_read(rbio, (unsigned char *)salt, sizeof salt) != sizeof salt) { BIO_printf(bio_err, "error reading input file\n"); goto end; } else if (memcmp(mbuf, magic, sizeof magic - 1)) { BIO_printf(bio_err, "bad magic number\n"); goto end; } sptr = salt; } if (!EVP_BytesToKey(cipher, dgst, sptr, (unsigned char *)str, strlen(str), 1, key, iv)) { BIO_printf(bio_err, "EVP_BytesToKey failed\n"); goto end; } /* * zero the complete buffer or the string passed from the command * line bug picked up by Larry J. Hughes Jr. <*****@*****.**> */ if (str == strbuf) OPENSSL_cleanse(str, SIZE); else OPENSSL_cleanse(str, strlen(str)); } if (hiv != NULL) { int siz = EVP_CIPHER_iv_length(cipher); if (siz == 0) { BIO_printf(bio_err, "warning: iv not use by this cipher\n"); } else if (!set_hex(hiv, iv, sizeof iv)) { BIO_printf(bio_err, "invalid hex iv value\n"); goto end; } } if ((hiv == NULL) && (str == NULL) && EVP_CIPHER_iv_length(cipher) != 0) { /* * No IV was explicitly set and no IV was generated during * EVP_BytesToKey. Hence the IV is undefined, making correct * decryption impossible. */ BIO_printf(bio_err, "iv undefined\n"); goto end; } if ((hkey != NULL) && !set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) { BIO_printf(bio_err, "invalid hex key value\n"); goto end; } if ((benc = BIO_new(BIO_f_cipher())) == NULL) goto end; /* * Since we may be changing parameters work on the encryption context * rather than calling BIO_set_cipher(). */ BIO_get_cipher_ctx(benc, &ctx); if (non_fips_allow) EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW); if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", EVP_CIPHER_name(cipher)); ERR_print_errors(bio_err); goto end; } if (nopad) EVP_CIPHER_CTX_set_padding(ctx, 0); if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) { BIO_printf(bio_err, "Error setting cipher %s\n", EVP_CIPHER_name(cipher)); ERR_print_errors(bio_err); goto end; } if (debug) { BIO_set_callback(benc, BIO_debug_callback); BIO_set_callback_arg(benc, (char *)bio_err); } if (printkey) { if (!nosalt) { printf("salt="); for (i = 0; i < (int)sizeof(salt); i++) printf("%02X", salt[i]); printf("\n"); } if (cipher->key_len > 0) { printf("key="); for (i = 0; i < cipher->key_len; i++) printf("%02X", key[i]); printf("\n"); } if (cipher->iv_len > 0) { printf("iv ="); for (i = 0; i < cipher->iv_len; i++) printf("%02X", iv[i]); printf("\n"); } if (printkey == 2) { ret = 0; goto end; } } } /* Only encrypt/decrypt as we write the file */ if (benc != NULL) wbio = BIO_push(benc, wbio); for (;;) { inl = BIO_read(rbio, (char *)buff, bsize); if (inl <= 0) break; if (BIO_write(wbio, (char *)buff, inl) != inl) { BIO_printf(bio_err, "error writing output file\n"); goto end; } } if (!BIO_flush(wbio)) { BIO_printf(bio_err, "bad decrypt\n"); goto end; } ret = 0; if (verbose) { BIO_printf(bio_err, "bytes read :%8"PRIu64"\n", BIO_number_read(in)); BIO_printf(bio_err, "bytes written:%8"PRIu64"\n", BIO_number_written(out)); } end: ERR_print_errors(bio_err); OPENSSL_free(strbuf); OPENSSL_free(buff); BIO_free(in); BIO_free_all(out); BIO_free(benc); BIO_free(b64); #ifdef ZLIB BIO_free(bzl); #endif OPENSSL_free(pass); return (ret); }
#define B64_NONE 0 #define B64_ENCODE 1 #define B64_DECODE 2 typedef struct b64_struct { /*BIO *bio; moved to the BIO structure */ int buf_len; int buf_off; int tmp_len; /* used to find the start when decoding */ int tmp_nl; /* If true, scan until '\n' */ int encode; int start; /* have we started decoding yet? */ int cont; /* <= 0 when finished */ EVP_ENCODE_CTX base64; char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE)+10]; char tmp[B64_BLOCK_SIZE]; } BIO_B64_CTX; static BIO_METHOD methods_b64= { .type = BIO_TYPE_BASE64, .name = "base64 encoding", .bwrite = b64_write, .bread = b64_read, .bputs = b64_puts, .ctrl = b64_ctrl, .create = b64_new, .destroy = b64_free, .callback_ctrl = b64_callback_ctrl };
int MAIN(int argc, char **argv) { static const char magic[]="Salted__"; char mbuf[8]; /* should be 1 smaller than magic */ char *strbuf=NULL; unsigned char *buff=NULL,*bufsize=NULL; int bsize=BSIZE,verbose=0; int ret=1,inl; unsigned char key[24],iv[MD5_DIGEST_LENGTH]; unsigned char salt[PKCS5_SALT_LEN]; char *str=NULL, *passarg = NULL, *pass = NULL; char *hkey=NULL,*hiv=NULL,*hsalt = NULL; int enc=1,printkey=0,i,base64=0; int debug=0,olb64=0,nosalt=0; const EVP_CIPHER *cipher=NULL,*c; char *inf=NULL,*outf=NULL; BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL; #define PROG_NAME_SIZE 39 char pname[PROG_NAME_SIZE+1]; apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); /* first check the program name */ program_name(argv[0],pname,PROG_NAME_SIZE); if (strcmp(pname,"base64") == 0) base64=1; cipher=EVP_get_cipherbyname(pname); if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0)) { BIO_printf(bio_err,"%s is an unknown cipher\n",pname); goto bad; } argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-e") == 0) enc=1; else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; inf= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outf= *(++argv); } else if (strcmp(*argv,"-pass") == 0) { if (--argc < 1) goto bad; passarg= *(++argv); } else if (strcmp(*argv,"-d") == 0) enc=0; else if (strcmp(*argv,"-p") == 0) printkey=1; else if (strcmp(*argv,"-v") == 0) verbose=1; else if (strcmp(*argv,"-salt") == 0) nosalt=0; else if (strcmp(*argv,"-nosalt") == 0) nosalt=1; else if (strcmp(*argv,"-debug") == 0) debug=1; else if (strcmp(*argv,"-P") == 0) printkey=2; else if (strcmp(*argv,"-A") == 0) olb64=1; else if (strcmp(*argv,"-a") == 0) base64=1; else if (strcmp(*argv,"-base64") == 0) base64=1; else if (strcmp(*argv,"-bufsize") == 0) { if (--argc < 1) goto bad; bufsize=(unsigned char *)*(++argv); } else if (strcmp(*argv,"-k") == 0) { if (--argc < 1) goto bad; str= *(++argv); } else if (strcmp(*argv,"-kfile") == 0) { static char buf[128]; FILE *infile; char *file; if (--argc < 1) goto bad; file= *(++argv); infile=fopen(file,"r"); if (infile == NULL) { BIO_printf(bio_err,"unable to read key from '%s'\n", file); goto bad; } buf[0]='\0'; fgets(buf,128,infile); fclose(infile); i=strlen(buf); if ((i > 0) && ((buf[i-1] == '\n') || (buf[i-1] == '\r'))) buf[--i]='\0'; if ((i > 0) && ((buf[i-1] == '\n') || (buf[i-1] == '\r'))) buf[--i]='\0'; if (i < 1) { BIO_printf(bio_err,"zero length password\n"); goto bad; } str=buf; } else if (strcmp(*argv,"-K") == 0) { if (--argc < 1) goto bad; hkey= *(++argv); } else if (strcmp(*argv,"-S") == 0) { if (--argc < 1) goto bad; hsalt= *(++argv); } else if (strcmp(*argv,"-iv") == 0) { if (--argc < 1) goto bad; hiv= *(++argv); } else if ((argv[0][0] == '-') && ((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL)) { cipher=c; } else if (strcmp(*argv,"-none") == 0) cipher=NULL; else { BIO_printf(bio_err,"unknown option '%s'\n",*argv); bad: BIO_printf(bio_err,"options are\n"); BIO_printf(bio_err,"%-14s input file\n","-in <file>"); BIO_printf(bio_err,"%-14s output file\n","-out <file>"); BIO_printf(bio_err,"%-14s pass phrase source\n","-pass <arg>"); BIO_printf(bio_err,"%-14s encrypt\n","-e"); BIO_printf(bio_err,"%-14s decrypt\n","-d"); BIO_printf(bio_err,"%-14s base64 encode/decode, depending on encryption flag\n","-a/-base64"); BIO_printf(bio_err,"%-14s key is the next argument\n","-k"); BIO_printf(bio_err,"%-14s key is the first line of the file argument\n","-kfile"); BIO_printf(bio_err,"%-14s key/iv in hex is the next argument\n","-K/-iv"); BIO_printf(bio_err,"%-14s print the iv/key (then exit if -P)\n","-[pP]"); BIO_printf(bio_err,"%-14s buffer size\n","-bufsize <n>"); BIO_printf(bio_err,"Cipher Types\n"); BIO_printf(bio_err,"des : 56 bit key DES encryption\n"); BIO_printf(bio_err,"des_ede :112 bit key ede DES encryption\n"); BIO_printf(bio_err,"des_ede3:168 bit key ede DES encryption\n"); #ifndef NO_IDEA BIO_printf(bio_err,"idea :128 bit key IDEA encryption\n"); #endif #ifndef NO_RC4 BIO_printf(bio_err,"rc2 :128 bit key RC2 encryption\n"); #endif #ifndef NO_BF BIO_printf(bio_err,"bf :128 bit key Blowfish encryption\n"); #endif #ifndef NO_RC4 BIO_printf(bio_err," -%-5s :128 bit key RC4 encryption\n", LN_rc4); #endif BIO_printf(bio_err," -%-12s -%-12s -%-12s -%-12s", LN_des_ecb,LN_des_cbc, LN_des_cfb64,LN_des_ofb64); BIO_printf(bio_err," -%-4s (%s)\n", "des", LN_des_cbc); BIO_printf(bio_err," -%-12s -%-12s -%-12s -%-12s", LN_des_ede,LN_des_ede_cbc, LN_des_ede_cfb64,LN_des_ede_ofb64); BIO_printf(bio_err," -desx -none\n"); BIO_printf(bio_err," -%-12s -%-12s -%-12s -%-12s", LN_des_ede3,LN_des_ede3_cbc, LN_des_ede3_cfb64,LN_des_ede3_ofb64); BIO_printf(bio_err," -%-4s (%s)\n", "des3", LN_des_ede3_cbc); #ifndef NO_IDEA BIO_printf(bio_err," -%-12s -%-12s -%-12s -%-12s", LN_idea_ecb, LN_idea_cbc, LN_idea_cfb64, LN_idea_ofb64); BIO_printf(bio_err," -%-4s (%s)\n","idea",LN_idea_cbc); #endif #ifndef NO_RC2 BIO_printf(bio_err," -%-12s -%-12s -%-12s -%-12s", LN_rc2_ecb, LN_rc2_cbc, LN_rc2_cfb64, LN_rc2_ofb64); BIO_printf(bio_err," -%-4s (%s)\n","rc2", LN_rc2_cbc); #endif #ifndef NO_BF BIO_printf(bio_err," -%-12s -%-12s -%-12s -%-12s", LN_bf_ecb, LN_bf_cbc, LN_bf_cfb64, LN_bf_ofb64); BIO_printf(bio_err," -%-4s (%s)\n","bf", LN_bf_cbc); #endif #ifndef NO_CAST BIO_printf(bio_err," -%-12s -%-12s -%-12s -%-12s", LN_cast5_ecb, LN_cast5_cbc, LN_cast5_cfb64, LN_cast5_ofb64); BIO_printf(bio_err," -%-4s (%s)\n","cast", LN_cast5_cbc); #endif #ifndef NO_RC5 BIO_printf(bio_err," -%-12s -%-12s -%-12s -%-12s", LN_rc5_ecb, LN_rc5_cbc, LN_rc5_cfb64, LN_rc5_ofb64); BIO_printf(bio_err," -%-4s (%s)\n","rc5", LN_rc5_cbc); #endif goto end; } argc--; argv++; } if (bufsize != NULL) { unsigned long n; for (n=0; *bufsize; bufsize++) { i= *bufsize; if ((i <= '9') && (i >= '0')) n=n*10+i-'0'; else if (i == 'k') { n*=1024; bufsize++; break; } } if (*bufsize != '\0') { BIO_printf(bio_err,"invalid 'bufsize' specified.\n"); goto end; } /* It must be large enough for a base64 encoded line */ if (n < 80) n=80; bsize=(int)n; if (verbose) BIO_printf(bio_err,"bufsize=%d\n",bsize); } strbuf=OPENSSL_malloc(SIZE); buff=(unsigned char *)OPENSSL_malloc(EVP_ENCODE_LENGTH(bsize)); if ((buff == NULL) || (strbuf == NULL)) { BIO_printf(bio_err,"OPENSSL_malloc failure %ld\n",(long)EVP_ENCODE_LENGTH(bsize)); goto end; } in=BIO_new(BIO_s_file()); out=BIO_new(BIO_s_file()); if ((in == NULL) || (out == NULL)) { ERR_print_errors(bio_err); goto end; } if (debug) { BIO_set_callback(in,BIO_debug_callback); BIO_set_callback(out,BIO_debug_callback); BIO_set_callback_arg(in,bio_err); BIO_set_callback_arg(out,bio_err); } if (inf == NULL) BIO_set_fp(in,stdin,BIO_NOCLOSE); else { if (BIO_read_filename(in,inf) <= 0) { perror(inf); goto end; } } if(!str && passarg) { if(!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } str = pass; } if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) { for (;;) { char buf[200]; sprintf(buf,"enter %s %s password:"******"encryption":"decryption"); strbuf[0]='\0'; i=EVP_read_pw_string((char *)strbuf,SIZE,buf,enc); if (i == 0) { if (strbuf[0] == '\0') { ret=1; goto end; } str=strbuf; break; } if (i < 0) { BIO_printf(bio_err,"bad password read\n"); goto end; } } } if (outf == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outf) <= 0) { perror(outf); goto end; } } rbio=in; wbio=out; if (base64) { if ((b64=BIO_new(BIO_f_base64())) == NULL) goto end; if (debug) { BIO_set_callback(b64,BIO_debug_callback); BIO_set_callback_arg(b64,bio_err); } if (olb64) BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL); if (enc) wbio=BIO_push(b64,wbio); else rbio=BIO_push(b64,rbio); } if (cipher != NULL) { if (str != NULL) { /* Salt handling: if encrypting generate a salt and * write to output BIO. If decrypting read salt from * input BIO. */ unsigned char *sptr; if(nosalt) sptr = NULL; else { if(enc) { if(hsalt) { if(!set_hex(hsalt,salt,PKCS5_SALT_LEN)) { BIO_printf(bio_err, "invalid hex salt value\n"); goto end; } } else if (RAND_pseudo_bytes(salt, PKCS5_SALT_LEN) < 0) goto end; /* If -P option then don't bother writing */ if((printkey != 2) && (BIO_write(wbio,magic, sizeof magic-1) != sizeof magic-1 || BIO_write(wbio, (char *)salt, PKCS5_SALT_LEN) != PKCS5_SALT_LEN)) { BIO_printf(bio_err,"error writing output file\n"); goto end; } } else if(BIO_read(rbio,mbuf,sizeof mbuf) != sizeof mbuf || BIO_read(rbio, (unsigned char *)salt, PKCS5_SALT_LEN) != PKCS5_SALT_LEN) { BIO_printf(bio_err,"error reading input file\n"); goto end; } else if(memcmp(mbuf,magic,sizeof magic-1)) { BIO_printf(bio_err,"bad magic number\n"); goto end; } sptr = salt; } EVP_BytesToKey(cipher,EVP_md5(),sptr, (unsigned char *)str, strlen(str),1,key,iv); /* zero the complete buffer or the string * passed from the command line * bug picked up by * Larry J. Hughes Jr. <*****@*****.**> */ if (str == strbuf) OPENSSL_cleanse(str,SIZE); else OPENSSL_cleanse(str,strlen(str)); } if ((hiv != NULL) && !set_hex(hiv,iv,8)) { BIO_printf(bio_err,"invalid hex iv value\n"); goto end; } if ((hiv == NULL) && (str == NULL)) { /* No IV was explicitly set and no IV was generated * during EVP_BytesToKey. Hence the IV is undefined, * making correct decryption impossible. */ BIO_printf(bio_err, "iv undefined\n"); goto end; } if ((hkey != NULL) && !set_hex(hkey,key,24)) { BIO_printf(bio_err,"invalid hex key value\n"); goto end; } if ((benc=BIO_new(BIO_f_cipher())) == NULL) goto end; BIO_set_cipher(benc,cipher,key,iv,enc); if (debug) { BIO_set_callback(benc,BIO_debug_callback); BIO_set_callback_arg(benc,bio_err); } if (printkey) { if (!nosalt) { printf("salt="); for (i=0; i<PKCS5_SALT_LEN; i++) printf("%02X",salt[i]); printf("\n"); } if (cipher->key_len > 0) { printf("key="); for (i=0; i<cipher->key_len; i++) printf("%02X",key[i]); printf("\n"); } if (cipher->iv_len > 0) { printf("iv ="); for (i=0; i<cipher->iv_len; i++) printf("%02X",iv[i]); printf("\n"); } if (printkey == 2) { ret=0; goto end; } } } /* Only encrypt/decrypt as we write the file */ if (benc != NULL) wbio=BIO_push(benc,wbio); for (;;) { inl=BIO_read(rbio,(char *)buff,bsize); if (inl <= 0) break; if (BIO_write(wbio,(char *)buff,inl) != inl) { BIO_printf(bio_err,"error writing output file\n"); goto end; } } if (!BIO_flush(wbio)) { BIO_printf(bio_err,"bad decrypt\n"); goto end; } ret=0; if (verbose) { BIO_printf(bio_err,"bytes read :%8ld\n",BIO_number_read(in)); BIO_printf(bio_err,"bytes written:%8ld\n",BIO_number_written(out)); } end: ERR_print_errors(bio_err); if (strbuf != NULL) OPENSSL_free(strbuf); if (buff != NULL) OPENSSL_free(buff); if (in != NULL) BIO_free(in); if (out != NULL) BIO_free_all(out); if (benc != NULL) BIO_free(benc); if (b64 != NULL) BIO_free(b64); if(pass) OPENSSL_free(pass); OPENSSL_EXIT(ret); }