+
+ 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. <hughes@indiana.edu>
+ */
+ 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);