b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 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 | } |