UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
openssl_encrypt.c File Reference
#include "crypto/openssl_encrypt.h"
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include "compat/strings.h"
#include "crypto/crc.h"
#include "crypto/md5.h"
#include "debug.h"
#include "lib_common.h"
#include "utils/color_out.h"
#include "utils/macros.h"
Include dependency graph for openssl_encrypt.c:

Go to the source code of this file.

Classes

struct  openssl_encrypt
 

Macros

#define CHECK(action, errmsg)
 
#define DEFAULT_CIPHER_MODE   MODE_AES128_GCM
 
#define GCM_TAG_LEN   16
 
#define MOD_NAME   "[encrypt] "
 

Functions

const void * get_cipher (enum openssl_mode mode)
 
static enum openssl_mode get_cipher_from_str (char *str)
 
static int openssl_encrypt (struct openssl_encrypt *encryption, char *plaintext, int data_len, char *aad, int aad_len, char *ciphertext)
 
static void openssl_encrypt_destroy (struct openssl_encrypt *s)
 
static int openssl_encrypt_init (struct openssl_encrypt **state, const char *passphrase)
 
static enum openssl_mode openssl_get_cipher (struct openssl_encrypt *encryption)
 
static int openssl_get_overhead (struct openssl_encrypt *s)
 
 REGISTER_MODULE (openssl_encrypt, &functions, LIBRARY_CLASS_UNDEFINED, OPENSSL_ENCRYPT_ABI_VERSION)
 
static void usage (void)
 

Variables

struct { 
 
   const EVP_CIPHER *(*   get_cipher )(void) 
 
   enum openssl_mode   mode 
 
   const char *   name 
 
} ciphers [] 
 
static const struct openssl_encrypt_info functions
 

Detailed Description

Encryption is done on per-packet basis, for every packet, new IV is generated, which is send on the beginning, then length of data (uint32_t), and actual encrypted data with:

  1. 32-bit CRC (encryptied) for non-GCM
  2. GCM tag after encrypted data

Encryption algorithm is set in transmit.cpp, detected on receiver. Required algorightms are currently GCM (default) and CBC.

Definition in file openssl_encrypt.c.

Macro Definition Documentation

◆ CHECK

#define CHECK ( action,
errmsg )
Value:
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)
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MOD_NAME

Definition at line 198 of file openssl_encrypt.c.

Referenced by openssl_encrypt().

◆ DEFAULT_CIPHER_MODE

#define DEFAULT_CIPHER_MODE   MODE_AES128_GCM

Definition at line 84 of file openssl_encrypt.c.

Referenced by openssl_encrypt_init().

◆ GCM_TAG_LEN

#define GCM_TAG_LEN   16

Definition at line 85 of file openssl_encrypt.c.

Referenced by openssl_encrypt(), and openssl_get_overhead().

◆ MOD_NAME

#define MOD_NAME   "[encrypt] "

Definition at line 86 of file openssl_encrypt.c.

Referenced by openssl_encrypt(), and openssl_encrypt_init().

Function Documentation

◆ get_cipher()

const void * get_cipher ( enum openssl_mode mode)

Definition at line 114 of file openssl_encrypt.c.

114 {
115 for (unsigned i = 0; i < sizeof ciphers / sizeof ciphers[0]; ++i) {
116 if (ciphers[i].mode == mode) {
117 return ciphers[i].get_cipher();
118 }
119 }
120 return NULL;
121}
const struct @17 ciphers[]
enum openssl_mode mode

References ciphers, and mode.

◆ get_cipher_from_str()

static enum openssl_mode get_cipher_from_str ( char * str)
static

Definition at line 135 of file openssl_encrypt.c.

136{
137 char *tok = strstr(str, ":cipher=");
138 assert(tok != NULL);
139 char *cipher = strchr(tok, '=') + 1;
140 *tok = '\0';
141 for (unsigned i = 0; i < sizeof ciphers / sizeof ciphers[0]; ++i) {
142 if (strcasecmp(ciphers[i].name, cipher) == 0) {
143 return ciphers[i].mode;
144 }
145 }
146 MSG(ERROR, "Unknown/unsuppoted/not compiled cipher %s!\n", cipher);
147 return MODE_AES128_NONE;
148}
#define MSG(l, fmt,...)
Definition debug.h:96
const char * name
@ MODE_AES128_NONE

References ciphers, MODE_AES128_NONE, MSG, and name.

Referenced by openssl_encrypt_init().

◆ openssl_encrypt()

static int openssl_encrypt ( struct openssl_encrypt * encryption,
char * plaintext,
int data_len,
char * aad,
int aad_len,
char * ciphertext )
static

Definition at line 200 of file openssl_encrypt.c.

202{
203 memcpy(ciphertext, &data_len, sizeof(uint32_t));
204 int total_len = sizeof(uint32_t);
205
206 unsigned char ivec[16];
207 if (RAND_bytes(ivec, 8) < 0) {
208 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot generate random bytes!\n");
209 return 0;
210 }
211 memcpy(ciphertext + total_len, ivec, sizeof ivec);
212 total_len += sizeof ivec;
213
214 CHECK(EVP_CipherInit(encryption->ctx, encryption->cipher, encryption->key_hash, ivec, 1), "Cannot initialize cipher");
215 /* Set IV length if default 12 bytes (96 bits) is not appropriate */
216 CHECK(EVP_CIPHER_CTX_ctrl(encryption->ctx, EVP_CTRL_GCM_SET_IVLEN, sizeof ivec, NULL), "set IV len");
217 int out_len = 0;
218 if (encryption->mode == MODE_AES128_GCM) {
219 if (aad_len > 0) {
220 EVP_EncryptUpdate(encryption->ctx, NULL, &out_len, (unsigned char *) aad, aad_len);
221 }
222 }
223 CHECK(EVP_CipherUpdate(encryption->ctx, (unsigned char *) ciphertext + total_len, &out_len, (unsigned char *) plaintext, data_len), "EVP_CipherUpdate");
224 total_len += out_len;
225 if (encryption->mode != MODE_AES128_GCM) {
226 uint32_t crc = crc32buf(aad, aad_len);
227 crc = crc32buf_with_oldcrc(plaintext, data_len, crc);
228 CHECK(EVP_CipherUpdate(encryption->ctx, (unsigned char *) ciphertext + total_len, &out_len, (unsigned char *) &crc, sizeof crc), "EVP_CipherUpdate CRC");
229 total_len += out_len;
230 }
231 CHECK(EVP_CipherFinal(encryption->ctx, (unsigned char *) ciphertext + total_len, &out_len), "EVP_CipherFinal");
232 total_len += out_len;
233 if (encryption->mode == MODE_AES128_GCM) {
234 CHECK(EVP_CIPHER_CTX_ctrl(encryption->ctx, EVP_CTRL_GCM_GET_TAG, GCM_TAG_LEN, ciphertext + total_len), "GCM get tag");
235 total_len += GCM_TAG_LEN;
236 }
237
238 return total_len;
239}
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
#define GCM_TAG_LEN
#define CHECK(action, errmsg)
@ MODE_AES128_GCM
const EVP_CIPHER * cipher
enum openssl_mode mode
EVP_CIPHER_CTX * ctx
unsigned char key_hash[16]

References CHECK, openssl_encrypt::cipher, crc32buf(), crc32buf_with_oldcrc(), openssl_encrypt::ctx, GCM_TAG_LEN, openssl_encrypt::key_hash, LOG_LEVEL_ERROR, log_msg(), MOD_NAME, openssl_encrypt::mode, and MODE_AES128_GCM.

Here is the call graph for this function:

◆ openssl_encrypt_destroy()

static void openssl_encrypt_destroy ( struct openssl_encrypt * s)
static

Definition at line 192 of file openssl_encrypt.c.

193{
194 EVP_CIPHER_CTX_free(s->ctx);
195 free(s);
196}

References openssl_encrypt::ctx.

◆ openssl_encrypt_init()

static int openssl_encrypt_init ( struct openssl_encrypt ** state,
const char * passphrase )
static

Definition at line 151 of file openssl_encrypt.c.

152{
154
155 struct openssl_encrypt *s = (struct openssl_encrypt *)
156 calloc(1, sizeof(struct openssl_encrypt));
157
158 if (strcmp(passphrase, "help") == 0) {
159 usage();
160 return 1;
161 }
162
163 char pass[STR_LEN];
164 snprintf_ch(pass, "%s", passphrase);
165
166 if (strstr(passphrase, ":cipher=")) {
168 }
169
170 MD5CTX context;
171
172 MD5Init(&context);
173 MD5Update(&context, (const unsigned char *) pass,
174 strlen(pass));
175 MD5Final(s->key_hash, &context);
176
177 s->cipher = get_cipher(mode);
178 if (s->cipher == NULL) {
179 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cipher %d not available!\n", (int) mode);
180 free(s);
181 return -1;
182 }
183
184 s->ctx = EVP_CIPHER_CTX_new();
185 s->mode = mode;
186 log_msg(LOG_LEVEL_INFO, MOD_NAME "Encryption set to mode %d\n", (int) mode);
187
188 *state = s;
189 return 0;
190}
void ** state
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#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 enum openssl_mode get_cipher_from_str(char *str)
#define DEFAULT_CIPHER_MODE
static void usage(void)
const EVP_CIPHER *(* get_cipher)(void)
openssl_mode
only GCM provides autenticity, other modes only check integrity (CRC)
Definition md5.h:34

References openssl_encrypt::cipher, openssl_encrypt::ctx, DEFAULT_CIPHER_MODE, get_cipher, get_cipher_from_str(), openssl_encrypt::key_hash, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, log_msg(), MD5Final(), MD5Init(), MD5Update(), MOD_NAME, mode, openssl_encrypt::mode, snprintf_ch, state, STR_LEN, and usage().

Here is the call graph for this function:

◆ openssl_get_cipher()

static enum openssl_mode openssl_get_cipher ( struct openssl_encrypt * encryption)
static

Definition at line 249 of file openssl_encrypt.c.

250{
251 return encryption->mode;
252}

References openssl_encrypt::mode.

◆ openssl_get_overhead()

static int openssl_get_overhead ( struct openssl_encrypt * s)
static

Definition at line 241 of file openssl_encrypt.c.

242{
243 return sizeof(uint32_t) /* data_len */ +
244 16 /* nonce + counter */ + (s->mode == MODE_AES128_GCM ? GCM_TAG_LEN : sizeof(uint32_t) /* crc */)
245 + (s->mode == MODE_AES128_ECB ? 15 : 0 /* padding */);
246}
@ MODE_AES128_ECB

References GCM_TAG_LEN, openssl_encrypt::mode, MODE_AES128_ECB, and MODE_AES128_GCM.

◆ REGISTER_MODULE()

◆ usage()

static void usage ( void )
static

Definition at line 124 of file openssl_encrypt.c.

125{
126 color_printf("Usage:\n");
127 color_printf("\t" TBOLD("-e <passphrase>[:cipher=<c>]") "\n");
128 color_printf("\nAvailable ciphers:\n");
129 for (unsigned i = 0; i < sizeof ciphers / sizeof ciphers[0]; ++i) {
130 color_printf("\t- " TBOLD("%s") "\n", ciphers[i].name);
131 }
132}
int color_printf(const char *format,...)
#define TBOLD(x)
Definition color_out.h:70

References ciphers, color_printf(), name, and TBOLD.

Referenced by openssl_encrypt_init().

Here is the call graph for this function:

Variable Documentation

◆ [struct]

const struct { ... } ciphers[]
Initial value:
= {
{ MODE_AES128_CBC, "cbc", EVP_aes_128_cbc },
{ MODE_AES128_GCM, "gcm", EVP_aes_128_gcm },
}
@ MODE_AES128_CBC

Referenced by get_cipher(), get_cipher_from_str(), and usage().

◆ functions

const struct openssl_encrypt_info functions
static
Initial value:
= {
}
static int openssl_encrypt_init(struct openssl_encrypt **state, const char *passphrase)
static enum openssl_mode openssl_get_cipher(struct openssl_encrypt *encryption)
static int openssl_encrypt(struct openssl_encrypt *encryption, char *plaintext, int data_len, char *aad, int aad_len, char *ciphertext)
static int openssl_get_overhead(struct openssl_encrypt *s)
static void openssl_encrypt_destroy(struct openssl_encrypt *s)

Definition at line 254 of file openssl_encrypt.c.

◆ get_cipher

const EVP_CIPHER *(* get_cipher) (void) ( void )

Definition at line 98 of file openssl_encrypt.c.

Referenced by openssl_decrypt(), and openssl_encrypt_init().

◆ mode

◆ name

const char* name

Definition at line 97 of file openssl_encrypt.c.

Referenced by get_cipher_from_str(), and usage().