Exemplo n.º 1
0
int read_cipher_data( const char *filename, char *out, int len, unsigned char *key, unsigned char *iv )
{
    int retcode, count;
    BIO *cipher, *b64, *buffer, *file;

    /* Create a buffered file BIO for writing */
    file = BIO_new_file (filename, "r");
    if (!file) {
        /* FIXME - log an error */
        return -1;
    }

    retcode = alloc_cipher_BIOs( &buffer, &b64, &cipher );
    assert( retcode == 0 );
    if( retcode != 0 ) {
        /* alloc_cipher_BIOs() should log error */
        return retcode;
    }

    BIO_set_cipher (cipher, ENCRYPT_CIPHER, key, iv, 0);

    /* Assemble the BIO chain to be in the order file-buffer-b64-cipher */
    BIO_push (cipher, b64);
    BIO_push (b64, buffer);
    BIO_push (buffer, file);

    count = read_from_BIO( cipher, out, len );
    assert( count > 0 );

    BIO_free_all( cipher );
    
    /* success */
    return count;
}
Exemplo n.º 2
0
int main()
{
	const char* inFilename="data.jpg.enc";
    unsigned char key[] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
    unsigned char iv[]  = {0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};

	BIO* fileBio=BIO_new_file(inFilename,"rb");
	
	BIO* tBio=BIO_new(&methods_t);
	
	BIO* cipherBio = BIO_new(BIO_f_cipher ());
	BIO_set_cipher (cipherBio, EVP_aes_128_cbc (), key, iv, 0);
	
	BIO_push(cipherBio,tBio);
	BIO_push(tBio,fileBio);

	unsigned char* buffer[4096];

    FILE* out = fopen("data.1.c010", "wb");
    int seek_ret=BIO_seek(cipherBio,10000-16);
    if(seek_ret!=0){
    	printf("GmCAJDCY seek_ret %d\n",seek_ret);
    	return 1;
    }
    BIO_read(cipherBio,buffer,16);
	int len=BIO_read(cipherBio,buffer,4096);
	if(len!=4096){
		printf("yRWvFwNc len %d\n",len);
		return 1;
	}
	fwrite(buffer, 1, len, out);
    BIO_free(cipherBio);

    fclose(out);
    
    memset(buffer,0,4096);
    
    FILE* in0=fopen("data.jpg", "rb");
    seek_ret=fseek(in0,10000,SEEK_SET);
    if(seek_ret!=0){
    	printf("TjFQJbgg seek_ret %d\n",seek_ret);
    	return 1;
    }
    len=fread(buffer,1,4096,in0);
	if(len!=4096){
		printf("ZwIxswJf len %d\n",len);
		return 1;
	}
	fclose(in0);
	
	FILE* out0=fopen("data.0.c010", "wb");
	fwrite(buffer, 1, len, out0);
    fclose(out0);

    return 0;
}
Exemplo n.º 3
0
void CryptStream::setEncryptionKey (std::string passphrase, const char *cipherName, const char *ivParam, int keyIterationCount) {
	if (!_crypt_bio)
		throw std::logic_error ("CryptStream was not set up to use encryption");
	if (!_cipher) {
		if (cipherName && cipherName[0] != '\0') {
			this->_cipher = EVP_get_cipherbyname(cipherName);
		} else
			this->_cipher = EVP_aes_256_ctr();
	}
	if (!this->_cipher)
		throw std::runtime_error ("OpenSSL library does not provide requested Cipher mode");
	if (ivParam) {
		this->_iv = ivParam;
	} else {
		if (this->_iv.size() == 0) {
			this->_iv.resize(_cipher->iv_len);
			if (!RAND_bytes((unsigned char*)&_iv[0], _cipher->iv_len))
				throw std::runtime_error ("Could not generate random bytes to create initialization vector");
		}
	}
	if (keyIterationCount != -1) {
		this->_pbkdfIterationCount = keyIterationCount;
	}
	if (_iv.length() != _cipher->iv_len)
		throw std::runtime_error ("Invalid initialization vector length does not match cipher");
	// Use PBKDF2 to derive the encryption key from the passphrase. Use iv as Salt.
	unsigned char raw_key[_cipher->key_len + 1];
	int r = PKCS5_PBKDF2_HMAC_SHA1(passphrase.c_str(), passphrase.size(), (const unsigned char*)_iv.c_str(), _iv.length(),
									_pbkdfIterationCount, _cipher->key_len, raw_key);
	if (r != 1)
		throw std::runtime_error ("PBKDF2 algorithm to derive encryption key failed");
	// enc should be set to 1 for encryption and 0 for decryption.
	int enc = (_mode == READ) ? 0 : 1;
	BIO_set_cipher (_crypt_bio, _cipher, raw_key, (const unsigned char*)_iv.c_str(), enc);
	_bio_chain = BIO_push(_crypt_bio, _bio_chain);
	
	// Have a magic string in the beggining to find out if decryption actually works
	// Cipher must be secure against known-plaintext attacks
	const std::string encBuffer ("-- FILE -- 85gxk9d7 --");
	if (_mode == WRITE) {
		BIO_write(_bio_chain, encBuffer.data(), encBuffer.size());
	} else {
		std::string rBuffer (encBuffer.size(), '\0');
		r = BIO_read(_bio_chain, &rBuffer[0], encBuffer.size());
		
		if (r != encBuffer.size())
			throw std::runtime_error ("Unexpected file read error");
		if (encBuffer != rBuffer)
			throw std::runtime_error ("Invalid key");
	}
	if (_mode == WRITE) {
		_writeHeader();
	}
	this->_initialized = true;
}
Exemplo n.º 4
0
void openssl_bioBS_cipher()
{
	int len, i;
	BIO *bc, *bd;
	char outs[MAX1_LEN];
	const EVP_CIPHER *cd;
	unsigned char key[8], iv[8];

	for (i = 0; i < 8; i++) {
		memset(&key[i], i + 1, 1);
		memset(&iv[i], i + 1, 1);
	}

	bc = BIO_new(BIO_f_cipher());
	BIO_set_cipher(bc, EVP_des_ecb(), key, iv, 1);
	bd = BIO_new(BIO_s_null());
	bd = BIO_push(bc, bd);
	BIO_write(bd, "openssl", 7);
	len = BIO_read(bd, outs, MAX1_LEN);
	printf("\nBIO_CIPHER(%s) = ", "openssl");
	for (i = 0; i < len; i++)
		printf("%.02x", outs[i]);
	BIO_free(bd);
	BIO_free(bc);

	cd = EVP_des_ecb();
	bc = BIO_new(BIO_f_cipher());
	BIO_set_cipher(bc, cd, key, iv, 0);
	bd = BIO_new(BIO_s_null());
	bd = BIO_push(bc, bd);
	BIO_write(bc, outs, len);
	memset(outs, 0, sizeof(outs));
	BIO_read(bc, outs, MAX1_LEN);
	printf(" = %s\n", outs);
	BIO_free(bc);
	BIO_free(bd);
}
Exemplo n.º 5
0
int write_cipher_data (const char *filename, char *out, int len, unsigned char *key, unsigned char *iv)
{
    int count, retcode;
    BIO *cipher, *b64, *buffer, *file;

    /* write_cipher_data() taken from Chapter 4, pp.96-97 _Network Security with
     * OpenSSL_, Viega, Messier, and Chandra. O'Reilly 2001. ISBN 0-596-00270-X
     *
     * (Changed the formatting a bit.)
     */

    /* Create a buffered file BIO for writing */
    file = BIO_new_file (filename, "w");
    if (!file) {
        /* FIXME - log an error */
        return -1;
    }

    retcode = alloc_cipher_BIOs( &buffer, &b64, &cipher );
    assert( retcode == 0 );
    if( retcode != 0 ) {
        return retcode;
    }

    BIO_set_cipher (cipher, ENCRYPT_CIPHER, key, iv, 1);

    /* Assemble the BIO chain to be in the order cipher-b64-buffer-file */
    BIO_push (cipher, b64);
    BIO_push (b64, buffer);
    BIO_push (buffer, file);

    count = write_to_BIO( cipher, out, len );
    assert( count == len );

    BIO_free_all (cipher);
    
    /* success */
    return count;
}
Exemplo n.º 6
0
int main()
{
	const char* inFilename="data.jpg.enc";
    unsigned char key[] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
    unsigned char iv[]  = {0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};

	BIO* fileBio=BIO_new_file(inFilename,"rb");
	
	BIO* tBio=BIO_new(&methods_t);
	
	BIO* cipherBio = BIO_new(BIO_f_cipher ());
	BIO_set_cipher (cipherBio, EVP_aes_128_cbc (), key, iv, 0);
	
	BIO_push(cipherBio,tBio);
	BIO_push(tBio,fileBio);

	unsigned char* buffer[4096];

    FILE* out = fopen("data.jpg.enc.-.c008", "wb");
    // warning: do not use BIO_eof
    while(true){
    	//printf("BIO_read\n");
    	int len=BIO_read(cipherBio,buffer,4096);
    	if(len>0){
    		fwrite(buffer, 1, len, out);
    	}else if(len==0){
    		break;
    	}else{
    		printf("len %d\n",len);
    		return 1;
    	}
    }
    BIO_free(cipherBio);

    fclose(out);

    return 0;
}
Exemplo n.º 7
0
static LUA_FUNCTION(openssl_bio_new_filter)
{
  /* 0         1        2      3      4    5 */
  static const char* sType[] = {"base64", "buffer", "cipher", "md", "ssl", NULL};
  int type = luaL_checkoption(L, 1, NULL, sType);
  BIO* bio = NULL;
  int ret = 1;
  int closeflag = 0;
  switch (type)
  {
  case 0:
    bio = BIO_new(BIO_f_base64());
    break;
  case 1:
    bio = BIO_new(BIO_f_buffer());
    break;
  case 2:
  {
    const EVP_CIPHER* c = get_cipher(L, 2, NULL);
    size_t kl, il;
    const char* k = luaL_checklstring(L, 3, &kl);
    const char* v = luaL_checklstring(L, 4, &il);
    int encrypt = auxiliar_checkboolean(L, 5);

    bio = BIO_new(BIO_f_cipher());
    BIO_set_cipher(bio, c, (const unsigned char*)k, (const unsigned char*)v, encrypt);
  }
  break;
  case 3:
  {
    const EVP_MD* md = get_digest(L, 2);
    bio = BIO_new(BIO_f_md());
    ret = BIO_set_md(bio, md);
  }
  case 4:
  {
    SSL* ssl = CHECK_OBJECT(2, SSL, "openssl.ssl");
    closeflag = luaL_checkoption(L, 3, "noclose", close_flags);
    bio = BIO_new(BIO_f_ssl());
    ret = BIO_set_ssl(bio, ssl, closeflag);
  }
  break;
  default:
    ret = 0;
  }
  if (ret == 1 && bio)
  {
    PUSH_OBJECT(bio, "openssl.bio");
    if (closeflag)
    {
      openssl_newvalue(L, bio);

      lua_pushboolean(L, 1);
      openssl_setvalue(L, bio, "free_all");
    }
    return 1;
  }
  else
  {
    if (bio)
      BIO_free(bio);
    return openssl_pushresult(L, ret);
  }
  return 0;
}
Exemplo n.º 8
0
int main(int argc, char** argv)
{
    const char* secret;
    secret = getenv("TRACKING_SECRET");
    if (!secret) {
        fprintf(stderr, "TRACKING_SECRET not set\n");
        return 1;
    }
    
    char input_line[MAX_LINE];
    char plaintext[MAX_LINE];
    const EVP_CIPHER* cipher = EVP_aes_128_cbc();

    while (fgets(input_line, MAX_LINE, stdin) != NULL) {
        /* split the line into unique_id and query */
        char *unique_id, *query;
        split_fields(input_line, &unique_id, &query, NO_MORE_FIELDS);

        /* parse the query string to get the value we need */
        char *blob = NULL;

        char *key, *value;
        while (parse_query_param(&query, &key, &value) >= 0) {
            if (strcmp(key, "v") == 0) {
                blob = value;
                break;
            }
        }

        if (blob == NULL)
            continue;

        /* undo url encoding on the query string */
        int b64_size = url_decode(blob);
        if (b64_size < 0) 
            continue;

        /* split off the initialization vector from the actual ciphertext */
        char *initialization_vector, *ciphertext;

        initialization_vector = blob;
        initialization_vector[KEY_SIZE] = '\0';
        ciphertext = blob + 32;
        b64_size -= 32;

        /* base 64 decode and decrypt the ciphertext */
        BIO* bio = BIO_new_mem_buf(ciphertext, b64_size);

        BIO* b64 = BIO_new(BIO_f_base64());
        BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
        bio = BIO_push(b64, bio);

        BIO* aes = BIO_new(BIO_f_cipher());
        BIO_set_cipher(
            aes,
            cipher,
            (unsigned char*)secret,
            (unsigned char*)initialization_vector,
            0 /* decryption */
        );
        bio = BIO_push(aes, bio);

        /* stream the output through the filters */
        int plaintext_length = BIO_read(bio, plaintext, b64_size);
        plaintext[plaintext_length] = '\0';

        if (!BIO_get_cipher_status(bio)) {
            BIO_free_all(bio);
            continue;
        }

        /* clean up */
        BIO_free_all(bio);

        /* check that the plaintext isn't garbage; if there are
         * non-ascii characters in it, it's likely bad */
        bool non_ascii_junk = false;
        for (unsigned char* c = (unsigned char*)plaintext; *c != '\0'; c++) {
            if (*c > 0x7F) {
                non_ascii_junk = true;
                break;
            }
        }

        if (non_ascii_junk) {
            continue;
        }

        /* write out the unique id since we don't need it for ourselves */
        fputs(unique_id, stdout);

        /* split the fields out of the plaintext */
        char* current_string = plaintext;
        int field_index = 0;

        for (int i = 0; i < plaintext_length; i++) {
            char *c = plaintext + i;
            if (*c != '|')
                continue;
            
            *c = '\0';

            switch (field_index) {
            case FIELD_USER:
                /* we don't use the username; skip it */
                break;
            case FIELD_SRPATH:
                fputc('\t', stdout);
                fputs(current_string, stdout);

                fputc('\t', stdout);
                for (char* c2=current_string; *c2 != '\0'; c2++) {
                    if (*c2 == '-') {
                        *c2 = '\0';
                        break;
                    }
                }
                fputs(current_string, stdout);
                break;
            case FIELD_LANG:
                fputc('\t', stdout);
                for (char* c2=current_string; *c2 != '\0'; c2++) {
                    *c2 = tolower(*c2);
                }
                fputs(current_string, stdout);
                break;
            case FIELD_CNAME:
                assert(0!=1);
            }

            current_string = c + 1;
            field_index += 1;
        }

        if (field_index < FIELD_COUNT) {
            fputc('\t', stdout);
            fputs(current_string, stdout);
            field_index += 1;
        }

        for (; field_index < FIELD_COUNT; field_index++) 
            fputc('\t', stdout);

        /* all done! */
        fputc('\n', stdout);
    }

    return 0;
}
Exemplo n.º 9
0
int commandhandler(BIO *cbio, int cl)
{
   BIO *bbody = NULL, *bbase64 = NULL, *bcrypt = NULL;
   int ret = -1;
   char buf[100 * 1024];
   json_object *config = NULL;
   unsigned char iv[16];
   BIO *bmem = NULL;
   char *bptr = NULL, *c = NULL;
   long blen = 0;
   char *command = NULL;

   logme(LOGMSG_DEBUG, "commandhandler (cl=%d)", cl);

   do {
      if(!(bmem = BIO_new(BIO_s_mem()))) break;
      if(!(bbody = BIO_new(BIO_s_mem()))) break;
      if(!(bbase64 = BIO_new(BIO_f_base64()))) break;
      BIO_set_flags(bbase64, BIO_FLAGS_BASE64_NO_NL);
      if(!(bcrypt = BIO_new(BIO_f_cipher()))) break;
      memset(iv, 0x00, sizeof(iv));
      BIO_set_cipher(bcrypt, EVP_get_cipherbyname("aes-128-cbc"), (unsigned char *)conf.key, iv, 0);
      BIO_push(bbase64, bbody);
      BIO_push(bcrypt, bmem);

      while(blen < cl) {
         if((ret = BIO_read(cbio, buf, ((cl - blen) > sizeof(buf)) ? sizeof(buf) : (cl - blen))) <= 0) break;
         blen += ret;

         while((c = memchr(buf, '\n', ret)) || (c = memchr(buf, '\r', ret))) memmove(c, c + 1, --ret - (c - buf));

         if(BIO_write(bbody, buf, ret) != ret) {
            logme(LOGMSG_DEBUG, "BIO_write error");
            break;
         }
      }

      do {
         blen = BIO_read(bbase64, buf, sizeof(buf));
         if(blen > 0) {
            BIO_write(bcrypt, buf, blen);
         }
      } while(blen > 0);
      (void)BIO_flush(bcrypt);
      blen = BIO_get_mem_data(bmem, &bptr);

      if(!(config = json_tokener_parse(bptr))) break;
      if(!(command = (char *)json_object_get_string(json_object_object_get(config, "command")))) break;

      logme(LOGMSG_DEBUG, "command: %s", command);
      if(!strcasecmp(command, "FORWARD")) {
         ret = command_forward(config, cbio);
      } else if(!strcasecmp(command, "CONFIG")) {
         ret = command_config(config, cbio);
      } else if(!strcasecmp(command, "UPGRADE")) {
         ret = command_upgrade(config, cbio);
      } else if(!strcasecmp(command, "CHECK")) {
         ret = command_check(config, cbio);
      }
   } while(0);
   if(bbody) BIO_free(bbody);
   if(bbase64) BIO_free(bbase64);
   if(bcrypt) BIO_free(bcrypt);
   if(bmem) BIO_free(bmem);
   if(config) json_object_put(config);

   return ret;
}
Exemplo n.º 10
0
/** Add a DSA key to the tspc key file
 *
 * @param dsa        the DSA param pointer filled with our key info
 * @param host       the hostname of the corresponding broker
 * @param filename   the keyfile to use
 *
 * @return  0 if error
 *          1 if ok
 *
 */
int
add_dsakey_to_keyfile(DSA *dsa, char *host, char *filename, tBoolean autoaccept)
{

  FILE *fp = NULL;
  Buffer buf;
  char *str = NULL;
  int ret = 0;

  switch (is_dsakey_in_keyfile(dsa, host, filename)) {

  case 0:
    Display(LOG_LEVEL_3, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_ERR_IN_KEY_VERIF);
    Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED);
    break;
  case 1: /* not in, we add and continue */
#if defined(WIN32) && !defined(WINCE)
// When running as a service we can't ask user
// permission. Compromise and accept the key auto
//
    if (!IsService && !autoaccept)
    {
#else
    if (!autoaccept)
    {
#endif
      if (!ask(GOGO_STR_UNKNOWN_HOST_ADD_KEY, host))
      {
        Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED_USER);
        break;
      }
    }
    else
  Display(LOG_LEVEL_1, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_SERVER_KEY_AUTO_ADDED);

    Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_ACCEPTED_ADDED);

    buffer_init(&buf);
    if (buf.buf == NULL)
      break;
    buffer_put_cstring(&buf, "ssh-dss");
    buffer_put_bignum(&buf, dsa->p);
    buffer_put_bignum(&buf, dsa->q);
    buffer_put_bignum(&buf, dsa->g);
    buffer_put_bignum(&buf, dsa->pub_key);

    if ( (str = pal_malloc(2 * buffer_len(&buf))) == NULL)
      break;

    if ( (base64encode(str, buffer_ptr(&buf), (int) buffer_len(&buf))) < 1)
      break;

    fp = fopen(filename, "a");
    if (fp) {
      fprintf(fp, "%s ssh-dss %s\n", host, str);
      fclose(fp);
      ret = 1;
    }
    buffer_free(&buf);
    pal_free(str);
    break;
  case 2: /* in and matching correctly, hurray */
    Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_MATCHING_KEY_FOUND_USED);
    ret = 1;
    break;
  case 3: /* in and NOT matching correctly */
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_STORED_LOCAL_KEY_NO_MATCH, filename, host);
  Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED);
    ret = 0;
    break;
  }

  return ret;
}


/**
 * Authenticate to the Migration Broker using PASSDSS-3DES-1
 *
 * Buf_H will contain the data used to validate the server
 * signature. The data is a concatenation of the following parameters,
 * in that order:
 * azname,authname,DH_public_key,pklength,"ssh-dss",p,q,g,z,Y,ssecmask,sbuflen,dh_K
 *
 * @param socket
 * @param user
 * @param passwd
 * @param host
 * @param nt
 *
 * @return
 *
 * @todo DH public key validation  (RFC2631, 2.1.5)
 * @todo Local storage for server public keys
 *
 */
gogoc_status AuthPASSDSS_3DES_1(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list)
{
  DH   *dh = NULL;        /**< client DH key used to exchange key with server */
  DSA  *dsa = NULL; /**< Remote server DSA key public information */
  DSA_SIG *sig = NULL;    /**< DSA signature */
  char authenticate[] = "AUTHENTICATE PASSDSS-3DES-1\r\n";
  char *BufferIn  = NULL;
  char *BufferOut = NULL;
  char *BufferPtr = NULL;
  Buffer BufH;    /**< Buffer to hold data used for signature. */
  Buffer BufSpace;  /**< Space to hold data before/after base64 conversion */
  Buffer *Buf_H = &BufH;
  Buffer *Buf_Space = &BufSpace;
  BIO  *bio_rw = NULL;    /**< Memory buffer bio */
  BIO  *b64= NULL;    /**< Base64 bio */
  BIO  *cipher = NULL;    /**< Symmetric crypto bio */
  BIGNUM *server_pubkey = NULL; /**< received server public DH key */
  BIGNUM *dh_K = NULL;          /**< DH computed shared secret */
  u_char hash[20];  /**< SHA1 hash */
  u_char enc_key[24]; /**< encryption key (3des) */
  u_char enc_iv[8]; /**< initialization vector (3des) */
  u_char int_key[20]; /**< cs integrity key */
  u_char tmphash[40]; /**< temporary hash storage */
  u_char hmac[EVP_MAX_MD_SIZE]; /**< HMAC for integrity of sent data (step L) */
  int  pklength = 0;  /**< length of SSH-style DSA server public key */
  int ssecmask = 0; /**< SASL security layers offered */
  int sbuflen = 0;  /**< maximum server security layer block size */
  char *s = NULL;
  u_char num[3];    /**< Array to manupulate 3 octet number (sbuflen)  */
  /* Temporary variables */
  int  buflen, readlen, keysize, siglength;
  gogoc_status status = STATUS_SUCCESS_INIT;
  sint32_t tsp_status;

/* From draft-newman-sasl-passdss-01.  "This group was taken from the
 * ISAKMP/Oakley specification, and was originally generated by
 * Richard Schroeppel at the University of Arizona.  Properties of
 * this prime are described in [Orm96]"
 */

        /* RFC2409, DH group 2 (second Oakley group) */
  static char *dh_group2=
      "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
      "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
      "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
      "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
      "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
      "FFFFFFFF" "FFFFFFFF";
  static unsigned char dh_g[]={
    0x02,
  };


  /* Initialize Diffie Hellman variables */
  if ((dh = DH_new()) == NULL || (server_pubkey = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Convert dh_group2 and dh_g to BIGNUM type */
  BN_hex2bn(&dh->p, dh_group2);
  dh->g = BN_bin2bn(dh_g,sizeof(dh_g),NULL);
  if ((dh->p == NULL) || (dh->g == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_INITIALIZATION_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  if ((dh_K = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /* Reserve storage for DSA key */
  if ((dsa = DSA_new()) == NULL || (dsa->p = BN_new()) == NULL ||
      (dsa->q = BN_new()) == NULL ||  (dsa->g = BN_new()) == NULL ||
      (dsa->pub_key = BN_new()) == NULL || (dsa->priv_key = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /* Allocate memory for DSA signature */
  if ((sig = DSA_SIG_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Initialize data buffers */
  BufferIn  = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE);
  BufferOut = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE);

  if ((BufferIn == NULL) || (BufferOut == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  buffer_init(Buf_Space);
  buffer_init(Buf_H);
  if (Buf_Space->buf == NULL || Buf_H->buf == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Create a read/write memory BIO. Memory is segment is
   * created and resized as needed. When BIO is destroyed, the
   * memory is freed. */
  bio_rw = BIO_new(BIO_s_mem());
  /* Create a base64 BIO filter */
  b64 = BIO_new(BIO_f_base64());
  if ((bio_rw == NULL) || (b64 == NULL))
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }

  /*
    Compute the Diffie-Hellman public value "X" as follows.  If
    X has a value of 0, repeat.

         x
    X = g  mod n

    where g = dh_g = 2
          n = dh_group2
    x = DH secret key
    X = DH public key
  */
  if (DH_generate_key(dh) == 0)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_GEN_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }

  /* Validate DH public key (RFC2631, 2.1.5) */

  /* Send  message with SASL mechanism identifier */
  if ( nt->netsend(socket, authenticate, sizeof(authenticate)) == -1 )
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_W_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }

  /* First PASSDSS  message from client to server:
     string azname       ; the user name to login as, may be empty if
                           same as authentication name
     string authname     ; the authentication name
     mpint  X            ; Diffie-Hellman parameter X
  */
  /* azname is empty. Just insert a string length zero */
  buffer_put_int(Buf_Space, 0);
  /* authname */
  buffer_put_cstring(Buf_Space, conf->userid);
  /* DH public key */
  buffer_put_bignum(Buf_Space, dh->pub_key);

  /* At this point, save the buffer into Buf_H. Used later for
   * signature verification. */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), buffer_len(Buf_Space));

  /* Push base64 filter */
  BIO_push(b64, bio_rw);
  /* no newline */
  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  /* Write Buffer content into bio_rw. Buffer will be base64
   * encoded. */
  BIO_write(b64, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space));
  BIO_flush(b64);
  /* Get pointer to the result */
  buflen = BIO_get_mem_data(bio_rw, &BufferPtr);

  // Send data to server, save response in BufferIn.
  if((readlen = nt->netsendrecv(socket,
               BufferPtr, buflen,
               BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }
  /* remove base64 filter */
  BIO_pop(bio_rw);
  buffer_clear(Buf_Space);
  buflen = 0;

  /* Decode response (base64) and extract server response
   *
   * The response format is as follows:

       uint32   pklength   ; length of SSH-style DSA server public key
           (number of bytes up to y, inclusively)
         string "ssh-dss"  ; constant string "ssh-dss" (lower case)
         mpint  p          ; DSA public key parameters
         mpint  q
         mpint  g
         mpint  z            (y in draft)
       mpint    Y          ; Diffie-Hellman parameter Y
       OCTET    ssecmask   ; SASL security layers offered
       3 OCTET  sbuflen    ; maximum server security layer block size
       uint32   siglength  ; length of SSH-style dss signature
           (number of bytes up to s inclusively)
         string "ssh-dss"  ; constant string "ssh-dss" (lower case)
         mpint  r          ; DSA signature parameters
         mpint  s

   */

  buflen = base64decode(BufferOut, BufferIn);

  buffer_append(Buf_Space, BufferOut, buflen);
  /* Get pklength */
  pklength = buffer_get_int(Buf_Space);
  /* Assuming that
   * p, g, and y are 512 bits,
   * q is 160 bits,
   * "ssh-dss" is 7 bytes
   * pklength should be at least 240 bytes.
   */
  if (pklength < 240)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }

  /* Make a copy of (pklength|"ssh-dss"|p|q|g|z) in Buf_H */
  /* Add pklength */
  buffer_put_int(Buf_H, pklength);
  /* Add "ssh-dss"|p|q|g|z */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), pklength);

  /* Get "ssh-dss" string */
  s = buffer_get_string(Buf_Space, (unsigned int*)&buflen);
  pal_free(s); s = NULL;
  /* Get p */
  buffer_get_bignum(Buf_Space, dsa->p);
  /* Get q */
  buffer_get_bignum(Buf_Space, dsa->q);
  /* Get g */
  buffer_get_bignum(Buf_Space, dsa->g);
  /* Get z (pub_key) */
  buffer_get_bignum(Buf_Space, dsa->pub_key);
  /* Get DH public key */
  buffer_get_bignum(Buf_Space, server_pubkey);
  /* Copy in Buf_H for signature verification later */
  buffer_put_bignum(Buf_H, server_pubkey);

  /* Buffer now points at ssecmask (1 octet), followed by
   * sbuflen (3 octets). Make a copy of these 4 octets in Buf_H
   * now, then extract these values. */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), 4);

  /* Get ssecmask */
  ssecmask = buffer_get_octet(Buf_Space);
  /* Get sbuflen
   * Big endian binary unsigned integer */
  buffer_get(Buf_Space, (char *)num, 3);
  sbuflen =  (((u_long)(u_char)(num)[0] << 16) |
        ((u_long)(u_char)(num)[1] << 8) |
        ((u_long)(u_char)(num)[2]));

  /* DSS signature */
  /* Get siglength */
  siglength = buffer_get_int(Buf_Space);
  /* r and s are 20 bytes each, encoded as mpint (2*24)
   * "ssh-dss" is 7 bytes + int32 siglength should be >= 59
   * octets (mpint may have leading zero byte)
   */
  if (siglength < 59)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  /* Get "ssh-dss" string */
  s = buffer_get_string(Buf_Space, (unsigned int*)&buflen);
  pal_free(s); s = NULL;
  /* Get DSA signature r and s*/
  if ((sig->r= BN_new()) == NULL || (sig->s = BN_new()) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  /* Get r */
  buffer_get_bignum(Buf_Space, sig->r);
  /* Get s */
  buffer_get_bignum(Buf_Space, sig->s);

  /* Validate server DH public key  (RFC2631, 2.1.5) */

  {
    if( !add_dsakey_to_keyfile(dsa, conf->server, TSPC_DSA_KEYFILE, conf->no_questions) )
    {
      Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_KEY_VERIF_ERROR);
      status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
      goto error;
    }
  }

  /* Verify that DSA public key belongs to server */

  /* Compute DH shared secret */
  if ((s = calloc(1, DH_size(dh))) == NULL)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION);
    goto error;
  }
  if( (keysize = DH_compute_key((unsigned char*)s, server_pubkey, dh)) < 0 )
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_SHARED_COMPUTE_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
  }
  BN_bin2bn((const unsigned char*)s, keysize, dh_K);
  memset(s, 0, keysize);
  pal_free(s);
  s = NULL;
  Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
    GOGO_STR_DH_SHARED_KEY, BN_bn2hex(dh_K));

  /* Append dh_K in to complete the buffer. Use Buffer to hold
   * result to keep Bf_H intact, since to will be used (without
   * dh_K) to compute HMAC for packet integrity. */
  buffer_clear(Buf_Space);
  buffer_append(Buf_Space, buffer_ptr(Buf_H), buffer_len(Buf_H));
  buffer_put_bignum(Buf_Space, dh_K);

  /* Compute SHA1 hash of Buffer */
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), hash);

  /* Debug information available at level 4 */
 {
   BIGNUM *h;
   h = BN_bin2bn(hash, 20, NULL);
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_SIGNED_HASH, BN_bn2hex(h));
   BN_free(h);
 }
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_DSA_SIGN_R, BN_bn2hex(sig->r));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_DSA_SIGN_S, BN_bn2hex(sig->s));

  // Verify that the DSS signature is a signature of hash.
  switch( DSA_do_verify(hash, sizeof(hash), sig, dsa) )
  {
  case 0:
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_BAD_SIG_FROM_SERVER);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
    break; /* NOTREACHED */

  case 1:  /* correct signature */
    break;

  default: /* -1 on error */
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SIG_VERIF_ERROR);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;
    break; /* NOTREACHED */
  }

  /* Step I: Compute 3DES key and iv */
  /*
    cs-encryption-iv    = SHA1( K || "A" || H )
    sc-encryption-iv    = SHA1( K || "B" || H )
    cs-encryption-key-1 = SHA1( K || "C" || H )
    cs-encryption-key-2 = SHA1( K || cs-encryption-key-1 )
    cs-encryption-key   = cs-encryption-key-1 || cs-encryption-key-2
    sc-encryption-key-1 = SHA1( K || "D" || H )
    sc-encryption-key-2 = SHA1( K || sc-encryption-key-1 )
    sc-encryption-key   = sc-encryption-key-1 || sc-encryption-key-2
    cs-integrity-key    = SHA1( K || "E" || H )
    sc-integrity-key    = SHA1( K || "F" || H )

    K is dh_k in mpint format (string)
    H is hash
  */

  /* Since we won't support SASL security layers, we need to
   * compute the following only:
   * cs-encryption-iv
   * cs-encryption-key
   * cs-integrity-key
   */
  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'A');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash);
  /* Use first 8 octets as iv */
  memcpy(enc_iv, tmphash, 8);

  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'E');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), int_key);

  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_put_octet(Buf_Space,'C');
  buffer_append(Buf_Space, hash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash);
  buffer_clear(Buf_Space);
  buffer_put_bignum(Buf_Space, dh_K);
  buffer_append(Buf_Space, tmphash, 20);
  SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash+20);
  /* Use first 24 octets as key */
  memcpy(enc_key, tmphash, 24);
 {
   BIGNUM *enc, *i, *iv;
   enc = BN_bin2bn(enc_key, 24, NULL);
   iv = BN_bin2bn(enc_iv, 8, NULL);
   i = BN_bin2bn(int_key, 20, NULL);

   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_ENC_KEY, BN_bn2hex(enc));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_IV, BN_bn2hex(iv));
   Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING,
     GOGO_STR_PASSDS_INTEG_KEY, BN_bn2hex(i));
   BN_free(enc);
   BN_free(i);
   BN_free(iv);
 }
  /*
    (J) Create a buffer beginning with a bit mask for the
    selected security layer (it MUST be one offered from server)
    followed by three octets representing the maximum
    cipher-text buffer size (at least 32) the client can accept
    in network byte order.  This is followed by a string
    containing the passphrase.
  */
  buffer_clear(Buf_Space);
  buffer_put_octet(Buf_Space, ssecmask);
  buffer_put_octet(Buf_Space, 0);
  buffer_put_octet(Buf_Space, 0);
  buffer_put_octet(Buf_Space, 0); /**< @bug must be at least 32 */
  buffer_put_cstring(Buf_Space, conf->passwd);

  /*
    (K) Create a buffer containing items (1) through (7)
    immediately followed by the first four octets of (J).
  */
  buffer_append(Buf_H, buffer_ptr(Buf_Space), 4);

  /*
    (L) Compute HMAC-SHA-1 with (K) as the data and the
    cs-integrity- key from step (I) as the key.  This produces a
    20 octet result.
  */
  HMAC(EVP_sha1(), int_key, sizeof(int_key),
       buffer_ptr(Buf_H), buffer_len(Buf_H), hmac, (unsigned int*)&keysize);
  /*
    (M) Create a buffer containing (J) followed by (L) followed
    by an arbitrary number of zero octets as necessary to reach
    the block size of DES and conceal the passphrase length from
    an eavesdropper.
  */
  buffer_append(Buf_Space, hmac, keysize);

  /*
    (N) Apply the triple-DES algorithm to (M) with the first 8
    octets of cs-encryption-iv from step (I) as the
    initialization vector and the first 24 octets of
    cs-encryption-key as the key.
  */
  /*
    Padding is automatically done. From OpenSSL EVP_EncryptInit(3):
    EVP_CIPHER_CTX_set_padding() enables or disables padding. By default
    encryption operations are padded using standard block padding and the
    padding is checked and removed when decrypting.
  */

  /*
    Create BIO filter to encrypt using 3des + convert to
    base64. Result is written in memory BIO.
  */
  /* Erase BIO and buffer memory */
  BIO_reset(bio_rw);
  memset(BufferOut, 0, TSP_AUTH_PASSDSS_BUFFERSIZE);
  memset(BufferIn, 0, TSP_AUTH_PASSDSS_BUFFERSIZE);
  buflen = 0;

  /* Create cipher BIO */
  cipher = BIO_new(BIO_f_cipher());
  BIO_set_cipher(cipher, EVP_des_ede3_cbc(), enc_key, enc_iv, 1);
  /* Assemble filters as cipher->b64->bio_rw */
  BIO_push(cipher, b64);
  BIO_push(b64, bio_rw);

  /* Write Buffer content into bio_rw */
  BIO_write(cipher, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space));
  BIO_flush(cipher);
  /* Get pointer to the result. */
  buflen = BIO_get_mem_data(bio_rw, &BufferPtr);

  /* wipe encryption material */
  memset(enc_key, 0, sizeof(enc_key));
  memset(enc_iv, 0, sizeof(enc_iv));

  /* Send data to server, save response in BufferIn */
  if( (readlen = nt->netsendrecv(socket, BufferPtr, buflen,
       BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1)
  {
    Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO);
    goto error;
  }
  tsp_status = tspGetStatusCode(BufferIn);

  // Check if the reply status indicated a broker redirection.
  if( tspIsRedirectStatus(tsp_status) )
  {
    if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK )
    {
      status = make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION);
    }
    else
    {
      // Redirect error.
      status = make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION);
    }
    goto error;
  }

  // Check if authentication was successful.
  switch( tsp_status )
  {
  case TSP_PROTOCOL_SUCCESS:
    break;

  case TSP_PROTOCOL_AUTH_FAILED:
    Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_AUTH_FAILED_USER, conf->userid);
    status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE);
    goto error;

  default:
    Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status));
    status = make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR);
    goto error;
  }

  status = STATUS_SUCCESS_INIT;

 error:

  /* Free storage for DSA key */
  if (dsa != NULL) DSA_free(dsa); /* Also frees BIGNUMs inside struct */
  /* DSA signature */
  if (sig != NULL) DSA_SIG_free(sig);
  /* Free Diffie Hellman variables */
  if (dh != NULL) DH_free(dh); /* Also frees BIGNUMs inside struct */
  if (server_pubkey != NULL) BN_free(server_pubkey);
  if (dh_K != NULL) BN_free(dh_K);
  /* Buffers */
  if (Buf_Space->buf != NULL) buffer_free(Buf_Space);
  if (Buf_H->buf != NULL)  buffer_free(Buf_H);
  /* malloc'ed space*/
  if (BufferIn != NULL) pal_free(BufferIn);
  if (BufferOut != NULL) pal_free(BufferOut);
  /* BIOs */
  if (cipher != NULL) BIO_vfree(cipher);
  if (b64 != NULL) BIO_vfree(b64);
  if (bio_rw != NULL) BIO_vfree(bio_rw);
  /* strings buffers */
  if (s != NULL) pal_free(s);

  return status;
}
Exemplo n.º 11
0
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);
	}