UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
openssl_decrypt.c
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2013-2024 CESNET
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
39
40#include <assert.h> // for assert
41#include <stdint.h> // for uint32_t
42#include <stdlib.h> // for calloc, free
43#include <string.h> // for NULL, memcpy, size_t, strstr
44
45#ifdef HAVE_CONFIG_H
46#include "config.h"
47#endif // HAVE_CONFIG_H
48
49#ifdef HAVE_WOLFSSL
50#define OPENSSL_EXTRA
51#define WC_NO_HARDEN
52#include <wolfssl/options.h>
53#include <wolfssl/openssl/aes.h>
54#include <wolfssl/openssl/err.h>
55#include <wolfssl/openssl/evp.h>
56#else
57#include <openssl/aes.h>
58#include <openssl/err.h>
59#include <openssl/evp.h>
60#endif
61
62#include "crypto/crc.h"
63#include "crypto/md5.h"
64#include "crypto/openssl_encrypt.h" // get_cipher
65#include "debug.h"
66#include "lib_common.h"
67#include "utils/macros.h" // for STR_LEN, snprintf_ch
68
69#define GCM_TAG_LEN 16
70#define MOD_NAME "[decrypt] "
71
73 EVP_CIPHER_CTX *ctx;
74 unsigned char key_hash[16];
75
76 unsigned char ivec[AES_BLOCK_SIZE];
77 unsigned char ecount[AES_BLOCK_SIZE];
78 unsigned int num;
79};
80
82 const char *passphrase)
83{
84 struct openssl_decrypt *s =
85 calloc(1, sizeof(struct openssl_decrypt));
86
87 char pass[STR_LEN];
88 snprintf_ch(pass, "%s", passphrase);
89 // used only by encrypt, drop option
90 if (strstr(pass, ":cipher=")) {
91 *strstr(pass, ":cipher=") = '\0';
92 }
93
94 MD5CTX context;
95
96 MD5Init(&context);
97 MD5Update(&context, (const unsigned char *) pass,
98 strlen(pass));
99 MD5Final(s->key_hash, &context);
100
101 s->ctx = EVP_CIPHER_CTX_new();
102 log_msg(LOG_LEVEL_INFO, MOD_NAME "Enabled stream decryption.\n");
103
104 *state = s;
105 return 0;
106}
107
109{
110 if(!s) {
111 return;
112 }
113 EVP_CIPHER_CTX_free(s->ctx);
114 free(s);
115}
116
117#define CHECK(action, errmsg) do { int rc = action; if (rc != 1) { log_msg(LOG_LEVEL_ERROR, MOD_NAME errmsg ": %s\n", ERR_error_string(ERR_get_error(), NULL)); return 0; } } while(0)
118#pragma GCC diagnostic ignored "-Wcast-qual"
119static int openssl_decrypt(struct openssl_decrypt *decrypt,
120 const char *ciphertext, int ciphertext_len,
121 const char *aad, int aad_len,
122 char *plaintext, enum openssl_mode mode)
123{
124 const EVP_CIPHER *cipher = get_cipher(mode);
125 if (cipher == NULL) {
126 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cipher %d not available!\n", (int) mode);
127 return 0;
128 }
129 uint32_t data_len;
130 memcpy(&data_len, ciphertext, sizeof(uint32_t));
131 assert ((size_t) ciphertext_len >= data_len + sizeof(uint32_t) + 16 + sizeof(uint32_t));
132 ciphertext += sizeof(uint32_t);
133 const unsigned char *iv = (const unsigned char *) ciphertext;
134 ciphertext += 16;
135 ciphertext_len -= 20;
136
137 CHECK(EVP_CipherInit(decrypt->ctx, cipher, decrypt->key_hash, iv, 0), "Unable to initialize cipher");
138 CHECK(EVP_CIPHER_CTX_ctrl(decrypt->ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL), "set IV len"); // default IV len is presumably 12 bytes
139
140 int out_len = 0;
141 if (mode == MODE_AES128_GCM) {
142 ciphertext_len -= GCM_TAG_LEN;
143 if (aad && aad_len > 0) {
144 if (!EVP_DecryptUpdate(decrypt->ctx, NULL, &out_len, (void *) aad, aad_len)) {
145 log_msg(LOG_LEVEL_ERROR, MOD_NAME "AAD processing: %s\n", ERR_error_string(ERR_get_error(), NULL));
146 }
147 }
148 }
149 CHECK(EVP_CipherUpdate(decrypt->ctx, (unsigned char *) plaintext, &out_len, (const unsigned char *) ciphertext, ciphertext_len), "EVP_CipherUpdate");
150 int total_len = out_len;
151 if (mode == MODE_AES128_GCM) {
152 CHECK(EVP_CIPHER_CTX_ctrl(decrypt->ctx, EVP_CTRL_GCM_SET_TAG, GCM_TAG_LEN, (void *) (ciphertext + ciphertext_len)), "GCM set tag");
153 }
154 CHECK(EVP_CipherFinal(decrypt->ctx, (unsigned char *) plaintext + out_len, &out_len), "EVP_CipherFinal");
155 total_len += out_len;
156
157 if (mode != MODE_AES128_GCM) {
158 uint32_t expected_crc = 0;
159 assert((size_t) total_len >= data_len + sizeof expected_crc);
160 memcpy(&expected_crc, plaintext + data_len, sizeof expected_crc);
161 uint32_t crc = crc32buf(aad, aad_len);
162 crc = crc32buf_with_oldcrc(plaintext, data_len, crc);
163 if (crc != expected_crc) {
164 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Warning: Packet dropped AES - wrong CRC!\n");
165 return 0;
166 }
167 }
168
169 return data_len;
170}
171
177
179
void ** state
uint32_t crc32buf(const char *buf, size_t len)
Definition crc_32.c:176
uint32_t crc32buf_with_oldcrc(const char *buf, size_t len, uint32_t oldcrc)
Definition crc_32.c:162
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
@ LIBRARY_CLASS_UNDEFINED
Definition lib_common.h:74
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
#define snprintf_ch(str,...)
shortcut for snprintf(var, sizeof var...), var must be a char array
Definition macros.h:101
@ STR_LEN
"standard" string length placeholder
Definition macros.h:134
void MD5Update(MD5CTX *context, const unsigned char *input, unsigned int inputLen)
Definition md5.c:249
void MD5Final(unsigned char digest[16], MD5CTX *context)
Definition md5.c:295
void MD5Init(MD5CTX *context)
Definition md5.c:229
static int openssl_decrypt(struct openssl_decrypt *decrypt, const char *ciphertext, int ciphertext_len, const char *aad, int aad_len, char *plaintext, enum openssl_mode mode)
static int openssl_decrypt_init(struct openssl_decrypt **state, const char *passphrase)
#define GCM_TAG_LEN
static const struct openssl_decrypt_info functions
#define MOD_NAME
static void openssl_decrypt_destroy(struct openssl_decrypt *s)
#define CHECK(action, errmsg)
#define OPENSSL_DECRYPT_ABI_VERSION
enum openssl_mode mode
const EVP_CIPHER *(* get_cipher)(void)
openssl_mode
only GCM provides autenticity, other modes only check integrity (CRC)
@ MODE_AES128_GCM
Definition md5.h:34
unsigned char ecount[AES_BLOCK_SIZE]
unsigned int num
EVP_CIPHER_CTX * ctx
unsigned char ivec[AES_BLOCK_SIZE]
unsigned char key_hash[16]