int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen) { int ret = 0; if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; *olen = 0; if( POLARSSL_MODE_CFB == ctx->cipher_info->mode || POLARSSL_MODE_CTR == ctx->cipher_info->mode || POLARSSL_MODE_NULL == ctx->cipher_info->mode ) { return 0; } if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) { if( POLARSSL_ENCRYPT == ctx->operation ) { add_pkcs_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ), ctx->unprocessed_len ); } else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len ) { /* For decrypt operations, expect a full block */ return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED; } /* cipher block */ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, cipher_get_block_size( ctx ), ctx->iv, ctx->unprocessed_data, output ) ) ) { return ret; } /* Set output size for decryption */ if( POLARSSL_DECRYPT == ctx->operation ) return get_pkcs_padding( output, cipher_get_block_size( ctx ), olen ); /* Set output size for encryption */ *olen = cipher_get_block_size( ctx ); return 0; } return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; }
result_t Cipher::process(const operation_t operation, Buffer_base *data, obj_ptr<Buffer_base> &retVal) { int ret; ret = cipher_setkey(&m_ctx, (unsigned char *)m_key.c_str(), (int)m_key.length() * 8, operation); if (ret != 0) return _ssl::setError(ret); ret = cipher_reset(&m_ctx); if (ret != 0) return _ssl::setError(ret); std::string input; std::string output; unsigned char buffer[1024]; size_t olen, ilen, offset, block_size, data_size; data->toString(input); block_size = cipher_get_block_size(&m_ctx); data_size = input.length(); for (offset = 0; offset < data_size; offset += block_size) { ilen = ((unsigned int)data_size - offset > block_size) ? block_size : (unsigned int)(data_size - offset); ret = cipher_update(&m_ctx, (unsigned char *)input.c_str() + offset, ilen, buffer, &olen); if (ret != 0) { reset(); return _ssl::setError(ret); } output.append((const char *)buffer, olen); } ret = cipher_finish(&m_ctx, buffer, &olen); reset(); if (ret != 0) return _ssl::setError(ret); output.append((const char *)buffer, olen); retVal = new Buffer(output); return 0; }
int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen ) { if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); *olen = 0; if( POLARSSL_MODE_CFB == ctx->cipher_info->mode || POLARSSL_MODE_CTR == ctx->cipher_info->mode || POLARSSL_MODE_GCM == ctx->cipher_info->mode || POLARSSL_MODE_STREAM == ctx->cipher_info->mode ) { return( 0 ); } if( POLARSSL_MODE_ECB == ctx->cipher_info->mode ) { if( ctx->unprocessed_len != 0 ) return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); return( 0 ); } #if defined(POLARSSL_CIPHER_MODE_CBC) if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) { int ret = 0; if( POLARSSL_ENCRYPT == ctx->operation ) { /* check for 'no padding' mode */ if( NULL == ctx->add_padding ) { if( 0 != ctx->unprocessed_len ) return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); return( 0 ); } ctx->add_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ), ctx->unprocessed_len ); } else if( cipher_get_block_size( ctx ) != ctx->unprocessed_len ) { /* * For decrypt operations, expect a full block, * or an empty block if no padding */ if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) return( 0 ); return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); } /* cipher block */ if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, cipher_get_block_size( ctx ), ctx->iv, ctx->unprocessed_data, output ) ) ) { return( ret ); } /* Set output size for decryption */ if( POLARSSL_DECRYPT == ctx->operation ) return ctx->get_padding( output, cipher_get_block_size( ctx ), olen ); /* Set output size for encryption */ *olen = cipher_get_block_size( ctx ); return( 0 ); } #else ((void) output); #endif /* POLARSSL_CIPHER_MODE_CBC */ return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); }
int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ) { int ret; if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) { return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); } *olen = 0; if( ctx->cipher_info->mode == POLARSSL_MODE_ECB ) { if( ilen != cipher_get_block_size( ctx ) ) return( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED ); *olen = ilen; if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, ctx->operation, input, output ) ) ) { return( ret ); } return( 0 ); } #if defined(POLARSSL_GCM_C) if( ctx->cipher_info->mode == POLARSSL_MODE_GCM ) { *olen = ilen; return gcm_update( (gcm_context *) ctx->cipher_ctx, ilen, input, output ); } #endif if( input == output && ( ctx->unprocessed_len != 0 || ilen % cipher_get_block_size( ctx ) ) ) { return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); } #if defined(POLARSSL_CIPHER_MODE_CBC) if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ) { size_t copy_len = 0; /* * If there is not enough data for a full block, cache it. */ if( ( ctx->operation == POLARSSL_DECRYPT && ilen <= cipher_get_block_size( ctx ) - ctx->unprocessed_len ) || ( ctx->operation == POLARSSL_ENCRYPT && ilen < cipher_get_block_size( ctx ) - ctx->unprocessed_len ) ) { memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, ilen ); ctx->unprocessed_len += ilen; return( 0 ); } /* * Process cached data first */ if( ctx->unprocessed_len != 0 ) { copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len; memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, copy_len ); if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, cipher_get_block_size( ctx ), ctx->iv, ctx->unprocessed_data, output ) ) ) { return( ret ); } *olen += cipher_get_block_size( ctx ); output += cipher_get_block_size( ctx ); ctx->unprocessed_len = 0; input += copy_len; ilen -= copy_len; } /* * Cache final, incomplete block */ if( 0 != ilen ) { copy_len = ilen % cipher_get_block_size( ctx ); if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT ) copy_len = cipher_get_block_size( ctx ); memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), copy_len ); ctx->unprocessed_len += copy_len; ilen -= copy_len; } /* * Process remaining full blocks */ if( ilen ) { if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output ) ) ) { return( ret ); } *olen += ilen; } return( 0 ); } #endif /* POLARSSL_CIPHER_MODE_CBC */ #if defined(POLARSSL_CIPHER_MODE_CFB) if( ctx->cipher_info->mode == POLARSSL_MODE_CFB ) { if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) { return( ret ); } *olen = ilen; return( 0 ); } #endif /* POLARSSL_CIPHER_MODE_CFB */ #if defined(POLARSSL_CIPHER_MODE_CTR) if( ctx->cipher_info->mode == POLARSSL_MODE_CTR ) { if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, ilen, &ctx->unprocessed_len, ctx->iv, ctx->unprocessed_data, input, output ) ) ) { return( ret ); } *olen = ilen; return( 0 ); } #endif /* POLARSSL_CIPHER_MODE_CTR */ #if defined(POLARSSL_CIPHER_MODE_STREAM) if( ctx->cipher_info->mode == POLARSSL_MODE_STREAM ) { if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, ilen, input, output ) ) ) { return( ret ); } *olen = ilen; return( 0 ); } #endif /* POLARSSL_CIPHER_MODE_STREAM */ return( POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE ); }
int cipher_ctx_block_size(const cipher_context_t *ctx) { return cipher_get_block_size(ctx); }
int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ) { int ret; size_t copy_len = 0; if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen || input == output ) { return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; } *olen = 0; #if defined(POLARSSL_CIPHER_NULL_CIPHER) if( ctx->cipher_info->mode == POLARSSL_MODE_NULL ) { memcpy( output, input, ilen ); *olen = ilen; return 0; } #endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ) { /* * If there is not enough data for a full block, cache it. */ if( ( ctx->operation == POLARSSL_DECRYPT && ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) || ( ctx->operation == POLARSSL_ENCRYPT && ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) ) { memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, ilen ); ctx->unprocessed_len += ilen; return 0; } /* * Process cached data first */ if( ctx->unprocessed_len != 0 ) { copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len; memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, copy_len ); if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, cipher_get_block_size( ctx ), ctx->iv, ctx->unprocessed_data, output ) ) ) { return ret; } *olen += cipher_get_block_size( ctx ); output += cipher_get_block_size( ctx ); ctx->unprocessed_len = 0; input += copy_len; ilen -= copy_len; } /* * Cache final, incomplete block */ if( 0 != ilen ) { copy_len = ilen % cipher_get_block_size( ctx ); if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT ) copy_len = cipher_get_block_size(ctx); memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), copy_len ); ctx->unprocessed_len += copy_len; ilen -= copy_len; } /* * Process remaining full blocks */ if( ilen ) { if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output ) ) ) { return ret; } *olen += ilen; } return 0; } if( ctx->cipher_info->mode == POLARSSL_MODE_CFB ) { if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) { return ret; } *olen = ilen; return 0; } if( ctx->cipher_info->mode == POLARSSL_MODE_CTR ) { if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, ilen, &ctx->unprocessed_len, ctx->iv, ctx->unprocessed_data, input, output ) ) ) { return ret; } *olen = ilen; return 0; } return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; }
result_t Cipher::get_blockSize(int32_t &retVal) { retVal = cipher_get_block_size(&m_ctx); return 0; }