The current approach reduces some duplication but it'd be easy to refactor it a different way. In fact, this approach might result in less duplication overall (there's a common need for integer pointer + buffer across many of the methods) How about this?

```python
    def update_encrypt_context(self, ctx, data):
        buf, outlen = self._create_buf_out(len(data))
        res = self.lib.EVP_EncryptUpdate(ctx, buf, outlen, data, len(data))
        assert res != 0
        return self.ffi.buffer(buf)[:outlen[0]]

    def update_decrypt_context(self, ctx, data):
        buf, outlen = self._create_buf_out(len(data))
        res = self.lib.EVP_DecryptUpdate(ctx, buf, outlen, data, len(data))
        assert res != 0
        return self.ffi.buffer(buf)[:outlen[0]]

    def _create_buf_out(self, data_len):
        buf = self.ffi.new("unsigned char[]", data_len)
        outlen = self.ffi.new("int *")
        return (buf, outlen)
```