コード例 #1
0
ファイル: aes_encryptor.cpp プロジェクト: klupek/cppcms
bool cipher::decrypt(string const &cipher,string &plain,time_t *timeout)
{
	vector<unsigned char> data;
	base64_dec(cipher,data);
	size_t norm_size=b64url::decoded_size(cipher.size());
	if(norm_size<sizeof(info)+sizeof(aes_hdr) || norm_size % 16 !=0)
		return false;

	gcry_cipher_decrypt(hd_in,&data.front(),data.size(),NULL,0);
	gcry_cipher_reset(hd_in);
	vector<char> md5(16,0);
	gcry_md_hash_buffer(GCRY_MD_MD5,&md5.front(),&data.front()+sizeof(aes_hdr),data.size()-sizeof(aes_hdr));
	aes_hdr &aes_header = *(aes_hdr*)&data.front();
	if(!std::equal(md5.begin(),md5.end(),aes_header.md5)) {
		return false;
	}
	info &header=*(info *)(&data.front()+sizeof(aes_hdr));
	if(time(NULL)>header.timeout)
		return false;
	if(timeout) *timeout=header.timeout;

	vector<unsigned char>::iterator data_start=data.begin()+sizeof(aes_hdr)+sizeof(info),
			data_end=data_start+header.size;

	plain.assign(data_start,data_end);
	return true;
}
コード例 #2
0
ファイル: crypter.c プロジェクト: tcpip4000/crypter
void decryptFile(gcry_cipher_hd_t hd, char *filename)
{
    FILE *encrypted_file;
    unsigned char encrypted_data[MAX_DATA_LEN], plain_data[MAX_DATA_LEN];
    gcry_error_t err = 0;

    if ((encrypted_file = fopen(filename, "r")) == NULL) {
        fprintf(stderr, "Cannot open %s\n", filename);
        exit(1);
    }

    fread(encrypted_data, MAX_DATA_LEN, 1, encrypted_file);
    while (!feof(encrypted_file) && !ferror(encrypted_file)) {
        err = gcry_cipher_decrypt(hd, plain_data, MAX_DATA_LEN, encrypted_data, MAX_DATA_LEN);
        if (err) {
            printf("grcy_cipher_decrypt failed: %s\n", gpg_strerror(err));
            exit(2);
        }
        gcry_cipher_reset(hd);

        printf("entrada: ");
        printCharArray(encrypted_data, MAX_DATA_LEN);
        printf("salida:  ");
        printCharArray(plain_data, MAX_DATA_LEN);
        fread(encrypted_data, MAX_DATA_LEN, 1, encrypted_file);
    }

    fclose(encrypted_file);
}
コード例 #3
0
void SymmetricCipherGcrypt::reset()
{
    gcry_error_t error;

    error = gcry_cipher_reset(m_ctx);
    Q_ASSERT(error == 0);
    error = gcry_cipher_setiv(m_ctx, m_iv.constData(), m_iv.size());
    Q_ASSERT(error == 0);
}
コード例 #4
0
ファイル: crypter.c プロジェクト: tcpip4000/crypter
void encryptDecryptTest(gcry_cipher_hd_t hd, char *plain_filename)
{
    FILE *plain_file;
    unsigned char encrypted_data[MAX_DATA_LEN], plain_data[MAX_DATA_LEN];
    gcry_error_t err = 0;
    int blocks_to_read = 1;

    if ((plain_file = fopen(plain_filename, "r")) == NULL) {
        fprintf(stderr, "Cannot open %s\n", plain_filename);
        exit(1);
    }

    while (!feof(plain_file) && !ferror(plain_file)) {
        //memcpy(plain_data, "                                ", MAX_DATA_LEN);
        fillCharVectorWithSpaces(plain_data, MAX_DATA_LEN);
        fread(plain_data, MAX_DATA_LEN, blocks_to_read, plain_file); 

        err = gcry_cipher_encrypt(hd, encrypted_data, MAX_DATA_LEN, plain_data, MAX_DATA_LEN);
        if (err) {
            printf("grcy_cipher_encrypt failed: %s\n", gpg_strerror(err));
            exit(2);
        }
        gcry_cipher_reset(hd);

        printf("entrada: ");
        printCharArray(plain_data, MAX_DATA_LEN);
        printf("salida:  ");
        printCharArray(encrypted_data, MAX_DATA_LEN);

        err = gcry_cipher_decrypt(hd, plain_data, MAX_DATA_LEN, encrypted_data, MAX_DATA_LEN);
        gcry_cipher_reset(hd);

        printf("entrada: ");
        printCharArray(encrypted_data, MAX_DATA_LEN);
        printf("salida:  ");
        printCharArray(plain_data, MAX_DATA_LEN);
    }

    fclose(plain_file);
}
コード例 #5
0
/**
 * ntfs_desx_decrypt
 */
static void ntfs_desx_decrypt(ntfs_fek *fek, u8 *outbuf, const u8 *inbuf)
{
    gcry_error_t err;
    ntfs_desx_ctx *ctx = &fek->desx_ctx;

    err = gcry_cipher_reset(fek->gcry_cipher_hd);
    if (err != GPG_ERR_NO_ERROR)
        ntfs_log_error("Failed to reset des cipher (error 0x%x).\n",
                       err);
    *(u64*)outbuf = *(const u64*)inbuf ^ ctx->out_whitening;
    err = gcry_cipher_encrypt(fek->gcry_cipher_hd, outbuf, 8, NULL, 0);
    if (err != GPG_ERR_NO_ERROR)
        ntfs_log_error("Des decryption failed (error 0x%x).\n", err);
    *(u64*)outbuf ^= ctx->in_whitening;
}
コード例 #6
0
ファイル: gcrypt.c プロジェクト: jbmulligan/quip
size_t _encrypt_char_buf(QSP_ARG_DECL  const char *in_buf, size_t in_len, uint8_t *out_buf, size_t out_len)
{
	gcry_error_t status;
	size_t padded_len, n_blocks;
	char *pad_buf;
	int bs;

	if( my_cipher_handle == NULL )
		init_gcrypt_subsystem();

	/* gcrypt doesn't seem to offer padding, so the input
	 * must be an integral number of blocks...
	 */
	bs=encryption_block_size();
	if( bs <= 0 ) return 0;	// when lib not present?

	n_blocks = in_len/bs;
	if( (in_len % bs) != 0 ){
		int i;
		n_blocks++;
		padded_len = n_blocks * bs;
		pad_buf = getbuf(padded_len);
		memcpy(pad_buf,in_buf,in_len);
		i=in_len;
		while(i<padded_len)
			pad_buf[i++] = 0;
	} else {
		pad_buf = (char *)in_buf;
		padded_len=in_len;
	}
	if( out_len < padded_len ){
		warn("encrypt_char_buf:  output buffer too small for pad!?");
		return 0;
	}

	status = gcry_cipher_encrypt(my_cipher_handle,
			out_buf,out_len,pad_buf,padded_len);
	CHECK_STATUS(encrypt_char_buf,gcry_cipher_encrypt)
	// how do we know how many chars actually written?

	status = gcry_cipher_reset(my_cipher_handle);
	CHECK_STATUS(encrypt_char_buf,gcry_cipher_reset)

	// if we allocated a buffer, then free it.
	if( pad_buf != in_buf ) givbuf(pad_buf);

	return padded_len;
}
コード例 #7
0
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
                         const uint8_t *iv, size_t niv,
                         Error **errp)
{
    gcry_cipher_hd_t handle = cipher->opaque;
    gcry_error_t err;

    gcry_cipher_reset(handle);
    err = gcry_cipher_setiv(handle, iv, niv);
    if (err != 0) {
        error_setg(errp, "Cannot set IV: %s",
                   gcry_strerror(err));
        return -1;
    }

    return 0;
}
コード例 #8
0
ファイル: psafe.c プロジェクト: mockbutler/psafe
void extract_random_key(const uint8_t *stretchkey,
			const uint8_t *fst, const uint8_t *snd,
			uint8_t *randkey)
{
	gcry_error_t gerr;
	gcry_cipher_hd_t hd;
	gerr = gcry_cipher_open(&hd, GCRY_CIPHER_TWOFISH,
				GCRY_CIPHER_MODE_ECB, GCRY_CIPHER_SECURE);
	if (gerr != GPG_ERR_NO_ERROR)
		gcrypt_fatal(gerr);
	gerr = gcry_cipher_setkey(hd, stretchkey, 32);
	if (gerr != GPG_ERR_NO_ERROR)
		gcrypt_fatal(gerr);
	gcry_cipher_decrypt(hd, randkey, 16, fst, 16);
	gcry_cipher_reset(hd);
	gcry_cipher_decrypt(hd, randkey + 16, 16, snd, 16);
	gcry_cipher_close(hd);
}
コード例 #9
0
ファイル: crypter.c プロジェクト: tcpip4000/crypter
void encryptFileToFile(gcry_cipher_hd_t hd, const char *plain_filename, const char *encrypted_filename) 
{
    FILE *plain_file, *encrypted_file;
    unsigned char encrypted_data[MAX_DATA_LEN], plain_data[MAX_DATA_LEN];
    gcry_error_t err = 0;
    size_t elements_written;
    int blocks_to_write = 1;

    if ((plain_file = fopen(plain_filename, "r")) == NULL) {
        fprintf(stderr, "Cannot open %s\n", plain_filename);
        exit(1);
    }

    if ((encrypted_file = fopen(encrypted_filename, "w+")) == NULL) {
        fprintf(stderr, "Cannot open %s\n", encrypted_filename);
        exit(1);
    }

    while (!feof(plain_file) && !ferror(plain_file)) { 
        //memcpy(plain_data, "                                ", MAX_DATA_LEN);
        fillCharVectorWithSpaces(plain_data, MAX_DATA_LEN);
        fread(plain_data, MAX_DATA_LEN, 1, plain_file);
        err = gcry_cipher_encrypt(hd, encrypted_data, MAX_DATA_LEN, plain_data, MAX_DATA_LEN);
        if (err) {
            printf("grcy_cipher_encrypt failed: %s\n", gpg_strerror(err));
            exit(2);
        }
        
        elements_written = fwrite(encrypted_data, MAX_DATA_LEN, blocks_to_write, encrypted_file);
        if (elements_written < blocks_to_write) {
            printf("Tried to write %d blocks but written %zu bytes\n", blocks_to_write, elements_written);
            exit(3);
        }
        gcry_cipher_reset(hd);
    }

    fflush(encrypted_file);
    fclose(encrypted_file);
    fclose(plain_file);
}
コード例 #10
0
/**
 * ntfs_fek_decrypt_sector
 */
static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
{
    gcry_error_t err;

    err = gcry_cipher_reset(fek->gcry_cipher_hd);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to reset cipher: %s\n",
                       gcry_strerror(err));
        return -1;
    }
    /*
     * Note: You may wonder why we are not calling gcry_cipher_setiv() here
     * instead of doing it by hand after the decryption.  The answer is
     * that gcry_cipher_setiv() wants an iv of length 8 bytes but we give
     * it a length of 16 for AES256 so it does not like it.
     */
    if (fek->alg_id == CALG_DESX) {
        int k;

        for (k=0; k<512; k+=8) {
            ntfs_desx_decrypt(fek, &data[k], &data[k]);
        }
    } else
        err = gcry_cipher_decrypt(fek->gcry_cipher_hd, data, 512, NULL, 0);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Decryption failed: %s\n", gcry_strerror(err));
        return -1;
    }
    /* Apply the IV. */
    if (fek->alg_id == CALG_AES_256) {
        ((le64*)data)[0] ^= cpu_to_le64(0x5816657be9161312ULL + offset);
        ((le64*)data)[1] ^= cpu_to_le64(0x1989adbe44918961ULL + offset);
    } else {
        /* All other algos (Des, 3Des, DesX) use the same IV. */
        ((le64*)data)[0] ^= cpu_to_le64(0x169119629891ad13ULL + offset);
    }
    return 512;
}
コード例 #11
0
ファイル: gcrypt.c プロジェクト: jbmulligan/quip
size_t _decrypt_char_buf(QSP_ARG_DECL  const uint8_t *in_buf, size_t in_len, char *out_buf, size_t out_len )
{
	gcry_error_t status;
	int bs;

	if( my_cipher_handle == NULL )
		init_gcrypt_subsystem();

	bs = encryption_block_size();
	if( bs <= 0 ) return 0;	// when lib not present?

	if( (in_len % bs) != 0 ){
		sprintf(ERROR_STRING,
"decrypt_char_buf:  input size (%ld) is not an integral number of blocks (bs = %d)!?",
			(long)in_len,bs);
		warn(ERROR_STRING);
		return 0;
	}

	status = gcry_cipher_decrypt(my_cipher_handle,
			out_buf,out_len,in_buf,in_len);
	CHECK_STATUS(decrypt_char_buf,gcry_cipher_decrypt)
	// how do we know how many chars actually written?

	status = gcry_cipher_reset(my_cipher_handle);
	CHECK_STATUS(decrypt_char_buf,gcry_cipher_reset)

	// If we padded, there will be zeroes at the end of the
	// message - we might assume that they are invalid,
	// as we are generally encrypting C strings?

	while( out_len >= 1 && out_buf[out_len-1]==0 )
		out_len --;

	return out_len;
}
コード例 #12
0
ファイル: aeswrap.c プロジェクト: Chronic-Dev/libgcrypt
static void
check (int algo,
       const void *kek, size_t keklen,
       const void *data, size_t datalen,
       const void *expected, size_t expectedlen)
{
  gcry_error_t err;
  gcry_cipher_hd_t hd;
  unsigned char outbuf[32+8];
  size_t outbuflen;

  err = gcry_cipher_open (&hd, algo, GCRY_CIPHER_MODE_AESWRAP, 0);
  if (err)
    {
      fail ("gcry_cipher_open failed: %s\n", gpg_strerror (err));
      return;
    }

  err = gcry_cipher_setkey (hd, kek, keklen);
  if (err)
    {
      fail ("gcry_cipher_setkey failed: %s\n", gpg_strerror (err));
      return;
    }

  outbuflen = datalen + 8;
  if (outbuflen > sizeof outbuf)
    err = gpg_error (GPG_ERR_INTERNAL);
  else
    err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, datalen);
  if (err)
    {
      fail ("gcry_cipher_encrypt failed: %s\n", gpg_strerror (err));
      return;
    }

  if (outbuflen != expectedlen || memcmp (outbuf, expected, expectedlen))
    {
      const unsigned char *s;
      int i;

      fail ("mismatch at encryption!\n");
      fprintf (stderr, "computed: ");
      for (i = 0; i < outbuflen; i++)
	fprintf (stderr, "%02x ", outbuf[i]);
      fprintf (stderr, "\nexpected: ");
      for (s = expected, i = 0; i < expectedlen; s++, i++)
        fprintf (stderr, "%02x ", *s);
      putc ('\n', stderr);
    }


  outbuflen = expectedlen - 8;
  if (outbuflen > sizeof outbuf)
    err = gpg_error (GPG_ERR_INTERNAL);
  else
    err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
  if (err)
    {
      fail ("gcry_cipher_decrypt failed: %s\n", gpg_strerror (err));
      return;
    }

  if (outbuflen != datalen || memcmp (outbuf, data, datalen))
    {
      const unsigned char *s;
      int i;

      fail ("mismatch at decryption!\n");
      fprintf (stderr, "computed: ");
      for (i = 0; i < outbuflen; i++)
	fprintf (stderr, "%02x ", outbuf[i]);
      fprintf (stderr, "\nexpected: ");
      for (s = data, i = 0; i < datalen; s++, i++)
        fprintf (stderr, "%02x ", *s);
      putc ('\n', stderr);
    }

  /* Now the last step again with a key reset. */
  gcry_cipher_reset (hd);

  outbuflen = expectedlen - 8;
  if (outbuflen > sizeof outbuf)
    err = gpg_error (GPG_ERR_INTERNAL);
  else
    err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
  if (err)
    {
      fail ("gcry_cipher_decrypt(2) failed: %s\n", gpg_strerror (err));
      return;
    }

  if (outbuflen != datalen || memcmp (outbuf, data, datalen))
    fail ("mismatch at decryption(2)!\n");

  /* And once ore without a key reset. */
  outbuflen = expectedlen - 8;
  if (outbuflen > sizeof outbuf)
    err = gpg_error (GPG_ERR_INTERNAL);
  else
    err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
  if (err)
    {
      fail ("gcry_cipher_decrypt(3) failed: %s\n", gpg_strerror (err));
      return;
    }

  if (outbuflen != datalen || memcmp (outbuf, data, datalen))
    fail ("mismatch at decryption(3)!\n");

  gcry_cipher_close (hd);
}
コード例 #13
0
static
int
mode_encrypt(File filein, File fileout)
{
	size_t			bytesread;
	size_t			chunkbuflen;
	void			*chunkbuf = NULL;
	void			*ivbuf = NULL;
	size_t			encryptbuflen = 0;
	size_t			encryptedlen = 0;
	void			*encryptbuf = NULL;
	ulonglong		ttlchunkswritten = 0;
	ulonglong		ttlbyteswritten = 0;
	xb_wcrypt_t		*xbcrypt_file = NULL;
	gcry_cipher_hd_t	cipher_handle;
	gcry_error_t		gcry_error;

	if (encrypt_algo != GCRY_CIPHER_NONE) {
		gcry_error = gcry_cipher_open(&cipher_handle,
					      encrypt_algo,
					      encrypt_mode, 0);
		if (gcry_error) {
			msg("%s:encrypt: unable to open libgcrypt cipher - "
			    "%s : %s\n", my_progname,
			    gcry_strsource(gcry_error),
			    gcry_strerror(gcry_error));
			return 1;
		}

		gcry_error = gcry_cipher_setkey(cipher_handle,
						opt_encrypt_key,
						encrypt_key_len);
		if (gcry_error) {
			msg("%s:encrypt: unable to set libgcrypt cipher key - "
			    "%s : %s\n", my_progname,
			    gcry_strsource(gcry_error),
			    gcry_strerror(gcry_error));
			goto err;
		}
	}

	posix_fadvise(filein, 0, 0, POSIX_FADV_SEQUENTIAL);

	xbcrypt_file = xb_crypt_write_open(&fileout,
					   my_xb_crypt_write_callback);
	if (xbcrypt_file == NULL) {
		msg("%s:encrypt: xb_crypt_write_open() failed.\n",
		    my_progname);
		goto err;
	}

	ivbuf = my_malloc(encrypt_iv_len, MYF(MY_FAE));

	/* now read in data in chunk size, encrypt and write out */
	chunkbuflen = opt_encrypt_chunk_size;
	chunkbuf = my_malloc(chunkbuflen, MYF(MY_FAE));
	while ((bytesread = my_read(filein, chunkbuf, chunkbuflen,
				    MYF(MY_WME))) > 0) {

		if (encrypt_algo != GCRY_CIPHER_NONE) {
			gcry_error = gcry_cipher_reset(cipher_handle);

			if (gcry_error) {
				msg("%s:encrypt: unable to reset cipher - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				goto err;
			}

			xb_crypt_create_iv(ivbuf, encrypt_iv_len);
			gcry_error = gcry_cipher_setiv(cipher_handle,
							ivbuf,
							encrypt_iv_len);

			if (gcry_error) {
				msg("%s:encrypt: unable to set cipher iv - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				continue;
			}

			if (encryptbuflen < bytesread) {
				if (encryptbuflen) {
					encryptbuf = my_realloc(encryptbuf,
								bytesread,
								MYF(MY_WME));
					encryptbuflen = bytesread;
				} else {
					encryptbuf = my_malloc(bytesread,
							       MYF(MY_WME));
					encryptbuflen = bytesread;
				}
			}

			gcry_error = gcry_cipher_encrypt(cipher_handle,
							 encryptbuf,
							 encryptbuflen,
							 chunkbuf,
							 bytesread);

			encryptedlen = bytesread;

			if (gcry_error) {
				msg("%s:encrypt: unable to encrypt chunk - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				gcry_cipher_close(cipher_handle);
				goto err;
			}
		} else {
			encryptedlen = bytesread;
			encryptbuf = chunkbuf;
		}

		if (xb_crypt_write_chunk(xbcrypt_file, encryptbuf, bytesread,
					 encryptedlen, ivbuf, encrypt_iv_len)) {
			msg("%s:encrypt: abcrypt_write_chunk() failed.\n",
			    my_progname);
			goto err;
		}

		ttlchunkswritten++;
		ttlbyteswritten += encryptedlen;

		if (opt_verbose)
			msg("%s:encrypt: %llu chunks written, %llu bytes "
			    "written\n.", my_progname, ttlchunkswritten,
			    ttlbyteswritten);
	}

	my_free(ivbuf);
	my_free(chunkbuf);

	if (encryptbuf && encryptbuflen)
		my_free(encryptbuf);

	xb_crypt_write_close(xbcrypt_file);

	if (encrypt_algo != GCRY_CIPHER_NONE)
		gcry_cipher_close(cipher_handle);

	if (opt_verbose)
		msg("\n%s:encrypt: done\n", my_progname);

	return 0;
err:
	if (chunkbuf)
		my_free(chunkbuf);

	if (encryptbuf && encryptbuflen)
		my_free(encryptbuf);

	if (xbcrypt_file)
		xb_crypt_write_close(xbcrypt_file);

	if (encrypt_algo != GCRY_CIPHER_NONE)
		gcry_cipher_close(cipher_handle);

	return 1;
}
コード例 #14
0
static void
check_one_cipher (int algo, int mode, int flags)
{
  gcry_cipher_hd_t hd;
  char key[32], plain[16], in[16], out[16];
  int keylen;
  gcry_error_t err = 0;

  memcpy (key, "0123456789abcdef.,;/[]{}-=ABCDEF", 32);
  memcpy (plain, "foobar42FOOBAR17", 16);

  keylen = gcry_cipher_get_algo_keylen (algo);
  if (!keylen)
    {
      fail ("algo %d, mode %d, gcry_cipher_get_algo_keylen failed\n",
	    algo, mode);
      return;
    }

  if (keylen < 40 / 8 || keylen > 32)
    {
      fail ("algo %d, mode %d, keylength problem (%d)\n", algo, mode, keylen);
      return;
    }

  err = gcry_cipher_open (&hd, algo, mode, flags);
  if (err)
    {
      fail ("algo %d, mode %d, grcy_open_cipher failed: %s\n",
	    algo, mode, gpg_strerror (err));
      return;
    }

  err = gcry_cipher_setkey (hd, key, keylen);
  if (err)
    {
      fail ("algo %d, mode %d, gcry_cipher_setkey failed: %s\n",
	    algo, mode, gpg_strerror (err));
      gcry_cipher_close (hd);
      return;
    }

  err = gcry_cipher_encrypt (hd, out, 16, plain, 16);
  if (err)
    {
      fail ("algo %d, mode %d, gcry_cipher_encrypt failed: %s\n",
	    algo, mode, gpg_strerror (err));
      gcry_cipher_close (hd);
      return;
    }

  gcry_cipher_reset (hd);

  err = gcry_cipher_decrypt (hd, in, 16, out, 16);
  if (err)
    {
      fail ("algo %d, mode %d, gcry_cipher_decrypt failed: %s\n",
	    algo, mode, gpg_strerror (err));
      gcry_cipher_close (hd);
      return;
    }

  gcry_cipher_close (hd);

  if (memcmp (plain, in, 16))
    fail ("algo %d, mode %d, encrypt-decrypt mismatch\n", algo, mode);
}
コード例 #15
0
ファイル: proto.c プロジェクト: Xara/Luna-Viewer
/* Create an OTR Data message.  Pass the plaintext as msg, and an
 * optional chain of TLVs.  A newly-allocated string will be returned in
 * *encmessagep. */
gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
	const char *msg, const OtrlTLV *tlvs, unsigned char flags)
{
    size_t justmsglen = strlen(msg);
    size_t msglen = justmsglen + 1 + otrl_tlv_seriallen(tlvs);
    size_t buflen;
    size_t pubkeylen;
    unsigned char *buf = NULL;
    unsigned char *bufp;
    size_t lenp;
    DH_sesskeys *sess = &(context->sesskeys[1][0]);
    gcry_error_t err;
    size_t reveallen = 20 * context->numsavedkeys;
    size_t base64len;
    char *base64buf = NULL;
    unsigned char *msgbuf = NULL;
    enum gcry_mpi_format format = GCRYMPI_FMT_USG;
    char *msgdup;
    int version = context->protocol_version;

    /* Make sure we're actually supposed to be able to encrypt */
    if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED ||
	    context->their_keyid == 0) {
	return gcry_error(GPG_ERR_CONFLICT);
    }

    /* We need to copy the incoming msg, since it might be an alias for
     * context->lastmessage, which we'll be freeing soon. */
    msgdup = gcry_malloc_secure(justmsglen + 1);
    if (msgdup == NULL) {
	return gcry_error(GPG_ERR_ENOMEM);
    }
    strcpy(msgdup, msg);

    *encmessagep = NULL;

    /* Header, send keyid, recv keyid, counter, msg len, msg
     * len of revealed mac keys, revealed mac keys, MAC */
    buflen = 3 + (version == 2 ? 1 : 0) + 4 + 4 + 8 + 4 + msglen +
	4 + reveallen + 20;
    gcry_mpi_print(format, NULL, 0, &pubkeylen, context->our_dh_key.pub);
    buflen += pubkeylen + 4;
    buf = malloc(buflen);
    msgbuf = gcry_malloc_secure(msglen);
    if (buf == NULL || msgbuf == NULL) {
	free(buf);
	gcry_free(msgbuf);
	gcry_free(msgdup);
	return gcry_error(GPG_ERR_ENOMEM);
    }
    memmove(msgbuf, msgdup, justmsglen);
    msgbuf[justmsglen] = '\0';
    otrl_tlv_serialize(msgbuf + justmsglen + 1, tlvs);
    bufp = buf;
    lenp = buflen;
    if (version == 1) {
	memmove(bufp, "\x00\x01\x03", 3);  /* header */
    } else {
	memmove(bufp, "\x00\x02\x03", 3);  /* header */
    }
    debug_data("Header", bufp, 3);
    bufp += 3; lenp -= 3;
    if (version == 2) {
	bufp[0] = flags;
	bufp += 1; lenp -= 1;
    }
    write_int(context->our_keyid-1);                    /* sender keyid */
    debug_int("Sender keyid", bufp-4);
    write_int(context->their_keyid);                    /* recipient keyid */
    debug_int("Recipient keyid", bufp-4);

    write_mpi(context->our_dh_key.pub, pubkeylen, "Y");      /* Y */

    otrl_dh_incctr(sess->sendctr);
    memmove(bufp, sess->sendctr, 8);      /* Counter (top 8 bytes only) */
    debug_data("Counter", bufp, 8);
    bufp += 8; lenp -= 8;

    write_int(msglen);                        /* length of encrypted data */
    debug_int("Msg len", bufp-4);

    err = gcry_cipher_reset(sess->sendenc);
    if (err) goto err;
    err = gcry_cipher_setctr(sess->sendenc, sess->sendctr, 16);
    if (err) goto err;
    err = gcry_cipher_encrypt(sess->sendenc, bufp, msglen, msgbuf, msglen);
    if (err) goto err;                              /* encrypted data */
    debug_data("Enc data", bufp, msglen);
    bufp += msglen;
    lenp -= msglen;

    gcry_md_reset(sess->sendmac);
    gcry_md_write(sess->sendmac, buf, bufp-buf);
    memmove(bufp, gcry_md_read(sess->sendmac, GCRY_MD_SHA1), 20);
    debug_data("MAC", bufp, 20);
    bufp += 20;                                         /* MAC */
    lenp -= 20;

    write_int(reveallen);                     /* length of revealed MAC keys */
    debug_int("Revealed MAC length", bufp-4);

    if (reveallen > 0) {
	memmove(bufp, context->saved_mac_keys, reveallen);
	debug_data("Revealed MAC data", bufp, reveallen);
	bufp += reveallen; lenp -= reveallen;
	free(context->saved_mac_keys);
	context->saved_mac_keys = NULL;
	context->numsavedkeys = 0;
    }

    assert(lenp == 0);

    /* Make the base64-encoding. */
    base64len = ((buflen + 2) / 3) * 4;
    base64buf = malloc(5 + base64len + 1 + 1);
    if (base64buf == NULL) {
	err = gcry_error(GPG_ERR_ENOMEM);
	goto err;
    }
    memmove(base64buf, "?OTR:", 5);
    otrl_base64_encode(base64buf+5, buf, buflen);
    base64buf[5 + base64len] = '.';
    base64buf[5 + base64len + 1] = '\0';

    free(buf);
    gcry_free(msgbuf);
    *encmessagep = base64buf;
    gcry_free(context->lastmessage);
    context->lastmessage = NULL;
    context->may_retransmit = 0;
    if (msglen > 0) {
	const char *prefix = "[resent] ";
	size_t prefixlen = strlen(prefix);
	if (!strncmp(prefix, msgdup, prefixlen)) {
	    /* The prefix is already there.  Don't add it again. */
	    prefix = "";
	    prefixlen = 0;
	}
	context->lastmessage = gcry_malloc_secure(prefixlen + justmsglen + 1);
	if (context->lastmessage) {
	    strcpy(context->lastmessage, prefix);
	    strcat(context->lastmessage, msgdup);
	}
    }
    gcry_free(msgdup);
    return gcry_error(GPG_ERR_NO_ERROR);
err:
    free(buf);
    gcry_free(msgbuf);
    gcry_free(msgdup);
    *encmessagep = NULL;
    return err;
}
コード例 #16
0
ファイル: proto.c プロジェクト: Xara/Luna-Viewer
/* Accept an OTR Data Message in datamsg.  Decrypt it and put the
 * plaintext into *plaintextp, and any TLVs into tlvsp.  Put any
 * received flags into *flagsp (if non-NULL). */
gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
	ConnContext *context, const char *datamsg, unsigned char *flagsp)
{
    char *otrtag, *endtag;
    gcry_error_t err;
    unsigned char *rawmsg = NULL;
    size_t msglen, rawlen, lenp;
    unsigned char *macstart, *macend;
    unsigned char *bufp;
    unsigned int sender_keyid, recipient_keyid;
    gcry_mpi_t sender_next_y = NULL;
    unsigned char ctr[8];
    unsigned int datalen, reveallen;
    unsigned char *data = NULL;
    unsigned char *nul = NULL;
    unsigned char givenmac[20];
    DH_sesskeys *sess;
    unsigned char version;

    *plaintextp = NULL;
    *tlvsp = NULL;
    if (flagsp) *flagsp = 0;
    otrtag = strstr(datamsg, "?OTR:");
    if (!otrtag) {
	goto invval;
    }
    endtag = strchr(otrtag, '.');
    if (endtag) {
	msglen = endtag-otrtag;
    } else {
	msglen = strlen(otrtag);
    }

    /* Base64-decode the message */
    rawlen = ((msglen-5) / 4) * 3;   /* maximum possible */
    rawmsg = malloc(rawlen);
    if (!rawmsg && rawlen > 0) {
	err = gcry_error(GPG_ERR_ENOMEM);
	goto err;
    }
    rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5);  /* actual size */

    bufp = rawmsg;
    lenp = rawlen;

    macstart = bufp;
    require_len(3);
    if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3)) {
	/* Invalid header */
	goto invval;
    }
    version = bufp[1];
    bufp += 3; lenp -= 3;

    if (version == 2) {
	require_len(1);
	if (flagsp) *flagsp = bufp[0];
	bufp += 1; lenp -= 1;
    }
    read_int(sender_keyid);
    read_int(recipient_keyid);
    read_mpi(sender_next_y);
    require_len(8);
    memmove(ctr, bufp, 8);
    bufp += 8; lenp -= 8;
    read_int(datalen);
    require_len(datalen);
    data = malloc(datalen+1);
    if (!data) {
	err = gcry_error(GPG_ERR_ENOMEM);
	goto err;
    }
    memmove(data, bufp, datalen);
    data[datalen] = '\0';
    bufp += datalen; lenp -= datalen;
    macend = bufp;
    require_len(20);
    memmove(givenmac, bufp, 20);
    bufp += 20; lenp -= 20;
    read_int(reveallen);
    require_len(reveallen);
    /* Just skip over the revealed MAC keys, which we don't need.  They
     * were published for deniability of transcripts. */
    bufp += reveallen; lenp -= reveallen;

    /* That should be everything */
    if (lenp != 0) goto invval;

    /* We don't take any action on this message (especially rotating
     * keys) until we've verified the MAC on this message.  To that end,
     * we need to know which keys this message is claiming to use. */
    if (context->their_keyid == 0 ||
	    (sender_keyid != context->their_keyid &&
		sender_keyid != context->their_keyid - 1) ||
	    (recipient_keyid != context->our_keyid &&
	     recipient_keyid != context->our_keyid - 1) ||
	    sender_keyid == 0 || recipient_keyid == 0) {
	goto conflict;
    }

    if (sender_keyid == context->their_keyid - 1 &&
	    context->their_old_y == NULL) {
	goto conflict;
    }

    /* These are the session keys this message is claiming to use. */
    sess = &(context->sesskeys
	    [context->our_keyid - recipient_keyid]
	    [context->their_keyid - sender_keyid]);

    gcry_md_reset(sess->rcvmac);
    gcry_md_write(sess->rcvmac, macstart, macend-macstart);
    if (memcmp(givenmac, gcry_md_read(sess->rcvmac, GCRY_MD_SHA1), 20)) {
	/* The MACs didn't match! */
	goto conflict;
    }
    sess->rcvmacused = 1;

    /* Check to see that the counter is increasing; i.e. that this isn't
     * a replay. */
    if (otrl_dh_cmpctr(ctr, sess->rcvctr) <= 0) {
	goto conflict;
    }

    /* Decrypt the message */
    memmove(sess->rcvctr, ctr, 8);
    err = gcry_cipher_reset(sess->rcvenc);
    if (err) goto err;
    err = gcry_cipher_setctr(sess->rcvenc, sess->rcvctr, 16);
    if (err) goto err;
    err = gcry_cipher_decrypt(sess->rcvenc, data, datalen, NULL, 0);
    if (err) goto err;

    /* See if either set of keys needs rotating */

    if (recipient_keyid == context->our_keyid) {
	/* They're using our most recent key, so generate a new one */
	err = rotate_dh_keys(context);
	if (err) goto err;
    }

    if (sender_keyid == context->their_keyid) {
	/* They've sent us a new public key */
	err = rotate_y_keys(context, sender_next_y);
	if (err) goto err;
    }

    gcry_mpi_release(sender_next_y);
    *plaintextp = (char *)data;

    /* See if there are TLVs */
    nul = data;
    while (nul < data+datalen && *nul) ++nul;
    /* If we stopped before the end, skip the NUL we stopped at */
    if (nul < data+datalen) ++nul;
    *tlvsp = otrl_tlv_parse(nul, (data+datalen)-nul);

    free(rawmsg);
    return gcry_error(GPG_ERR_NO_ERROR);

invval:
    err = gcry_error(GPG_ERR_INV_VALUE);
    goto err;
conflict:
    err = gcry_error(GPG_ERR_CONFLICT);
    goto err;
err:
    gcry_mpi_release(sender_next_y);
    free(data);
    free(rawmsg);
    return err;
}
コード例 #17
0
static
int
mode_decrypt(File filein, File fileout)
{
	xb_rcrypt_t		*xbcrypt_file = NULL;
	void			*chunkbuf = NULL;
	size_t			chunksize;
	size_t			originalsize;
	void			*ivbuf = NULL;
	size_t			ivsize;
	void			*decryptbuf = NULL;
	size_t			decryptbufsize = 0;
	ulonglong		ttlchunksread = 0;
	ulonglong		ttlbytesread = 0;
	xb_rcrypt_result_t	result;
	gcry_cipher_hd_t	cipher_handle;
	gcry_error_t		gcry_error;

	if (encrypt_algo != GCRY_CIPHER_NONE) {
		gcry_error = gcry_cipher_open(&cipher_handle,
					      encrypt_algo,
					      encrypt_mode, 0);
		if (gcry_error) {
			msg("%s:decrypt: unable to open libgcrypt"
			    " cipher - %s : %s\n", my_progname,
			    gcry_strsource(gcry_error),
			    gcry_strerror(gcry_error));
			return 1;
		}

		gcry_error = gcry_cipher_setkey(cipher_handle,
						opt_encrypt_key,
						encrypt_key_len);
		if (gcry_error) {
			msg("%s:decrypt: unable to set libgcrypt cipher"
			    "key - %s : %s\n", my_progname,
			    gcry_strsource(gcry_error),
			    gcry_strerror(gcry_error));
			goto err;
		}
	}

	/* Initialize the xb_crypt format reader */
	xbcrypt_file = xb_crypt_read_open(&filein, my_xb_crypt_read_callback);
	if (xbcrypt_file == NULL) {
		msg("%s:decrypt: xb_crypt_read_open() failed.\n", my_progname);
		goto err;
	}

	/* Walk the encrypted chunks, decrypting them and writing out */
	while ((result = xb_crypt_read_chunk(xbcrypt_file, &chunkbuf,
					     &originalsize, &chunksize,
					     &ivbuf, &ivsize))
		== XB_CRYPT_READ_CHUNK) {

		if (encrypt_algo != GCRY_CIPHER_NONE) {
			gcry_error = gcry_cipher_reset(cipher_handle);
			if (gcry_error) {
				msg("%s:decrypt: unable to reset libgcrypt"
				    " cipher - %s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				goto err;
			}

			if (ivsize) {
				gcry_error = gcry_cipher_setiv(cipher_handle,
							       ivbuf,
							       ivsize);
			} else {
				gcry_error = gcry_cipher_setiv(cipher_handle,
							       v1_encrypt_iv,
							       encrypt_iv_len);
			}
			if (gcry_error) {
				msg("%s:decrypt: unable to set cipher iv - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				continue;
			}

			if (decryptbufsize < originalsize) {
				if (decryptbufsize) {
					decryptbuf = my_realloc(decryptbuf,
								originalsize,
								MYF(MY_WME));
					decryptbufsize = originalsize;
				} else {
					decryptbuf = my_malloc(originalsize,
							       MYF(MY_WME));
					decryptbufsize = originalsize;
				}
			}

			/* Try to decrypt it */
			gcry_error = gcry_cipher_decrypt(cipher_handle,
							 decryptbuf,
							 originalsize,
							 chunkbuf,
							 chunksize);
			if (gcry_error) {
				msg("%s:decrypt: unable to decrypt chunk - "
				    "%s : %s\n", my_progname,
				    gcry_strsource(gcry_error),
				    gcry_strerror(gcry_error));
				gcry_cipher_close(cipher_handle);
					goto err;
			}

		} else {
			decryptbuf = chunkbuf;
		}

		/* Write it out */
		if (my_write(fileout, decryptbuf, originalsize,
			     MYF(MY_WME | MY_NABP))) {
			msg("%s:decrypt: unable to write output chunk.\n",
			    my_progname);
			goto err;
		}
		ttlchunksread++;
		ttlbytesread += chunksize;
		if (opt_verbose)
			msg("%s:decrypt: %llu chunks read, %llu bytes read\n.",
		    	    my_progname, ttlchunksread, ttlbytesread);
	}

	xb_crypt_read_close(xbcrypt_file);

	if (encrypt_algo != GCRY_CIPHER_NONE)
		gcry_cipher_close(cipher_handle);

	if (decryptbuf && decryptbufsize)
		my_free(decryptbuf);

	if (opt_verbose)
		msg("\n%s:decrypt: done\n", my_progname);

	return 0;
err:
	if (xbcrypt_file)
		xb_crypt_read_close(xbcrypt_file);

	if (encrypt_algo != GCRY_CIPHER_NONE)
		gcry_cipher_close(cipher_handle);

	if (decryptbuf && decryptbufsize)
		my_free(decryptbuf);

	return 1;
}