uencrypt: split common and library-specific code
[openwrt/staging/svanheule.git] / package / utils / uencrypt / src / uencrypt-openssl.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2 * Copyright (C) 2022-2023 Eneas Ulir de Queiroz
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include "uencrypt.h"
10
11 const cipher_t *get_default_cipher(void)
12 {
13 return EVP_aes_128_cbc();
14 }
15
16 #ifndef USE_WOLFSSL
17 static void print_ciphers(const OBJ_NAME *name,void *arg) {
18 fprintf(arg, "\t%s\n", name->name);
19 }
20 #endif
21
22 const cipher_t *get_cipher_or_print_error(char *name)
23 {
24 const EVP_CIPHER *cipher;
25
26 if ((cipher = EVP_get_cipherbyname(name)))
27 return cipher;
28
29 fprintf(stderr, "Error: invalid cipher: %s.\n", name);
30 #ifndef USE_WOLFSSL
31 fprintf(stderr, "Supported ciphers: \n");
32 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, print_ciphers, stderr);
33 #endif
34 return NULL;
35 }
36
37 int get_cipher_ivsize(const cipher_t *cipher)
38 {
39 return EVP_CIPHER_iv_length(cipher);
40 }
41
42 int get_cipher_keysize(const cipher_t *cipher)
43 {
44 return EVP_CIPHER_key_length(cipher);
45 }
46
47 ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key,
48 const unsigned char *iv, int enc, int padding)
49 {
50 EVP_CIPHER_CTX *ctx;
51 int ret;
52
53 ctx = EVP_CIPHER_CTX_new();
54 if (!ctx) {
55 fprintf (stderr, "Error: create_ctx: out of memory.\n");
56 return NULL;
57 }
58 ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
59 if (!ret) {
60 fprintf(stderr, "Error:EVP_CipherInit_ex: %d\n", ret);
61 goto abort;
62 }
63 ret = EVP_CIPHER_CTX_set_padding(ctx, padding);
64 if (!ret) {
65 fprintf(stderr, "Error:EVP_CIPHER_CTX_set_padding: %d\n", ret);
66 goto abort;
67 }
68
69 return ctx;
70
71 abort:
72 free_ctx(ctx);
73 return NULL;
74 }
75
76
77 int do_crypt(FILE *infile, FILE *outfile, ctx_t *ctx)
78 {
79 unsigned char inbuf[CRYPT_BUF_SIZE];
80 unsigned char outbuf[CRYPT_BUF_SIZE + EVP_MAX_BLOCK_LENGTH];
81 int inlen, outlen;
82 int ret;
83
84 for (;;) {
85 inlen = fread(inbuf, 1, CRYPT_BUF_SIZE, infile);
86 if (inlen <= 0)
87 break;
88 ret = EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen);
89 if (!ret) {
90 fprintf(stderr, "Error: EVP_CipherUpdate: %d\n", ret);
91 return ret;
92 }
93 ret = fwrite(outbuf, 1, outlen, outfile);
94 if (ret != outlen) {
95 fprintf(stderr, "Error: CipherUpdate short write.\n");
96 return ret - outlen;
97 }
98 }
99 ret = EVP_CipherFinal_ex(ctx, outbuf, &outlen);
100 if (!ret) {
101 fprintf(stderr, "Error: EVP_CipherFinal: %d\n", ret);
102 return ret;
103 }
104 ret = fwrite(outbuf, 1, outlen, outfile);
105 if (ret != outlen) {
106 fprintf(stderr, "Error: CipherFinal short write.\n");
107 return ret - outlen;
108 }
109
110 return 0;
111 }
112
113 void free_ctx(ctx_t *ctx)
114 {
115 EVP_CIPHER_CTX_free(ctx);
116 }