+/* MAGMA encryption in CBC mode */
+int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ unsigned char b[8];
+ unsigned char d[8];
+ const unsigned char *in_ptr = in;
+ unsigned char *out_ptr = out;
+ int i;
+ struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
+ unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
+ if (EVP_CIPHER_CTX_encrypting(ctx)) {
+ while (inl > 0) {
+
+ for (i = 0; i < 8; i++) {
+ b[7 - i] = iv[i] ^ in_ptr[i];
+ }
+ gostcrypt(&(c->cctx), b, d);
+
+ for (i = 0; i < 8; i++) {
+ out_ptr[7 - i] = d[i];
+ }
+ memcpy(iv, out_ptr, 8);
+ out_ptr += 8;
+ in_ptr += 8;
+ inl -= 8;
+ }
+ } else {
+ while (inl > 0) {
+ for (i = 0; i < 8; i++) {
+ d[7 - i] = in_ptr[i];
+ }
+ gostdecrypt(&(c->cctx), d, b);
+ for (i = 0; i < 8; i++) {
+ out_ptr[i] = iv[i] ^ b[7 - i];
+ }
+ memcpy(iv, in_ptr, 8);
+ out_ptr += 8;
+ in_ptr += 8;
+ inl -= 8;
+ }
+ }
+ return 1;
+}
+
+/* increment counter (64-bit int) by 1 */
+static void ctr64_inc(unsigned char *counter)
+{
+ inc_counter(counter, 8);
+}
+
+/* MAGMA encryption in CTR mode */
+static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ const unsigned char *in_ptr = in;
+ unsigned char *out_ptr = out;
+ size_t i = 0;
+ size_t j;
+ struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx);
+ unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
+ unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
+ unsigned char b[8];
+/* Process partial blocks */
+ if (EVP_CIPHER_CTX_num(ctx)) {
+ for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl;
+ j++, i++, in_ptr++, out_ptr++) {
+ *out_ptr = buf[7 - j] ^ (*in_ptr);
+ }
+ if (j == 8) {
+ EVP_CIPHER_CTX_set_num(ctx, 0);
+ } else {
+ EVP_CIPHER_CTX_set_num(ctx, j);
+ return 1;
+ }
+ }
+
+/* Process full blocks */
+ for (; i + 8 <= inl; i += 8, in_ptr += 8, out_ptr += 8) {
+ for (j = 0; j < 8; j++) {
+ b[7 - j] = iv[j];
+ }
+ gostcrypt(&(c->cctx), b, buf);
+ for (j = 0; j < 8; j++) {
+ out_ptr[j] = buf[7 - j] ^ in_ptr[j];
+ }
+ ctr64_inc(iv);
+ }
+
+/* Process the rest of plaintext */
+ if (i < inl) {
+ for (j = 0; j < 8; j++) {
+ b[7 - j] = iv[j];
+ }
+ gostcrypt(&(c->cctx), iv, buf);
+ ctr64_inc(iv);
+ for (j = 0; i < inl; j++, i++) {
+ out_ptr[j] = buf[7 - j] ^ in_ptr[j];
+ }
+
+ EVP_CIPHER_CTX_set_num(ctx, j);
+ } else {
+ EVP_CIPHER_CTX_set_num(ctx, 0);
+ }
+
+ return 1;
+}
+