コード例 #1
0
ファイル: pal_symmetric.cpp プロジェクト: AlfredoMS/corefx
extern "C" int AppleCryptoNative_CryptorUpdate(CCCryptorRef cryptor,
                                               const uint8_t* pbData,
                                               int32_t cbData,
                                               uint32_t* pbOutput,
                                               int32_t cbOutput,
                                               int32_t* pcbWritten,
                                               int32_t* pccStatus)
{
    if (pccStatus == nullptr)
        return -1;

    *pccStatus = 0;

    if (pbData == nullptr || cbData < 0 || pbOutput == nullptr || cbOutput < cbData || pcbWritten == nullptr)
        return -1;

    CCStatus status = CCCryptorUpdate(cryptor,
                                      pbData,
                                      static_cast<size_t>(cbData),
                                      pbOutput,
                                      static_cast<size_t>(cbOutput),
                                      reinterpret_cast<size_t*>(pcbWritten));

    *pccStatus = status;
    return status == kCCSuccess;
}
コード例 #2
0
CCCryptorStatus
CCCryptWithMode(CCOperation op, CCMode mode, CCAlgorithm alg, CCPadding padding, const void *iv, 
				const void *key, size_t keyLength, const void *tweak, size_t tweakLength,
                int numRounds, CCModeOptions options,
                const void *dataIn, size_t dataInLength, 
                void *dataOut, size_t dataOutAvailable, size_t *dataOutMoved)
#ifdef CRYPTORWITHMODE
{
    CCCryptorRef cref;
	CCCryptorStatus retval;
    size_t moved;

   	if((retval = CCCryptorCreateWithMode(op, mode, alg, padding, iv, key, keyLength, tweak, tweakLength, numRounds, options, &cref)) != kCCSuccess) {
    	return retval;
    }
    
    if((retval = CCCryptorUpdate(cref, dataIn, dataInLength, dataOut, dataOutAvailable, &moved)) != kCCSuccess) {
    	return retval;
    }
    
    dataOut += moved;
    dataOutAvailable -= moved;
    *dataOutMoved = moved;
    
    if((retval = CCCryptorFinal(cref, dataOut, dataOutAvailable, &moved)) != kCCSuccess) {
    	return retval;
    }
    
    *dataOutMoved += moved;

	CCCryptorRelease(cref);
    
    return kCCSuccess;
}
コード例 #3
0
ファイル: encrypt.c プロジェクト: 3gao/shadowsocks-libev
static int cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, size_t *olen,
                                 const uint8_t *input, size_t ilen)
{
#ifdef USE_CRYPTO_APPLECC
    cipher_cc_t *cc = &ctx->cc;
    if (cc->valid == kCCContextValid) {
        CCCryptorStatus ret;
        ret = CCCryptorUpdate(cc->cryptor, input, ilen, output,
                              ilen, olen);
        return (ret == kCCSuccess) ? 1 : 0;
    }
#endif
    cipher_evp_t *evp = &ctx->evp;
#if defined(USE_CRYPTO_OPENSSL)
    int err = 0, tlen = *olen;
    err = EVP_CipherUpdate(evp, (uint8_t *)output, &tlen,
                           (const uint8_t *)input, ilen);
    *olen = tlen;
    return err;
#elif defined(USE_CRYPTO_POLARSSL)
    return !cipher_update(evp, (const uint8_t *)input, ilen,
                          (uint8_t *)output, olen);
#elif defined(USE_CRYPTO_MBEDTLS)
    return !mbedtls_cipher_update(evp, (const uint8_t *)input, ilen,
                                  (uint8_t *)output, olen);
#endif
}
コード例 #4
0
ファイル: main.c プロジェクト: CarlChenCC/examples
static void AES_Operation(CCOperation operation, void* key, size_t keySize,
						  FILE *fpInput, FILE *fpOutput)
{
	CCCryptorRef cryptorRef;
	CCCryptorStatus rc;
	rc = CCCryptorCreate(operation, kCCAlgorithmAES128, 0, key, keySize, NULL, &cryptorRef);
	assert(rc == kCCSuccess);
	
	char rawData[128/8];
	size_t bytesRead;
	while((bytesRead = fread(rawData, 1, sizeof(rawData), fpInput)) > 0)
	{
		char convertedData[128/8];
		size_t dataOutMoved;
		
		if(bytesRead < sizeof(rawData))
			bzero(&rawData[bytesRead], sizeof(rawData) - bytesRead);
		
		rc = CCCryptorUpdate(cryptorRef, rawData, sizeof(rawData), convertedData, sizeof(convertedData), &dataOutMoved);
		assert(rc == kCCSuccess);
		//assert(dataOutMoved == sizeof(convertedData));
		if(dataOutMoved != sizeof(convertedData))
			printf("Data out moved (%d) != converted (%d)\n", dataOutMoved, convertedData);
		
		if(dataOutMoved > 0)
			fwrite(convertedData, dataOutMoved, 1, fpOutput);
	}
	
	CCCryptorRelease(cryptorRef);
}
コード例 #5
0
ファイル: pal_symmetric.c プロジェクト: mono/corefx
int32_t AppleCryptoNative_CryptorUpdate(CCCryptorRef cryptor,
                                        const uint8_t* pbData,
                                        int32_t cbData,
                                        uint32_t* pbOutput,
                                        int32_t cbOutput,
                                        int32_t* pcbWritten,
                                        int32_t* pccStatus)
{
    if (pccStatus == NULL)
        return -1;

    *pccStatus = 0;

    if (pbData == NULL || cbData < 0 || pbOutput == NULL || cbOutput < cbData || pcbWritten == NULL)
        return -1;

    CCStatus status = CCCryptorUpdate(cryptor,
                                      pbData,
                                      (size_t)cbData,
                                      pbOutput,
                                      (size_t)cbOutput,
                                      (size_t*)pcbWritten);

    *pccStatus = status;
    return status == kCCSuccess;
}
コード例 #6
0
            CryptoBuffer CommonCryptoCipher::DecryptBuffer(const CryptoBuffer& encryptedData)
            {
                if (m_failure)
                {
                    AWS_LOGSTREAM_FATAL(CC_LOG_TAG, "Cipher not properly initialized for decryption. Aborting");
                    return CryptoBuffer();
                }

                CheckInitDecryptor();
                size_t lengthWritten = encryptedData.GetLength() + (GetBlockSizeBytes() - 1);
                CryptoBuffer decryptedText(static_cast<size_t>(lengthWritten));

                CCStatus status = CCCryptorUpdate(m_cryptoHandle, encryptedData.GetUnderlyingData(), encryptedData.GetLength(),
                    decryptedText.GetUnderlyingData(), decryptedText.GetLength(), &lengthWritten);

                if (status != kCCSuccess)
                {
                    m_failure = true;
                    AWS_LOGSTREAM_ERROR(CC_LOG_TAG, "Decryption of buffer failed with status code: " << status);
                    return CryptoBuffer();
                }

                if (lengthWritten < decryptedText.GetLength())
                {
                    return CryptoBuffer(decryptedText.GetUnderlyingData(), static_cast<size_t>(lengthWritten));
                }

                return decryptedText;
            }
コード例 #7
0
void sln_cryptor_osx_cc_encrypt(sln_cryptor_t *enc, const void *data,
                                size_t len, char *buf, size_t *blen) {
  /* TODO: output buffer must be exactly the right size, our interface never
   * pads for you */
  CCCryptorRef cryptor = enc->baton;

  CCCryptorUpdate(cryptor, data, len, buf, *blen, blen);
}
コード例 #8
0
/*
 * All of these functions are called by CSPFullPluginSession.
 */
void RC4Context::update(
    void 			*inp,
    size_t 			&inSize, 			// in/out
    void 			*outp,
    size_t 			&outSize)			// in/out
{
    (void) CCCryptorUpdate(rc4Key, inp, inSize, outp, inSize, &outSize);
}
コード例 #9
0
ファイル: crypt_cc.c プロジェクト: Boozekashi/libairfloat
size_t crypt_aes_decrypt(crypt_aes_p d, void* encrypted_data, size_t encrypted_data_size, void* data, size_t data_size) {
    
    size_t data_moved = 0;
    
    CCCryptorUpdate(d->cryptor, encrypted_data, encrypted_data_size, data, data_size, &data_moved);
    
    return data_moved;
    
}
コード例 #10
0
ファイル: CommonCrypto.cpp プロジェクト: UIKit0/encfs
 virtual bool decrypt(const byte *iv, const byte *in, byte *out, int size) {
   CCCryptorRef cryptor;
   CCCryptorCreateWithMode(kCCDecrypt, mode, algorithm, 0, iv, key.data(),
                           key.size(), NULL, 0, 0, 0, &cryptor);
   size_t updateLength = 0;
   CCCryptorUpdate(cryptor, in, size, out, size, &updateLength);
   CCCryptorRelease(cryptor);
   return true;
 }
コード例 #11
0
ファイル: symcrypt.c プロジェクト: randix/redside
int
encryptFinal(void)
{
  CCCryptorStatus status;
  int rv;

  /* finish zlib */
  do {
    strm.next_out = compressed;
    strm.avail_out = sizeof(compressed);

    rv = deflate(&strm, Z_FINISH);
    if (rv != Z_OK && rv != Z_STREAM_END && rv != Z_BUF_ERROR) {
      printf("zlib error %d\n", rv);
    }

    status = CCCryptorUpdate(cryptorRef,
                             compressed, sizeof(compressed) - strm.avail_out,
                             bufOut, sizeof(bufOut), &bufOutLen);
    if (status != kCCSuccess) {
      printf("cryptor update error\n");
      return(-1);
    }

    if (bufOutLen) {
      CCHmacUpdate(&hmacContext, bufOut, bufOutLen);
      writer(bufOut, bufOutLen);
    }
  } while (strm.avail_out == 0);

  deflateEnd(&strm);

  status = CCCryptorFinal(cryptorRef,
                          bufOut, sizeof(bufOut), &bufOutLen);
  if (status != kCCSuccess) {
    printf("cryptor update error: %d\n", status);
  }

  if (bufOutLen) {
      CCHmacUpdate(&hmacContext, bufOut, bufOutLen);
      writer(bufOut, bufOutLen);
  }

  status = CCCryptorRelease(cryptorRef);
  if (status != kCCSuccess) {
    printf("cryptor release error\n");
  }

  CCHmacFinal(&hmacContext, &header.hmacDigest);
  CCHmacFinal(&hmacContextPlain, &header.hmacDigestPlain);

  seeker(0);
  writer(&header, sizeof(header));

  return(0);
}
コード例 #12
0
ファイル: AESUtils.c プロジェクト: Vampireyifeng/MICO
OSStatus    AES_CBCFrame_Update( AES_CBCFrame_Context *inContext, const void *inSrc, size_t inSrcLen, void *inDst )
{
    OSStatus            err;
    const uint8_t *     src;
    const uint8_t *     end;
    uint8_t *           dst;
    size_t              len;
    
    src = (const uint8_t *) inSrc;
    end = src + inSrcLen;
    dst = (uint8_t *) inDst;
    
    // Process whole blocks.
    
    len = inSrcLen & ~( (size_t)( kAES_CBCFrame_Size - 1 ) );
    if( len > 0 )
    {
        #if( AES_UTILS_USE_COMMON_CRYPTO )
            err = CCCryptorReset(  inContext->cryptor, inContext->iv );
            require_noerr( err, exit );
            
            err = CCCryptorUpdate( inContext->cryptor, src, len, dst, len, &len );
            require_noerr( err, exit );
        #elif( AES_UTILS_USE_GLADMAN_AES )
            uint8_t     iv[ kAES_CBCFrame_Size ];
            
            memcpy( iv, inContext->iv, kAES_CBCFrame_Size ); // Use local copy so original IV is not changed.
            if( inContext->encrypt )    aes_cbc_encrypt( src, dst, (int) len, iv, &inContext->ctx.encrypt );
            else                        aes_cbc_decrypt( src, dst, (int) len, iv, &inContext->ctx.decrypt );
        #elif( AES_UTILS_USE_USSL )
            uint8_t     iv[ kAES_CBCFrame_Size ];

            memcpy( iv, inContext->iv, kAES_CBCFrame_Size ); // Use local copy so original IV is not changed.
            if( inContext->encrypt )    aes_crypt_cbc( &inContext->ctx, AES_ENCRYPT, len, iv, (unsigned char *) src, dst );
            else                        aes_crypt_cbc( &inContext->ctx, AES_DECRYPT, len, iv, (unsigned char *) src, dst );
        #else
            uint8_t     iv[ kAES_CBCFrame_Size ];
            
            memcpy( iv, inContext->iv, kAES_CBCFrame_Size ); // Use local copy so original IV is not changed.
            AES_cbc_encrypt( src, dst, (unsigned long) len, &inContext->key, iv, inContext->mode );
        #endif
        src += len;
        dst += len;
    }
    
    // The remaining bytes are just copied unencrypted.
    
    while( src != end ) *dst++ = *src++;
    err = kNoErr;
    
#if( AES_UTILS_USE_COMMON_CRYPTO )
exit:
#endif
    return( err );
}
コード例 #13
0
static int
aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
{
	CCCryptorRef ref = ctx->ctx;
	CCCryptorStatus r;

	r = CCCryptorReset(ref, NULL);
	if (r != kCCSuccess)
		return -1;
	r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
	    AES_BLOCK_SIZE, NULL);
	return (r == kCCSuccess)? 0: -1;
}
コード例 #14
0
ファイル: mz_crypt_apple.c プロジェクト: nmoinvaz/minizip
int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size)
{
    mz_crypt_aes *aes = (mz_crypt_aes *)handle;
    size_t data_moved = 0;
    
    if (aes == NULL || buf == NULL)
        return MZ_PARAM_ERROR;
    if (size != MZ_AES_BLOCK_SIZE)
        return MZ_PARAM_ERROR;

    aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved);
    
    if (aes->error != kCCSuccess)
        return MZ_HASH_ERROR;

    return size;
}
コード例 #15
0
static void transformAES_CBC(CCOperation operation, const CryptoAlgorithmAesCbcParams& parameters, const CryptoKeyAES& key, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise)
{
    static_assert(sizeof(parameters.iv) == kCCBlockSizeAES128, "Initialization vector size must be the same as algorithm block size");

    size_t keyLengthInBytes = key.key().size();
    if (keyLengthInBytes != 16 && keyLengthInBytes != 24 && keyLengthInBytes != 32) {
        promise->reject(nullptr);
        return;
    }

    CCCryptorRef cryptor;
#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
    CCAlgorithm aesAlgorithm = kCCAlgorithmAES;
#else
    CCAlgorithm aesAlgorithm = kCCAlgorithmAES128;
#endif
    CCCryptorStatus status = CCCryptorCreate(operation, aesAlgorithm, kCCOptionPKCS7Padding, key.key().data(), keyLengthInBytes, parameters.iv.data(), &cryptor);
    if (status) {
        promise->reject(nullptr);
        return;
    }

    Vector<uint8_t> result(CCCryptorGetOutputLength(cryptor, data.second, true));

    size_t bytesWritten;
    status = CCCryptorUpdate(cryptor, data.first, data.second, result.data(), result.size(), &bytesWritten);
    if (status) {
        promise->reject(nullptr);
        return;
    }

    uint8_t* p = result.data() + bytesWritten;
    status = CCCryptorFinal(cryptor, p, result.end() - p, &bytesWritten);
    p += bytesWritten;
    if (status) {
        promise->reject(nullptr);
        return;
    }

    ASSERT(p <= result.end());
    result.shrink(p - result.begin());

    CCCryptorRelease(cryptor);

    promise->fulfill(result);
}
コード例 #16
0
ファイル: AESUtils.c プロジェクト: Vampireyifeng/MICO
OSStatus    AES_ECB_Update( AES_ECB_Context *inContext, const void *inSrc, size_t inLen, void *inDst )
{
    OSStatus            err;
    const uint8_t *     src;
    uint8_t *           dst;
    size_t              n;
    
    // inSrc and inDst may be the same, but otherwise, the buffers must not overlap.
    
#if( DEBUG )
    if( inSrc != inDst ) check_ptr_overlap( inSrc, inLen, inDst, inLen );
    if( ( inLen % kAES_ECB_Size ) != 0 ) aes_log( "ECB doesn't support non-block-sized operations (%d bytes)", (int)inLen );
#endif
    
    src = (const uint8_t *) inSrc;
    dst = (uint8_t *) inDst;
    for( n = inLen / kAES_ECB_Size; n > 0; --n )
    {
        #if( AES_UTILS_USE_COMMON_CRYPTO )
            size_t      len;
            
            err = CCCryptorUpdate( inContext->cryptor, src, kAES_ECB_Size, dst, kAES_ECB_Size, &len );
            require_noerr( err, exit );
            check( len == kAES_ECB_Size );
        #elif( AES_UTILS_USE_GLADMAN_AES )
            if( inContext->encrypt )    aes_ecb_encrypt( src, dst, kAES_ECB_Size, &inContext->ctx.encrypt );
            else                        aes_ecb_decrypt( src, dst, kAES_ECB_Size, &inContext->ctx.decrypt );
        #elif( AES_UTILS_USE_USSL )
            aes_crypt_ecb( &inContext->ctx, inContext->mode, (unsigned char *) src, dst );
        #else
            inContext->cryptFunc( src, dst, &inContext->key );
        #endif
        src += kAES_ECB_Size;
        dst += kAES_ECB_Size;
    }
    err = kNoErr;
    
#if( AES_UTILS_USE_COMMON_CRYPTO )
exit:
#endif
    return( err );
}
コード例 #17
0
ファイル: encrypt.c プロジェクト: DrShahin-/shadowsocks-libev
static int cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, int *olen,
                                 const uint8_t *input, int ilen)
{
#ifdef USE_CRYPTO_APPLECC
    cipher_cc_t *cc = &ctx->cc;
    if (cc->valid == kCCContextValid)
    {
        CCCryptorStatus ret;
        ret = CCCryptorUpdate(cc->cryptor, input, ilen, output, ilen + BLOCK_SIZE, (size_t *) olen);
        return (ret == kCCSuccess) ? 1 : 0;
    }
#endif
    cipher_evp_t *evp = &ctx->evp;
#if defined(USE_CRYPTO_OPENSSL)
    return EVP_CipherUpdate(evp, (uint8_t *) output, olen,
                            (const uint8_t *) input, (size_t) ilen);
#elif defined(USE_CRYPTO_POLARSSL)
    return !cipher_update(evp, (const uint8_t *) input, (size_t) ilen,
                          (uint8_t *) output, (size_t *) olen);
#endif
}
コード例 #18
0
ファイル: evp-cc.c プロジェクト: Sp1l/heimdal
static int
cc_do_cipher(EVP_CIPHER_CTX *ctx,
	     unsigned char *out,
	     const unsigned char *in,
	     unsigned int size)
{
    struct cc_key *cc = ctx->cipher_data;
    CCCryptorStatus ret;
    size_t moved;

    memcpy(out, in, size);

    ret = CCCryptorUpdate(cc->href, in, size, out, size, &moved);
    if (ret)
	return 0;

    if (moved != size)
	return 0;

    return 1;
}
コード例 #19
0
ファイル: symcrypt.c プロジェクト: randix/redside
int
decryptData(void *bufIn, size_t bufInLen)
{
  CCCryptorStatus status;
  int rv;

  CCHmacUpdate(&hmacContext, bufIn, bufInLen);

  status = CCCryptorUpdate(cryptorRef,
                           bufIn, bufInLen,
                           compressed, sizeof(compressed), &compressedLen);
  if (status != kCCSuccess) {
    printf("cryptor update error\n");
    return(-1);
  }

  if (compressedLen) {
    strm.next_in = compressed;
    strm.avail_in = (uint)compressedLen;

    do {
      strm.next_out = bufOut;
      strm.avail_out = sizeof(bufOut);

      rv = inflate(&strm, Z_NO_FLUSH);
      if (rv != Z_OK && rv != Z_STREAM_END && rv != Z_BUF_ERROR) {
         printf("zlib error %d\n", rv);
      }

      bufOutLen = sizeof(bufOut) - strm.avail_out;
      if (bufOutLen) {
        CCHmacUpdate(&hmacContextPlain, bufOut, bufOutLen);
        writer(bufOut, bufOutLen);
      }

    } while (strm.avail_out == 0);
  }

  return(0);
}
コード例 #20
0
static int __aes_process (crypto_aes_t *crypto,
                          CCCryptorRef cryptor,
                          const void *src,
                          unsigned int src_size,
                          void *dst,
                          unsigned int *dst_size)
{
    size_t out_avail;
    size_t used = 0;
    uint8_t *outp;
    size_t moved;

    pthread_mutex_lock(&(crypto->lock));

    outp = (uint8_t *)dst;
    out_avail = src_size + 16;
    if (CCCryptorUpdate(cryptor, src, src_size, outp, out_avail, &moved)) {
        pthread_mutex_unlock(&(crypto->lock));
        CCCryptorReset(cryptor, crypto->iv);
        return(-2);
    }

    outp += moved;
    used += moved;
    out_avail -= moved;
    if (CCCryptorFinal(cryptor, outp, out_avail, &moved)) {
        pthread_mutex_unlock(&(crypto->lock));
        CCCryptorReset(cryptor, crypto->iv);
        return(-3);
    }

    used += moved;
    if (dst_size != NULL)
        *dst_size = used;

    CCCryptorReset(cryptor, crypto->iv);
    pthread_mutex_unlock(&(crypto->lock));
    return(0);
}
コード例 #21
0
ファイル: evp-cc.c プロジェクト: Sp1l/heimdal
static int
cc_do_cfb8_cipher(EVP_CIPHER_CTX *ctx,
                  unsigned char *out,
                  const unsigned char *in,
                  unsigned int size)
{
    struct cc_key *cc = ctx->cipher_data;
    CCCryptorStatus ret;
    size_t moved;
    unsigned int i;

    for (i = 0; i < size; i++) {
        unsigned char oiv[EVP_MAX_IV_LENGTH + 1];

        assert(ctx->cipher->iv_len + 1 <= sizeof(oiv));
        memcpy(oiv, ctx->iv, ctx->cipher->iv_len);

        ret = CCCryptorUpdate(cc->href, ctx->iv, ctx->cipher->iv_len,
                              ctx->iv, ctx->cipher->iv_len, &moved);
        if (ret)
            return 0;

        if (moved != ctx->cipher->iv_len)
            return 0;

        if (!ctx->encrypt)
            oiv[ctx->cipher->iv_len] = in[i];
        out[i] = in[i] ^ ctx->iv[0];
        if (ctx->encrypt)
            oiv[ctx->cipher->iv_len] = out[i];

        memcpy(ctx->iv, &oiv[1], ctx->cipher->iv_len);
    }

    return 1;
}
コード例 #22
0
int main(int argc, char **argv)
{
	unsigned loops = LOOPS_DEF;
	unsigned bufSize = BUFSIZE_DEF;
	unsigned algFirst = ALG_FIRST;
	unsigned algLast = ALG_LAST;
	bool ecbMode = false;
	extern char *optarg;
	int arg;
	while ((arg = getopt(argc, argv, "a:l:b:eh")) != -1) {
		switch (arg) {
			case 'a':
				switch(optarg[0]) {
					case 'a':
						algFirst = algLast = ALG_AES_128;
						break;
					case 'n':
						algFirst = algLast = ALG_AES_192;
						break;
					case 'A':
						algFirst = algLast = ALG_AES_256;
						break;
					case 'd':
						algFirst = algLast = ALG_DES;
						break;
					case '3':
						algFirst = algLast = ALG_3DES;
						break;
					case 'c':
						algFirst = algLast = ALG_CAST;
					case '4':
						algFirst = algLast = ALG_RC4;
				}
				break;
			case 'l':
				loops = atoi(optarg);
				break;
			case 'b':
				bufSize = atoi(optarg);
				break;
			case 'e':
				ecbMode = true;
				break;
			case 'h':
				usage(argv);
		}
	}
	if(optind != argc) {
		usage(argv);
	}

	/* 
	 * encrypt and decrypt on workBuf
	 * save original ptext in saveBuf, compare at end as sanity check 
	 *   for ECB only
	 */
	unsigned char *workBuf = (unsigned char *)malloc(bufSize);
	unsigned char *saveBuf = (unsigned char *)malloc(bufSize);
	if((workBuf == NULL) || (saveBuf == NULL)) {
		printf("***malloc failure\n");
		exit(1);
	}
	appGetRandomBytes(workBuf, bufSize);
	memmove(saveBuf, workBuf, bufSize);
	
	uint8_t keyBytes[MAX_KEY_SIZE];
	size_t keyLength;
	
	appGetRandomBytes(keyBytes, MAX_KEY_SIZE);
	
	CCCryptorRef cryptor;
	CCAlgorithm alg;
	CCOptions options = 0;
	OSStatus ortn;
	
	if(ecbMode) {
		options |= kCCOptionECBMode;
	}
	
	unsigned currAlg;
	for(currAlg=algFirst; currAlg<=algLast; currAlg++) {
		const char *algStr = NULL;
		
		switch(currAlg) {
			case ALG_DES:
				keyLength = kCCKeySizeDES;
				alg = kCCAlgorithmDES;
				algStr = "DES ";
				break;
			case ALG_3DES:
				keyLength = kCCKeySize3DES;
				alg = kCCAlgorithm3DES;
				algStr = "3DES";
				break;
			case ALG_AES_128:
				keyLength = kCCKeySizeAES128;
				alg = kCCAlgorithmAES128;
				algStr = "AES128";
				break;
			case ALG_AES_192:
				keyLength = kCCKeySizeAES192;
				alg = kCCAlgorithmAES128;
				algStr = "AES192";
				break;
			case ALG_AES_256:
				keyLength = kCCKeySizeAES256;
				alg = kCCAlgorithmAES128;
				algStr = "AES256";
				break;
			case ALG_CAST:
				keyLength = kCCKeySizeMaxCAST;
				alg = kCCAlgorithmCAST;
				algStr = "CAST";
				break;
			case ALG_RC4:
				keyLength = kCCKeySizeMaxRC4;
				alg = kCCAlgorithmRC4;
				algStr = "RC4";
				break;
		}
		
		printf("Algorithm: %s  keySize: %u  mode: %s  loops: %u  bufSize: %u\n",
			algStr, (unsigned)keyLength, ecbMode ? "ECB" : "CBC",
			(unsigned)loops, (unsigned)bufSize);
			
		CFAbsoluteTime start, end;
		unsigned loop;
		size_t thisMoved;
		
		/* encrypt: GO */
		start = CFAbsoluteTimeGetCurrent();
		
		ortn = CCCryptorCreate(kCCEncrypt, alg, options,
			keyBytes, keyLength, NULL, &cryptor);
		if(ortn) {
			printCCError("CCCryptorCreate", ortn);
			exit(1);
		}
		
		for(loop=0; loop<loops; loop++) {
			ortn = CCCryptorUpdate(cryptor, workBuf, bufSize,
				workBuf, bufSize, &thisMoved);
			if(ortn) {
				printCCError("CCCryptorUpdate", ortn);
				exit(1);
			}
		}
		/* no padding, CCCryptFinal not needed */
		end = CFAbsoluteTimeGetCurrent();
		
		printf("   encrypt %u * %u bytes took %gs: %g KBytes/s\n",
			(unsigned)loops, (unsigned)bufSize,
			end - start,
			(loops * bufSize) / (end - start) / 1024.0);
			
		/* dncrypt: GO */
		start = CFAbsoluteTimeGetCurrent();
		
		ortn = CCCryptorCreate(kCCDecrypt, alg, options,
			keyBytes, keyLength, NULL, &cryptor);
		if(ortn) {
			printCCError("CCCryptorCreate", ortn);
			exit(1);
		}
		
		for(loop=0; loop<loops; loop++) {
			ortn = CCCryptorUpdate(cryptor, workBuf, bufSize,
				workBuf, bufSize, &thisMoved);
			if(ortn) {
				printCCError("CCCryptorUpdate", ortn);
				exit(1);
			}
		}
		/* no padding, CCCryptFinal not needed */
		end = CFAbsoluteTimeGetCurrent();
		
		printf("   decrypt %u * %u bytes took %gs: %g KBytes/s\n",
			(unsigned)loops, (unsigned)bufSize,
			end - start,
			(loops * bufSize) / (end - start) / 1024.0);
			
		if(ecbMode) {
			if(memcmp(workBuf, saveBuf, bufSize)) {
				printf("***plaintext miscompare!\n");
			}
		}
	}
	return 0;
}
コード例 #23
0
ファイル: AESUtils.c プロジェクト: Vampireyifeng/MICO
OSStatus
    AES_CBCFrame_Update2( 
        AES_CBCFrame_Context *  inContext, 
        const void *            inSrc1, 
        size_t                  inLen1, 
        const void *            inSrc2, 
        size_t                  inLen2, 
        void *                  inDst )
{
    const uint8_t *     src1 = (const uint8_t *) inSrc1;
    const uint8_t *     end1 = src1 + inLen1;
    const uint8_t *     src2 = (const uint8_t *) inSrc2;
    const uint8_t *     end2 = src2 + inLen2;
    uint8_t *           dst  = (uint8_t *) inDst;
    OSStatus            err;
    size_t              len;
    size_t              i;
#if( !AES_UTILS_USE_COMMON_CRYPTO )
    uint8_t             iv[ kAES_CBCFrame_Size ];
#endif
    
#if( AES_UTILS_USE_COMMON_CRYPTO )
    if( ( inLen1 + inLen2 ) >= kAES_CBCFrame_Size )
    {
        err = CCCryptorReset(  inContext->cryptor, inContext->iv );
        require_noerr( err, exit );
    }
#else
    memcpy( iv, inContext->iv, kAES_CBCFrame_Size ); // Use local copy so original IV is not changed.
#endif
    
    // Process all whole blocks from buffer 1.
    
    len = inLen1 & ~( (size_t)( kAES_CBCFrame_Size - 1 ) );
    if( len > 0 )
    {
        #if( AES_UTILS_USE_COMMON_CRYPTO )
            err = CCCryptorUpdate( inContext->cryptor, src1, len, dst, len, &len );
            require_noerr( err, exit );
        #elif( AES_UTILS_USE_GLADMAN_AES )
            if( inContext->encrypt )    aes_cbc_encrypt( src1, dst, (int) len, iv, &inContext->ctx.encrypt );
            else                        aes_cbc_decrypt( src1, dst, (int) len, iv, &inContext->ctx.decrypt );
        #elif( AES_UTILS_USE_USSL )
            if( inContext->encrypt )    aes_crypt_cbc( &inContext->ctx, AES_ENCRYPT, len, iv, (unsigned char *) src1, dst );
            else                        aes_crypt_cbc( &inContext->ctx, AES_DECRYPT, len, iv, (unsigned char *) src1, dst );
        #else
            AES_cbc_encrypt( src1, dst, (unsigned long) len, &inContext->key, iv, inContext->mode );
        #endif
        src1 += len;
        dst  += len;
    }
    
    // If there are any partial block bytes in buffer 1 and enough bytes in buffer 2 to fill a 
    // block then combine them into a temporary buffer and encrypt it.
    
    if( ( src1 != end1 ) && ( ( ( end1 - src1 ) + ( end2 - src2 ) ) >= kAES_CBCFrame_Size ) )
    {
        uint8_t     buf[ kAES_CBCFrame_Size ];
        
        for( i = 0; src1 != end1; ++i )
        {
            buf[ i ] = *src1++;
        }
        for( ; ( i < kAES_CBCFrame_Size ) && ( src2 != end2 ); ++i )
        {
            buf[ i ] = *src2++;
        }
        #if( AES_UTILS_USE_COMMON_CRYPTO )
            err = CCCryptorUpdate( inContext->cryptor, buf, i, dst, i, &i );
            require_noerr( err, exit );
        #elif( AES_UTILS_USE_GLADMAN_AES )
            if( inContext->encrypt )    aes_cbc_encrypt( buf, dst, (int) i, iv, &inContext->ctx.encrypt );
            else                        aes_cbc_decrypt( buf, dst, (int) i, iv, &inContext->ctx.decrypt );
        #elif( AES_UTILS_USE_USSL )
            if( inContext->encrypt )    aes_crypt_cbc( &inContext->ctx, AES_ENCRYPT, i, iv, buf, dst );
            else                        aes_crypt_cbc( &inContext->ctx, AES_DECRYPT, i, iv, buf, dst );
        #else
            AES_cbc_encrypt( buf, dst, (unsigned long) i, &inContext->key, iv, inContext->mode );
        #endif
        dst += i;
    }
    
    // Process any remaining whole blocks in buffer 2.
    
    len = ( (size_t)( end2 - src2 ) ) & ~( (size_t)( kAES_CBCFrame_Size - 1 ) );
    if( len > 0 )
    {
        #if( AES_UTILS_USE_COMMON_CRYPTO )
            err = CCCryptorUpdate( inContext->cryptor, src2, len, dst, len, &len );
            require_noerr( err, exit );
        #elif( AES_UTILS_USE_GLADMAN_AES )
            if( inContext->encrypt )    aes_cbc_encrypt( src2, dst, (int) len, iv, &inContext->ctx.encrypt );
            else                        aes_cbc_decrypt( src2, dst, (int) len, iv, &inContext->ctx.decrypt );
        #elif( AES_UTILS_USE_USSL )
            if( inContext->encrypt )    aes_crypt_cbc( &inContext->ctx, AES_ENCRYPT, len, iv, (unsigned char *) src2, dst );
            else                        aes_crypt_cbc( &inContext->ctx, AES_DECRYPT, len, iv, (unsigned char *) src2, dst );
        #else
            AES_cbc_encrypt( src2, dst, (unsigned long) len, &inContext->key, iv, inContext->mode );
        #endif
        src2 += len;
        dst  += len;
    }
    
    // Any remaining bytes are just copied unencrypted.
    
    while( src1 != end1 ) *dst++ = *src1++;
    while( src2 != end2 ) *dst++ = *src2++;
    err = kNoErr;
    
#if( AES_UTILS_USE_COMMON_CRYPTO )
exit:
#endif
    return( err );
}
コード例 #24
0
ファイル: ccSymTest.cpp プロジェクト: gunyarakun/CommonCrypto
/* 
 * Test harness for CCCryptor with lots of options. 
 */
CCCryptorStatus doCCCrypt(
	bool forEncrypt,
	CCAlgorithm encrAlg,			
	bool doCbc,
	bool doPadding,
	const void *keyBytes, size_t keyLen,
	const void *iv,
	bool randUpdates,
	bool inPlace,								/* !doPadding only */
	size_t ctxSize,								/* if nonzero, we allocate ctx */
	bool askOutSize,
	const uint8_t *inText, size_t inTextLen,
	uint8_t **outText, size_t *outTextLen)		/* both returned, WE malloc */
{
	CCCryptorRef	cryptor = NULL;
	CCCryptorStatus crtn;
	CCOperation		op = forEncrypt ? kCCEncrypt : kCCDecrypt;
	CCOptions		options = 0;
	uint8_t			*outBuf = NULL;			/* mallocd output buffer */
	uint8_t			*outp;					/* running ptr into outBuf */
	const uint8		*inp;					/* running ptr into inText */
	size_t			outLen;					/* bytes remaining in outBuf */
	size_t			toMove;					/* bytes remaining in inText */
	size_t			thisMoveOut;			/* output from CCCryptUpdate()/CCCryptFinal() */
	size_t			outBytes;				/* total bytes actually produced in outBuf */
	char			ctx[CC_MAX_CTX_SIZE];	/* for CCCryptorCreateFromData() */
	uint8_t			*textMarker = NULL;		/* 8 bytes of marker here after expected end of 
											 * output */
	char			*ctxMarker = NULL;		/* ditto for caller-provided context */
	unsigned		dex;
	size_t			askedOutSize;			/* from the lib */
	size_t			thisOutLen;				/* dataOutAvailable we use */
	
	if(ctxSize > CC_MAX_CTX_SIZE) {
		printf("***HEY! Adjust CC_MAX_CTX_SIZE!\n");
		exit(1);
	}
	if(!doCbc) {
		options |= kCCOptionECBMode;
	}
	if(doPadding) {
		options |= kCCOptionPKCS7Padding;
	}
	
	/* just hack this one */
	outLen = inTextLen;
	if(forEncrypt) {
		outLen += MAX_BLOCK_SIZE;
	}
	
	outBuf = (uint8_t *)malloc(outLen + MARKER_LENGTH);
	memset(outBuf, 0xEE, outLen + MARKER_LENGTH);
	
	/* library should not touch this memory */
	textMarker = outBuf + outLen;
	memset(textMarker, MARKER_BYTE, MARKER_LENGTH);
	
	/* subsequent errors to errOut: */

	if(inPlace) {
		memmove(outBuf, inText, inTextLen);
		inp = outBuf;
	}
	else {
		inp = inText;
	}

	if(!randUpdates) {
		/* one shot */
		if(askOutSize) {
			crtn = CCCrypt(op, encrAlg, options,
				keyBytes, keyLen, iv,
				inp, inTextLen,
				outBuf, 0, &askedOutSize);
			if(crtn != kCCBufferTooSmall) {
				printf("***Did not get kCCBufferTooSmall as expected\n");
				printf("   alg %d inTextLen %lu cbc %d padding %d keyLen %lu\n",
					(int)encrAlg, (unsigned long)inTextLen, (int)doCbc, (int)doPadding,
					(unsigned long)keyLen);
				printCCError("CCCrypt", crtn);
				crtn = -1;
				goto errOut;
			}
			outLen = askedOutSize;
		}
		crtn = CCCrypt(op, encrAlg, options,
			keyBytes, keyLen, iv,
			inp, inTextLen,
			outBuf, outLen, &outLen);
		if(crtn) {
			printCCError("CCCrypt", crtn);
			goto errOut;
		}
		*outText = outBuf;
		*outTextLen = outLen;
		goto errOut;
	}
	
	/* random multi updates */
	if(ctxSize) {
		size_t ctxSizeCreated;
		
		if(askOutSize) {
			crtn = CCCryptorCreateFromData(op, encrAlg, options,
				keyBytes, keyLen, iv,
				ctx, 0 /* ctxSize */,
				&cryptor, &askedOutSize);
			if(crtn != kCCBufferTooSmall) {
				printf("***Did not get kCCBufferTooSmall as expected\n");
				printCCError("CCCryptorCreateFromData", crtn);
				crtn = -1;
				goto errOut;
			}
			ctxSize = askedOutSize;
		}
		crtn = CCCryptorCreateFromData(op, encrAlg, options,
			keyBytes, keyLen, iv,
			ctx, ctxSize, &cryptor, &ctxSizeCreated);
		if(crtn) {
			printCCError("CCCryptorCreateFromData", crtn);
			return crtn;
		}
		ctxMarker = ctx + ctxSizeCreated;
		memset(ctxMarker, MARKER_BYTE, MARKER_LENGTH);
	}
	else {
		crtn = CCCryptorCreate(op, encrAlg, options,
			keyBytes, keyLen, iv,
			&cryptor);
		if(crtn) {
			printCCError("CCCryptorCreate", crtn);
			return crtn;
		}
	}
	
	toMove = inTextLen;		/* total to go */
	outp = outBuf;
	outBytes = 0;			/* bytes actually produced in outBuf */
	
	while(toMove) {
		uint32 thisMoveIn;			/* input to CCryptUpdate() */
		
		thisMoveIn = genRand(1, toMove);
		logSize(("###ptext segment len %lu\n", (unsigned long)thisMoveIn)); 
		if(askOutSize) {
			thisOutLen = CCCryptorGetOutputLength(cryptor, thisMoveIn, false);
		}
		else {
			thisOutLen = outLen;
		}
		crtn = CCCryptorUpdate(cryptor, inp, thisMoveIn,
			outp, thisOutLen, &thisMoveOut);
		if(crtn) {
			printCCError("CCCryptorUpdate", crtn);
			goto errOut;
		}
		inp			+= thisMoveIn;
		toMove		-= thisMoveIn;
		outp		+= thisMoveOut;
		outLen   	-= thisMoveOut;
		outBytes	+= thisMoveOut;
	}
	
	if(doPadding) {
		/* Final is not needed if padding is disabled */
		if(askOutSize) {
			thisOutLen = CCCryptorGetOutputLength(cryptor, 0, true);
		}
		else {
			thisOutLen = outLen;
		}
		crtn = CCCryptorFinal(cryptor, outp, thisOutLen, &thisMoveOut);
	}
	else {
		thisMoveOut = 0;
		crtn = kCCSuccess;
	}
	
	if(crtn) {
		printCCError("CCCryptorFinal", crtn);
		goto errOut;
	}
	
	outBytes += thisMoveOut;
	*outText = outBuf;
	*outTextLen = outBytes;
	crtn = kCCSuccess;

	for(dex=0; dex<MARKER_LENGTH; dex++) {
		if(textMarker[dex] != MARKER_BYTE) {
			printf("***lib scribbled on our textMarker memory (op=%s)!\n",
				forEncrypt ? "encrypt" : "decrypt");
			crtn = (CCCryptorStatus)-1;
		}
	}
	if(ctxSize) {
		for(dex=0; dex<MARKER_LENGTH; dex++) {
			if(ctxMarker[dex] != MARKER_BYTE) {
				printf("***lib scribbled on our ctxMarker memory (op=%s)!\n",
					forEncrypt ? "encrypt" : "decrypt");
				crtn = (CCCryptorStatus)-1;
			}
		}
	}
	
errOut:
	if(crtn) {
		if(outBuf) {
			free(outBuf);
		}
	}
	if(cryptor) {
		CCCryptorRelease(cryptor);
	}
	return crtn;
}
コード例 #25
0
ファイル: AESUtils.c プロジェクト: Vampireyifeng/MICO
OSStatus    AES_CTR_Update( AES_CTR_Context *inContext, const void *inSrc, size_t inLen, void *inDst )
{
    OSStatus            err;
    const uint8_t *     src;
    uint8_t *           dst;
    uint8_t *           buf;
    size_t              used;
    size_t              i;
    
    // inSrc and inDst may be the same, but otherwise, the buffers must not overlap.
    
#if( DEBUG )
    if( inSrc != inDst ) check_ptr_overlap( inSrc, inLen, inDst, inLen );
#endif
    
    src = (const uint8_t *) inSrc;
    dst = (uint8_t *) inDst;
    
    // If there's any buffered key material from a previous block then use that first.
    
    buf  = inContext->buf;
    used = inContext->used;
    while( ( inLen > 0 ) && ( used != 0 ) ) 
    {
        *dst++ = *src++ ^ buf[ used++ ];
        used %= kAES_CTR_Size;
        inLen -= 1;
    }
    inContext->used = used;
    
    // Process whole blocks.
    
    while( inLen >= kAES_CTR_Size )
    {
        #if( AES_UTILS_USE_COMMON_CRYPTO )
            err = CCCryptorUpdate( inContext->cryptor, inContext->ctr, kAES_CTR_Size, buf, kAES_CTR_Size, &i );
            require_noerr( err, exit );
            require_action( i == kAES_CTR_Size, exit, err = kSizeErr );
        #elif( AES_UTILS_USE_GLADMAN_AES )
            aes_ecb_encrypt( inContext->ctr, buf, kAES_CTR_Size, &inContext->ctx );
        #elif( AES_UTILS_USE_USSL )
            aes_crypt_ecb( &inContext->ctx, AES_ENCRYPT, inContext->ctr, buf );
        #else
            AES_encrypt( inContext->ctr, buf, &inContext->key );
        #endif
        AES_CTR_Increment( inContext->ctr );
        
        for( i = 0; i < kAES_CTR_Size; ++i )
        {
            dst[ i ] = src[ i ] ^ buf[ i ];
        }
        src   += kAES_CTR_Size;
        dst   += kAES_CTR_Size;
        inLen -= kAES_CTR_Size;
    }
    
    // Process any trailing sub-block bytes. Extra key material is buffered for next time.
    
    if( inLen > 0 )
    {
        #if( AES_UTILS_USE_COMMON_CRYPTO )
            err = CCCryptorUpdate( inContext->cryptor, inContext->ctr, kAES_CTR_Size, buf, kAES_CTR_Size, &i );
            require_noerr( err, exit );
            require_action( i == kAES_CTR_Size, exit, err = kSizeErr );
        #elif( AES_UTILS_USE_GLADMAN_AES )
            aes_ecb_encrypt( inContext->ctr, buf, kAES_CTR_Size, &inContext->ctx );
        #elif( AES_UTILS_USE_USSL )
            aes_crypt_ecb( &inContext->ctx, AES_ENCRYPT, inContext->ctr, buf );
        #else
            AES_encrypt( inContext->ctr, buf, &inContext->key );
        #endif
        AES_CTR_Increment( inContext->ctr );
        
        for( i = 0; i < inLen; ++i )
        {
            *dst++ = *src++ ^ buf[ used++ ];
        }
        
        // For legacy mode, always leave the used amount as 0 so we always increment the counter each time.
        
        if( !inContext->legacy )
        {
            inContext->used = used;
        }
    }
    err = kNoErr;
    
#if( AES_UTILS_USE_COMMON_CRYPTO )
exit:
#endif
    return( err );
}
コード例 #26
0
ファイル: wi-cipher.c プロジェクト: ProfDrLuigi/zanka
wi_integer_t wi_cipher_decrypt_bytes(wi_cipher_t *cipher, const void *encrypted_buffer, wi_uinteger_t encrypted_length, void *decrypted_buffer) {
#ifdef WI_CIPHER_OPENSSL
	int			decrypted_length, padded_length;
	
	if(EVP_DecryptUpdate(&cipher->decrypt_ctx, decrypted_buffer, &decrypted_length, encrypted_buffer, encrypted_length) != 1) {
		wi_error_set_openssl_error();
		
		return -1;
	}
	
	if(EVP_DecryptFinal_ex(&cipher->decrypt_ctx, decrypted_buffer + decrypted_length, &padded_length) != 1) {
		wi_error_set_openssl_error();
		
		return -1;
	}
	
	if(EVP_DecryptInit_ex(&cipher->decrypt_ctx, NULL, NULL, NULL, NULL) != 1) {
		wi_error_set_openssl_error();
		
		return -1;
	}
	
	return decrypted_length + padded_length;
#endif

#ifdef WI_CIPHER_COMMONCRYPTO
	CCCryptorStatus		status;
	size_t				available_length, decrypted_length, padded_length;
	
	available_length = wi_cipher_block_size(cipher) + encrypted_length;
	
	status = CCCryptorUpdate(cipher->decrypt_ref,
							 encrypted_buffer,
							 encrypted_length,
							 decrypted_buffer,
							 available_length,
							 &decrypted_length);
	
	if(status != kCCSuccess) {
		wi_error_set_commoncrypto_error(status);
		
		return -1;
	}

	status = CCCryptorFinal(cipher->decrypt_ref,
							decrypted_buffer + decrypted_length,
							available_length - decrypted_length,
							&padded_length);
	
	if(status != kCCSuccess) {
		wi_error_set_commoncrypto_error(status);
		
		return -1;
	}
	
	status = CCCryptorReset(cipher->decrypt_ref, cipher->iv ? wi_data_bytes(cipher->iv) : NULL);
	
	if(status != kCCSuccess) {
		wi_error_set_commoncrypto_error(status);
		
		return -1;
	}
	
	return decrypted_length + padded_length;
#endif
}
コード例 #27
0
int Crypto::CipherUpdate(Cipher c, const StringPiece &in, char *out, int outlen) {
  size_t wrote = 0;
  if (CCCryptorUpdate(FromVoid<CCCipher*>(c)->ctx, in.data(), in.size(), out, outlen, &wrote) != kCCSuccess) return -1;
  return wrote;
}
コード例 #28
0
U8_EXPORT ssize_t u8_cryptic
(int do_encrypt,const char *cname,
 const unsigned char *key,int keylen,
 const unsigned char *iv,int ivlen,
 u8_block_reader reader,u8_block_writer writer,
 void *readstate,void *writestate,
 u8_context caller)
{
  if (strncasecmp(cname,"rsa",3)==0) {
    u8_seterr(_("RSA support NYI"),"u8_cryptic/CommonCrypto",u8_strdup(cname));
    return -1;}
  else {
    CCCryptorRef ctx;
    CCOptions options=0;
    ssize_t inlen, outlen, totalin=0, totalout=0, retval=0;
    unsigned char inbuf[1024], outbuf[1024];
    struct U8_CCCIPHER *cipher=get_cipher(cname);
    if (cipher) {
      size_t blocksize=cipher->cc_blocksize;
      ssize_t needivlen=cipher->cc_ivlen;
      if (!((keylen<=cipher->cc_keymax)&&(keylen>=cipher->cc_keymin)))
	return u8_reterr(u8_BadCryptoKey,
			 ((caller)?(caller):((u8_context)"u8_cryptic")),
			 u8_mkstring("%d!=[%d,%d](%s)",keylen,
				     cipher->cc_keymin,cipher->cc_keymax,
				     cname));
      if ((needivlen)&&(ivlen!=needivlen))
	return u8_reterr(u8_BadCryptoIV,
			 ((caller)?(caller):(COMMONCRYPTO_CRYPTIC)),
			 u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname));

      if (needivlen==0) iv=NULL;

      memset(&ctx,0,sizeof(ctx));

      CCCryptorStatus status=CCCryptorCreate
	(((do_encrypt)? (kCCEncrypt) : (kCCDecrypt)),
	 cipher->cc_algorithm,cipher->cc_opts,key,keylen,iv,&ctx);

      u8_log(CRYPTO_LOGLEVEL,COMMONCRYPTO_CRYPTIC,
	     " %s cipher=%s, keylen=%d/[%d,%d], ivlen=%d, blocksize=%d\n",
	     ((do_encrypt)?("encrypt"):("decrypt")),
	     cname,keylen,cipher->cc_keymin,cipher->cc_keymax,
	     ivlen,blocksize);

      while (1) {
	inlen = reader(inbuf,blocksize,readstate);
	if (inlen <= 0) {
	  u8_log(CRYPTO_LOGLEVEL,COMMONCRYPTO_CRYPTIC,
		 "Finished %s(%s) with %ld in, %ld out",
		 ((do_encrypt)?("encrypt"):("decrypt")),cname,
		 totalin,totalout);
	  break;}
	if ((status=CCCryptorUpdate(ctx,inbuf,inlen,outbuf,1024,&outlen))
	    !=kCCSuccess) {
	  CCCryptorRelease(ctx);
	  return u8_reterr(u8_InternalCryptoError,
			   ((caller)?(caller):((u8_context)"u8_cryptic")),
			   NULL);}
	else {
	  u8_log(CRYPTO_LOGLEVEL,COMMONCRYPTO_CRYPTIC,
		 "%s(%s) consumed %d/%ld bytes, emitted %d/%ld bytes"
		 " in=<%v>\n out=<%v>",
		 ((do_encrypt)?("encrypt"):("decrypt")),cname,
		 inlen,totalin,outlen,totalout+outlen,
		 inbuf,inlen,outbuf,outlen);
	  writer(outbuf,outlen,writestate);
	  totalout=totalout+outlen;}}

      if ((status=CCCryptorFinal(ctx,outbuf,1024,&outlen))!=kCCSuccess) {
	CCCryptorRelease(ctx);
	return u8_reterr(u8_InternalCryptoError,
			 ((caller)?(caller):((u8_context)"u8_cryptic")),
			 NULL);}
      else {
	writer(outbuf,outlen,writestate);
	u8_log(CRYPTO_LOGLEVEL,COMMONCRYPTO_CRYPTIC,
	       "%s(%s) done after consuming %ld/%ld bytes, emitting %ld/%ld bytes"
	       "\n final out=<%v>",
	       ((do_encrypt)?("encrypt"):("decrypt")),cname,
	       inlen,totalin,outlen,totalout+outlen,
	       outbuf,outlen);
	CCCryptorRelease(ctx);
	totalout=totalout+outlen;
	return totalout;}}
    else return u8_reterr("Unknown cipher",
			  ((caller)?(caller):((u8_context)"u8_cryptic")),
			  u8_strdup(cname));
  }
}