コード例 #1
0
ファイル: aes256ctr.c プロジェクト: HarryR/ffff-dnsp2p
struct aes256ctr* aes256ctr_init(const char *key)
{
  struct aes256ctr *ac;
  gcry_error_t err;

  if (! (ac = gcry_malloc_secure(sizeof(struct aes256ctr))))
    return NULL;

  err = gcry_cipher_open(&ac->ch, GCRY_CIPHER_AES256, 
			 GCRY_CIPHER_MODE_CTR, GCRY_CIPHER_SECURE);
  if (gcry_err_code(err))
    goto error;
  
  err = gcry_cipher_setkey(ac->ch, key, CIPHER_KEY_SIZE);
  if (gcry_err_code(err))
    goto error;
  
  err = gcry_cipher_setctr(ac->ch, NULL, 0);
  if (gcry_err_code(err))
    goto error;

  ac->idx = CIPHER_BLOCK_SIZE;
  return ac;

 error:
  gcry_free(ac);
  return NULL;
}
コード例 #2
0
ファイル: eax.c プロジェクト: PaulCharlton/wireshark
static void CTR(const guint8 *ws, guint8 *pK, guint8 *pN, guint16 SizeN) 
{
    gcry_cipher_hd_t cipher_hd;
    guint8 ctr[EAX_SIZEOF_KEY];

    BLK_CPY(ctr, ws);
    ctr[12] &= 0x7f;
    ctr[14] &= 0x7f;
    /* open the cipher */
    if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
	return;
    }
    if (gcry_cipher_setkey(cipher_hd, pK, EAX_SIZEOF_KEY)) {
	gcry_cipher_close(cipher_hd);
	return;
    }
    if (gcry_cipher_setctr(cipher_hd, ctr, EAX_SIZEOF_KEY)) {
	gcry_cipher_close(cipher_hd);
	return;
    }
    if (gcry_cipher_encrypt(cipher_hd, pN, SizeN, pN, SizeN)) {
	gcry_cipher_close(cipher_hd);
	return;
    }
    gcry_cipher_close(cipher_hd);
    return;
}
コード例 #3
0
ファイル: gcrypt.c プロジェクト: ut-osa/lacuna
static int gcrypt_set_iv(void *user_ctx, size_t len, uint8_t *iv)
{
   int rc = -PRIV_CRYPT_SOME_ERR;
   struct gcrypt_state *st = user_ctx;

   if (!user_ctx)
      goto out;

   if (st->mode != GCRY_CIPHER_MODE_CTR) {
      if ((rc = gcry_cipher_setiv(st->hd, iv, len)) != 0) {
         DPRINTF("gcry_cipher_setiv: %d\n", rc);
         rc = -PRIV_CRYPT_SOME_ERR;
         goto out;
      }
   } else {
      if ((rc = gcry_cipher_setctr(st->hd, iv, len)) != 0) {
         DPRINTF("gcry_cipher_setctr: %d\n", rc);
         rc = -PRIV_CRYPT_SOME_ERR;
         goto out;
      }
   }

   rc = 0;

 out:
   return rc;
}
コード例 #4
0
ファイル: techutils.c プロジェクト: yleong/gtscp
int aes_ctr  (char* key, int keyLength, char* inFile, long fileLength, char*
	      ctrInit, int blockLength,
              char** outFile){
    gcry_error_t err;
    gcry_cipher_hd_t aeshd;

    err = gcry_cipher_open(&aeshd, GCRY_CIPHER_AES256,
	                           GCRY_CIPHER_MODE_CTR,
	                           GCRY_CIPHER_SECURE);
    if(err){return CIPHER_OPEN_ERROR;}

    err = gcry_cipher_setkey(aeshd, key, keyLength);
    if(err){return CIPHER_SETKEY_ERROR;}
    
    err = gcry_cipher_setctr(aeshd, ctrInit, blockLength);
    if(err){return CIPHER_SETCTR_ERROR;}

    *outFile = (char*)(malloc(fileLength * sizeof(char)));
    DPRINT("going to enc/dec now\n");
    err = gcry_cipher_encrypt(aeshd, *outFile, fileLength, inFile, fileLength);
    if(err){return CIPHER_ENCRYPT_ERROR;}

    DPRINT("done with enc/dec\n");
    gcry_cipher_close(aeshd);
    return NONE;
}
コード例 #5
0
static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
  int mode=GCRY_CIPHER_MODE_CBC;
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    if(strstr(cipher->name,"-ctr"))
      mode=GCRY_CIPHER_MODE_CTR;
    switch (cipher->keysize) {
      case 128:
        if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES128,
              mode, 0)) {
          SAFE_FREE(cipher->key);
          return -1;
        }
        break;
      case 192:
        if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES192,
              mode, 0)) {
          SAFE_FREE(cipher->key);
          return -1;
        }
        break;
      case 256:
        if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES256,
              mode, 0)) {
          SAFE_FREE(cipher->key);
          return -1;
        }
        break;
    }
    if (gcry_cipher_setkey(cipher->key[0], key, cipher->keysize / 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if(mode == GCRY_CIPHER_MODE_CBC){
      if (gcry_cipher_setiv(cipher->key[0], IV, 16)) {

        SAFE_FREE(cipher->key);
        return -1;
      }
    } else {
      if(gcry_cipher_setctr(cipher->key[0],IV,16)){
        SAFE_FREE(cipher->key);
        return -1;
      }
    }
  }

  return 0;
}
コード例 #6
0
/** \brief set the IV
 */
void	skey_ciph_t::set_iv(const skey_ciph_iv_t & iv)				const throw()
{
	void *			iv_ptr = (void *)iv.get_iv_ptr();
	gcry_error_t		err;
	// if no iv is required, return now
	if( require_iv() == false )		return;
	// if an iv is required, set it
	if( ciph_type.get_mode() == skey_ciph_mode_t::CTR ){
		err = gcry_cipher_setctr( gcry_cipher_hd, iv_ptr, get_block_len() );
		DBG_ASSERT( !err );
	}else{
		err = gcry_cipher_setiv( gcry_cipher_hd, iv_ptr, get_block_len() );
		DBG_ASSERT( !err );
	}
}
コード例 #7
0
ファイル: cipher.cpp プロジェクト: hyps/DGT
void AesIcmCipher::calc(KeyDerivation& kd, uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
#ifndef USE_SSL_CRYPTO
  if(!handle_) {
    return;
  }
#endif

  kd.generate(dir_, LABEL_ENC, seq_nr, key_);
#ifdef USE_SSL_CRYPTO
  int ret = AES_set_encrypt_key(key_.getBuf(), key_.getLength()*8, &aes_key_);
  if(ret) {
    cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher ssl key (code: " << ret << ")";
    return;
  }
#else
  gcry_error_t err = gcry_cipher_setkey(handle_, key_.getBuf(), key_.getLength());
  if(err) {
    cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher key: " << AnytunGpgError(err);
    return;
  }
#endif

  calcCtr(kd, seq_nr, sender_id, mux);

#ifndef USE_SSL_CRYPTO
  err = gcry_cipher_setctr(handle_, ctr_.buf_, CTR_LENGTH);
  if(err) {
    cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher CTR: " << AnytunGpgError(err);
    return;
  }

  err = gcry_cipher_encrypt(handle_, out, olen, in, ilen);
  if(err) {
    cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to de/encrypt packet: " << AnytunGpgError(err);
    return;
  }
#else
  if(CTR_LENGTH != AES_BLOCK_SIZE) {
    cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher CTR: size don't fits";
    return;
  }
  unsigned int num = 0;
  std::memset(ecount_buf_, 0, AES_BLOCK_SIZE);
  AES_ctr128_encrypt(in, out, (ilen < olen) ? ilen : olen, &aes_key_, ctr_.buf_, ecount_buf_, &num);
#endif
}
コード例 #8
0
ファイル: libgcrypt.c プロジェクト: dmiller-nmap/libssh2
int
_libssh2_cipher_init(_libssh2_cipher_ctx * h,
                     _libssh2_cipher_type(algo),
                     unsigned char *iv, unsigned char *secret, int encrypt)
{
    int ret;
    int cipher = _libssh2_gcry_cipher(algo);
    int mode = _libssh2_gcry_mode(algo);
    int keylen = gcry_cipher_get_algo_keylen(cipher);

    (void) encrypt;

    ret = gcry_cipher_open(h, cipher, mode, 0);
    if(ret) {
        return -1;
    }

    ret = gcry_cipher_setkey(*h, secret, keylen);
    if(ret) {
        gcry_cipher_close(*h);
        return -1;
    }

    if(mode != GCRY_CIPHER_MODE_STREAM) {
        int blklen = gcry_cipher_get_algo_blklen(cipher);
        if(mode == GCRY_CIPHER_MODE_CTR)
            ret = gcry_cipher_setctr(*h, iv, blklen);
        else
            ret = gcry_cipher_setiv(*h, iv, blklen);
        if(ret) {
            gcry_cipher_close(*h);
            return -1;
        }
    }

    return 0;
}
コード例 #9
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;
}
コード例 #10
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;
}
コード例 #11
0
static gboolean webKitMediaClearKeyDecryptorDecrypt(WebKitMediaCommonEncryptionDecrypt* self, GstBuffer* ivBuffer, GstBuffer* buffer, unsigned subSampleCount, GstBuffer* subSamplesBuffer)
{
    GstMapInfo ivMap;
    if (!gst_buffer_map(ivBuffer, &ivMap, GST_MAP_READ)) {
        GST_ERROR_OBJECT(self, "Failed to map IV");
        return false;
    }

    uint8_t ctr[CLEARKEY_SIZE];
    if (ivMap.size == 8) {
        memset(ctr + 8, 0, 8);
        memcpy(ctr, ivMap.data, 8);
    } else {
        ASSERT(ivMap.size == CLEARKEY_SIZE);
        memcpy(ctr, ivMap.data, CLEARKEY_SIZE);
    }
    gst_buffer_unmap(ivBuffer, &ivMap);

    WebKitMediaClearKeyDecryptPrivate* priv = WEBKIT_MEDIA_CK_DECRYPT_GET_PRIVATE(WEBKIT_MEDIA_CK_DECRYPT(self));
    gcry_error_t error = gcry_cipher_setctr(priv->handle, ctr, CLEARKEY_SIZE);
    if (error) {
        GST_ERROR_OBJECT(self, "gcry_cipher_setctr failed: %s", gpg_strerror(error));
        return false;
    }

    GstMapInfo map;
    gboolean bufferMapped = gst_buffer_map(buffer, &map, static_cast<GstMapFlags>(GST_MAP_READWRITE));
    if (!bufferMapped) {
        GST_ERROR_OBJECT(self, "Failed to map buffer");
        return false;
    }

    GstMapInfo subSamplesMap;
    gboolean subsamplesBufferMapped = gst_buffer_map(subSamplesBuffer, &subSamplesMap, GST_MAP_READ);
    if (!subsamplesBufferMapped) {
        GST_ERROR_OBJECT(self, "Failed to map subsample buffer");
        gst_buffer_unmap(buffer, &map);
        return false;
    }

    GstByteReader* reader = gst_byte_reader_new(subSamplesMap.data, subSamplesMap.size);
    unsigned position = 0;
    unsigned sampleIndex = 0;

    GST_DEBUG_OBJECT(self, "position: %d, size: %zu", position, map.size);

    while (position < map.size) {
        guint16 nBytesClear = 0;
        guint32 nBytesEncrypted = 0;

        if (sampleIndex < subSampleCount) {
            if (!gst_byte_reader_get_uint16_be(reader, &nBytesClear)
                || !gst_byte_reader_get_uint32_be(reader, &nBytesEncrypted)) {
                GST_DEBUG_OBJECT(self, "unsupported");
                gst_byte_reader_free(reader);
                gst_buffer_unmap(buffer, &map);
                gst_buffer_unmap(subSamplesBuffer, &subSamplesMap);
                return false;
            }

            sampleIndex++;
        } else {
            nBytesClear = 0;
            nBytesEncrypted = map.size - position;
        }

        GST_TRACE_OBJECT(self, "%d bytes clear (todo=%zu)", nBytesClear, map.size - position);
        position += nBytesClear;
        if (nBytesEncrypted) {
            GST_TRACE_OBJECT(self, "%d bytes encrypted (todo=%zu)", nBytesEncrypted, map.size - position);
            error = gcry_cipher_decrypt(priv->handle, map.data + position, nBytesEncrypted, 0, 0);
            if (error) {
                GST_ERROR_OBJECT(self, "decryption failed: %s", gpg_strerror(error));
                gst_byte_reader_free(reader);
                gst_buffer_unmap(buffer, &map);
                gst_buffer_unmap(subSamplesBuffer, &subSamplesMap);
                return false;
            }
            position += nBytesEncrypted;
        }
    }

    gst_byte_reader_free(reader);
    gst_buffer_unmap(buffer, &map);
    gst_buffer_unmap(subSamplesBuffer, &subSamplesMap);
    return true;
}
コード例 #12
0
gpointer
encrypt_file (const gchar *input_file_path, const gchar *pwd, const gchar *algo, const gchar *algo_mode)
{
    Metadata *header_metadata = g_new0 (Metadata, 1);
    CryptoKeys *encryption_keys = g_new0 (CryptoKeys, 1);

    set_algo_and_mode (header_metadata, algo, algo_mode);
    gsize algo_key_len = gcry_cipher_get_algo_keylen (header_metadata->algo);
    gsize algo_blk_len = gcry_cipher_get_algo_blklen (header_metadata->algo);

    header_metadata->iv_size = algo_blk_len;  // iv must be the same size as the block size

    gcry_create_nonce (header_metadata->iv, header_metadata->iv_size);
    gcry_create_nonce (header_metadata->salt, KDF_SALT_SIZE);

    if (!setup_keys (pwd, algo_key_len, header_metadata, encryption_keys)) {
        multiple_free (2, (gpointer) &encryption_keys, (gpointer) &header_metadata);
        return g_strdup ("Couldn't setup the encryption keys, exiting...");
    }

    goffset filesize = get_file_size (input_file_path);

    GError *err = NULL;

    GFile *in_file = g_file_new_for_path (input_file_path);
    GFileInputStream *in_stream = g_file_read (in_file, NULL, &err);
    if (err != NULL) {
        multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key,
                            (gpointer) &encryption_keys->hmac_key);
        multiple_free (2, (gpointer) &encryption_keys, (gpointer) &header_metadata);
        g_object_unref (in_file);

        return g_strdup (err->message);
    }

    gchar *output_file_path = g_strconcat (input_file_path, ".enc", NULL);
    GFile *out_file = g_file_new_for_path (output_file_path);
    GFileOutputStream *out_stream = g_file_append_to (out_file, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &err);
    if (err != NULL) {
        multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key,
                            (gpointer) &encryption_keys->hmac_key);
        multiple_free (3, (gpointer) &encryption_keys, (gpointer) &header_metadata, (gpointer) &output_file_path);
        multiple_unref (3, (gpointer) &in_file, (gpointer) &out_file, (gpointer) &in_stream);
        g_input_stream_close (G_INPUT_STREAM (in_stream), NULL, NULL);

        return g_strdup (err->message);
    }

    gcry_cipher_hd_t hd;
    gcry_cipher_open (&hd, header_metadata->algo, header_metadata->algo_mode, 0);
    gcry_cipher_setkey (hd, encryption_keys->crypto_key, algo_key_len);

    gint64 number_of_blocks;
    gint number_of_padding_bytes;
    gchar *ret_msg;
    if (header_metadata->algo_mode == GCRY_CIPHER_MODE_CBC) {
        set_number_of_blocks_and_padding_bytes (filesize, algo_blk_len, &number_of_blocks, &number_of_padding_bytes);
        gcry_cipher_setiv (hd, header_metadata->iv, header_metadata->iv_size);
        ret_msg = encrypt_using_cbc_mode (header_metadata, &hd, number_of_blocks, number_of_padding_bytes, algo_blk_len, in_stream, out_stream);
    }
    else {
        gcry_cipher_setctr (hd, header_metadata->iv, header_metadata->iv_size);
        ret_msg = encrypt_using_ctr_mode (header_metadata, &hd, filesize, in_stream, out_stream);
    }
    if (ret_msg != NULL) {
        multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key,
                            (gpointer) &encryption_keys->hmac_key);
        multiple_free (3, (gpointer) &encryption_keys, (gpointer) &header_metadata, (gpointer) &output_file_path);
        multiple_unref (4, (gpointer) &in_file, (gpointer) &out_file, (gpointer) &in_stream,
                        (gpointer) &out_stream);
        g_input_stream_close (G_INPUT_STREAM (in_stream), NULL, NULL);
        g_output_stream_close (G_OUTPUT_STREAM (out_stream), NULL, NULL);

        return g_strdup (ret_msg);

    }

    gcry_cipher_close (hd);

    guchar *hmac = calculate_hmac (output_file_path, encryption_keys->hmac_key, NULL);
    gssize written_bytes = g_output_stream_write (G_OUTPUT_STREAM (out_stream), hmac, SHA512_DIGEST_SIZE, NULL, &err);
    if (written_bytes == -1) {
        multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key,
                            (gpointer) &encryption_keys->hmac_key);
        multiple_free (4, (gpointer) &encryption_keys, (gpointer) &header_metadata, (gpointer) &output_file_path,
                       (gpointer) &hmac);
        multiple_unref (4, (gpointer) &in_file, (gpointer) &out_file, (gpointer) &in_stream,
                        (gpointer) &out_stream);
        g_output_stream_close (G_OUTPUT_STREAM (out_stream), NULL, NULL);

        return g_strdup (err->message);
    }

    g_input_stream_close (G_INPUT_STREAM (in_stream), NULL, NULL);
    g_output_stream_close (G_OUTPUT_STREAM (out_stream), NULL, NULL);

    multiple_gcry_free (3, (gpointer) &encryption_keys->derived_key, (gpointer) &encryption_keys->crypto_key,
                        (gpointer) &encryption_keys->hmac_key);

    multiple_free (4, (gpointer) &output_file_path, (gpointer) &encryption_keys, (gpointer) &header_metadata,
                   (gpointer) &hmac);

    multiple_unref (4, (gpointer) &in_file, (gpointer) &out_file, (gpointer) &in_stream,
                    (gpointer) &out_stream);

    return NULL;
}
コード例 #13
0
ファイル: pkey_manage.c プロジェクト: pincushionman/gnoMint
gchar * __pkey_manage_aes_decrypt_aux (const gchar *string, const gchar *password, const guchar *iv, const guchar *ctr)
{
    guchar *out = __pkey_manage_from_hex(string);

    guchar *key = __pkey_manage_create_key (password);

    gcry_cipher_hd_t cry_ctxt;
    gcry_error_t get;

    get = gcry_cipher_open (&cry_ctxt, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR, 0);
    if (get) {
        fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
        return NULL;
    }

    if (! iv || !ctr) {

        get = gcry_cipher_setiv(cry_ctxt, &old_iv, 16);
        if (get) {
            fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
            return NULL;
        }

        if (! ctr)
            ctr = old_ctr;

        get = gcry_cipher_setctr(cry_ctxt, &old_ctr, 16);
        if (get) {
            fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
            return NULL;
        }

    } else {
        get = gcry_cipher_setiv(cry_ctxt, iv, 16);
        if (get) {
            fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
            return NULL;
        }

        if (! ctr)
            ctr = old_ctr;

        get = gcry_cipher_setctr(cry_ctxt, ctr, 16);
        if (get) {
            fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
            return NULL;
        }
    }

    get = gcry_cipher_setkey (cry_ctxt, key, 32);
    if (get) {
        fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
        return NULL;
    }

    get = gcry_cipher_decrypt(cry_ctxt, out, strlen(string)/2, NULL, 0);
    if (get) {
        fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
        return NULL;
    }

    gcry_cipher_close (cry_ctxt);

    return (gchar *) out;
}
コード例 #14
0
ファイル: pkey_manage.c プロジェクト: pincushionman/gnoMint
gchar * __pkey_manage_aes_encrypt_aux (const gchar *in, const gchar *password, const guchar *iv, const guchar *ctr)
{
    guchar *key = __pkey_manage_create_key (password);
    guchar *out = (guchar *) g_strdup(in);
    gchar *res;
    gcry_error_t get;

    gcry_cipher_hd_t cry_ctxt;

    get = gcry_cipher_open (&cry_ctxt, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR, 0);
    if (get) {
        fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
        return NULL;
    }

    if (! iv || !ctr) {

        get = gcry_cipher_setiv(cry_ctxt, &old_iv, 16);
        if (get) {
            fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
            return NULL;
        }

        if (! ctr)
            ctr = old_ctr;

        get = gcry_cipher_setctr(cry_ctxt, &old_ctr, 16);
        if (get) {
            fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
            return NULL;
        }

    } else {
        get = gcry_cipher_setiv(cry_ctxt, iv, 16);
        if (get) {
            fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
            return NULL;
        }

        if (! ctr)
            ctr = old_ctr;

        get = gcry_cipher_setctr(cry_ctxt, ctr, 16);
        if (get) {
            fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
            return NULL;
        }
    }
    get = gcry_cipher_setkey (cry_ctxt, key, 32);
    if (get) {
        fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
        return NULL;
    }

    get = gcry_cipher_encrypt(cry_ctxt, out, strlen(in), NULL, 0);
    if (get) {
        fprintf (stderr, "ERR GCRYPT: %ud\n", gcry_err_code(get));
        return NULL;
    }

    gcry_cipher_close (cry_ctxt);

    res = __pkey_manage_to_hex (out, strlen(in));

    g_free (out);

    return res;
}
コード例 #15
0
static void
decrypt (Metadata *header_metadata, CryptoKeys *dec_keys, GFile *enc_data, goffset enc_data_size, GFileOutputStream *ostream)
{
    gcry_cipher_hd_t hd;
    gcry_cipher_open (&hd, header_metadata->algo, header_metadata->algo_mode, 0);
    gcry_cipher_setkey (hd, dec_keys->crypto_key, gcry_cipher_get_algo_keylen (header_metadata->algo));

    if (header_metadata->algo_mode == GCRY_CIPHER_MODE_CBC) {
        gcry_cipher_setiv (hd, header_metadata->iv, header_metadata->iv_size);
    }
    else {
        gcry_cipher_setctr (hd, header_metadata->iv, header_metadata->iv_size);
    }

    GError *err = NULL;

    GFileInputStream *in_stream = g_file_read (enc_data, NULL, &err);
    if (err != NULL) {
        g_printerr ("%s\n", err->message);
        // TODO
        return;
    }
    if (!g_seekable_seek (G_SEEKABLE (in_stream), sizeof (Metadata), G_SEEK_SET, NULL, &err)) {
        g_printerr ("Couldn't set the position, exiting...\n");
        //TODO
        return;
    }

    guchar *enc_buf = g_try_malloc0 (FILE_BUFFER);
    guchar *dec_buf = g_try_malloc0 (FILE_BUFFER);

    if (enc_buf == NULL || dec_buf == NULL) {
        g_printerr ("Error during memory allocation\n");
        // TODO
        return;
    }

    goffset done_size = 0;
    gssize read_len;

    while (done_size < enc_data_size) {
        if ((enc_data_size - done_size) <= FILE_BUFFER) {
            read_len = g_input_stream_read (G_INPUT_STREAM (in_stream), enc_buf, enc_data_size - done_size, NULL, &err);
            gcry_cipher_decrypt (hd, dec_buf, read_len, enc_buf, read_len);
            g_output_stream_write (G_OUTPUT_STREAM (ostream), dec_buf, read_len - header_metadata->padding_value, NULL, &err);
        }
        else {
            read_len = g_input_stream_read (G_INPUT_STREAM (in_stream), enc_buf, FILE_BUFFER, NULL, &err);
            gcry_cipher_decrypt (hd, dec_buf, read_len, enc_buf, read_len);
            g_output_stream_write (G_OUTPUT_STREAM (ostream), dec_buf, read_len, NULL, &err);
        }

        memset (dec_buf, 0, FILE_BUFFER);
        memset (enc_buf, 0, FILE_BUFFER);

        done_size += read_len;
    }

    gcry_cipher_close (hd);

    multiple_free (2, (gpointer) &enc_buf, (gpointer) &dec_buf);

    g_input_stream_close (G_INPUT_STREAM (in_stream), NULL, NULL);

    g_object_unref (in_stream);
}
コード例 #16
0
extern void io_encryption_init(IO_HANDLE ptr, enum gcry_cipher_algos c, enum gcry_md_algos h, enum gcry_cipher_modes m, const uint8_t *k, size_t l, io_extra_t x)
{
	io_private_t *io_ptr = ptr;
	if (!io_ptr || io_ptr->fd < 0)
		return errno = EBADF , (void)NULL;
	/*
	 * start setting up the encryption buffer
	 */
	if (!(io_ptr->buffer_crypt = gcry_malloc_secure(sizeof( buffer_t ))))
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, sizeof( buffer_t ));

	gcry_md_open(&io_ptr->hash_handle, h, GCRY_MD_FLAG_SECURE);
	gcry_cipher_open(&io_ptr->cipher_handle, c, m, GCRY_CIPHER_SECURE);
	/*
	 * generate a hash of the supplied key data
	 */
	size_t hash_length = gcry_md_get_algo_dlen(h);
	uint8_t *hash = gcry_malloc_secure(hash_length);
	if (!hash)
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, hash_length);
	gcry_md_hash_buffer(gcry_md_get_algo(io_ptr->hash_handle), hash, k, l);
	/*
	 * set the key as the hash of supplied data
	 */
	size_t key_length = gcry_cipher_get_algo_keylen(c);
	uint8_t *key = gcry_calloc_secure(key_length, sizeof( byte_t ));
	if (!key)
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, key_length);
	memcpy(key, hash, key_length < hash_length ? key_length : hash_length);
	gcry_cipher_setkey(io_ptr->cipher_handle, key, key_length); /* here is where it blows-up on Windows 8, using AES */
	gcry_free(key);
	/*
	 * the 2011.* versions (incorrectly) used key length instead of block
	 * length; versions after 2014.06 randomly generate the IV instead
	 */
	io_ptr->buffer_crypt->block = gcry_cipher_get_algo_blklen(c);
	uint8_t *iv = gcry_calloc_secure(x.x_iv == IV_BROKEN ? key_length : io_ptr->buffer_crypt->block, sizeof( byte_t ));
	if (!iv)
	   die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, io_ptr->buffer_crypt->block);
	if (x.x_iv == IV_RANDOM)
	{
		if (x.x_encrypt)
		{
			gcry_create_nonce(iv, io_ptr->buffer_crypt->block);
			io_write(ptr, iv, io_ptr->buffer_crypt->block);
		}
		else
			io_read(ptr, iv, io_ptr->buffer_crypt->block);
	}
	else
	{
		uint8_t *iv_hash = gcry_malloc_secure(hash_length);
		if (!iv_hash)
			die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, hash_length);
		/*
		 * set the IV as the hash of the hash
		 */
		gcry_md_hash_buffer(gcry_md_get_algo(io_ptr->hash_handle), iv_hash, hash, hash_length);
		memcpy(iv, iv_hash, io_ptr->buffer_crypt->block < hash_length ? io_ptr->buffer_crypt->block : hash_length);
		gcry_free(iv_hash);
	}
	gcry_free(hash);

	if (m == GCRY_CIPHER_MODE_CTR)
		gcry_cipher_setctr(io_ptr->cipher_handle, iv, io_ptr->buffer_crypt->block);
	else
		gcry_cipher_setiv(io_ptr->cipher_handle, iv, io_ptr->buffer_crypt->block);
	gcry_free(iv);
	/*
	 * set the rest of the buffer
	 */
	if (!(io_ptr->buffer_crypt->stream = gcry_malloc_secure(io_ptr->buffer_crypt->block)))
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, io_ptr->buffer_crypt->block);
	/*
	 * when encrypting/writing data:
	 *   0: length of data buffered so far (in stream)
	 *   1: length of data processed (from d)
	 * when decrypting/reading data:
	 *   0: length of available data in input buffer (stream)
	 *   1: available space in read buffer (d)
	 *   2: next available memory location for data (from d)
	 */
	for (unsigned i = 0; i < OFFSET_SLOTS; i++)
		io_ptr->buffer_crypt->offset[i] = 0;
	io_ptr->cipher_init = true;
	io_ptr->hash_init = true;
	io_ptr->operation = IO_ENCRYPT;
	return;
}
コード例 #17
0
static void
check_ctr_cipher (void)
{
  struct tv
  {
    int algo;
    char key[MAX_DATA_LEN];
    char ctr[MAX_DATA_LEN];
    struct data
    {
      char plaintext[MAX_DATA_LEN];
      int inlen;
      char out[MAX_DATA_LEN];
    }
    data[MAX_DATA_LEN];
  } tv[] =
    {
      /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
      {	GCRY_CIPHER_AES,
	"\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
	"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
	{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
	    16,
	    "\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce" },
	  { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
	    16,
	    "\x98\x06\xf6\x6b\x79\x70\xfd\xff\x86\x17\x18\x7b\xb9\xff\xfd\xff" },
	  { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
	    16,
	    "\x5a\xe4\xdf\x3e\xdb\xd5\xd3\x5e\x5b\x4f\x09\x02\x0d\xb0\x3e\xab" },
	  { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
	    16,
	    "\x1e\x03\x1d\xda\x2f\xbe\x03\xd1\x79\x21\x70\xa0\xf3\x00\x9c\xee" },
	}
      },
      {	GCRY_CIPHER_AES192,
	"\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b"
	"\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
	"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
	{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
	    16,
	    "\x1a\xbc\x93\x24\x17\x52\x1c\xa2\x4f\x2b\x04\x59\xfe\x7e\x6e\x0b" },
	  { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
	    16,
	    "\x09\x03\x39\xec\x0a\xa6\xfa\xef\xd5\xcc\xc2\xc6\xf4\xce\x8e\x94" },
	  { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
	    16,
	    "\x1e\x36\xb2\x6b\xd1\xeb\xc6\x70\xd1\xbd\x1d\x66\x56\x20\xab\xf7" },
	  { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
	    16,
	    "\x4f\x78\xa7\xf6\xd2\x98\x09\x58\x5a\x97\xda\xec\x58\xc6\xb0\x50" },
	}
      },
      {	GCRY_CIPHER_AES256,
	"\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
	"\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
	"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
	{ { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
	    16,
	    "\x60\x1e\xc3\x13\x77\x57\x89\xa5\xb7\xa7\xf5\x04\xbb\xf3\xd2\x28" },
	  { "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
	    16,
	    "\xf4\x43\xe3\xca\x4d\x62\xb5\x9a\xca\x84\xe9\x90\xca\xca\xf5\xc5" },
	  { "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef",
	    16,
	    "\x2b\x09\x30\xda\xa2\x3d\xe9\x4c\xe8\x70\x17\xba\x2d\x84\x98\x8d" },
	  { "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
	    16,
	    "\xdf\xc9\xc5\x8d\xb6\x7a\xad\xa6\x13\xc2\xdd\x08\x45\x79\x41\xa6" }
	}
      }
    };
  gcry_cipher_hd_t hde, hdd;
  char out[MAX_DATA_LEN];
  int i, j, keylen, blklen;
  gcry_error_t err = 0;

  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
    {
      err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0);
      if (!err)
	err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0);
      if (err)
	{
	  fail ("aes-ctr, grcy_open_cipher failed: %s\n", gpg_strerror (err));
	  return;
	}

      keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
      if (!keylen)
	{
	  fail ("aes-ctr, gcry_cipher_get_algo_keylen failed\n");
	  return;
	}

      err = gcry_cipher_setkey (hde, tv[i].key, keylen);
      if (!err)
	err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
      if (err)
	{
	  fail ("aes-ctr, gcry_cipher_setkey failed: %s\n",
		gpg_strerror (err));
	  gcry_cipher_close (hde);
	  gcry_cipher_close (hdd);
	  return;
	}

      blklen = gcry_cipher_get_algo_blklen(tv[i].algo);
      if (!blklen)
	{
	  fail ("aes-ctr, gcry_cipher_get_algo_blklen failed\n");
	  return;
	}

      err = gcry_cipher_setctr (hde, tv[i].ctr, blklen);
      if (!err)
	err = gcry_cipher_setctr (hdd, tv[i].ctr, blklen);
      if (err)
	{
	  fail ("aes-ctr, gcry_cipher_setctr failed: %s\n",
		gpg_strerror (err));
	  gcry_cipher_close (hde);
	  gcry_cipher_close (hdd);
	  return;
	}

      for (j = 0; tv[i].data[j].inlen; j++)
	{
	  err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
				     tv[i].data[j].plaintext,
				     tv[i].data[j].inlen == -1 ?
				     strlen (tv[i].data[j].plaintext) :
				     tv[i].data[j].inlen);
	  if (err)
	    {
	      fail ("aes-ctr, gcry_cipher_encrypt (%d, %d) failed: %s\n",
		    i, j, gpg_strerror (err));
	      gcry_cipher_close (hde);
	      gcry_cipher_close (hdd);
	      return;
	    }

	  if (memcmp (tv[i].data[j].out, out, tv[i].data[j].inlen))
	    fail ("aes-ctr, encrypt mismatch entry %d:%d\n", i, j);

	  err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0);
	  if (err)
	    {
	      fail ("aes-ctr, gcry_cipher_decrypt (%d, %d) failed: %s\n",
		    i, j, gpg_strerror (err));
	      gcry_cipher_close (hde);
	      gcry_cipher_close (hdd);
	      return;
	    }

	  if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen))
	    fail ("aes-ctr, decrypt mismatch entry %d:%d\n", i, j);
	}

      gcry_cipher_close (hde);
      gcry_cipher_close (hdd);
    }
}