Skip to content
Snippets Groups Projects
Commit bebe12d4 authored by Vittorio Giovara's avatar Vittorio Giovara Committed by Tristan Matthews
Browse files

Rewrite audio srtp key generation and base64 functions internally

Change-Id: I81e4c27599c8e41d79d6d96d35798db0047f2922
Refs: #47142
parent cf8f7b7b
No related branches found
No related tags found
No related merge requests found
......@@ -19,4 +19,5 @@ libaudiortp_la_SOURCES = \
audio_rtp_stream.h \
audio_rtp_factory.h \
audio_symmetric_rtp_session.h \
audio_srtp_session.h
audio_srtp_session.h \
base64.c base64.h
......@@ -30,15 +30,10 @@
#include "audio_srtp_session.h"
#include "logger.h"
#include "array_size.h"
#include "base64.h"
#include <algorithm>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include <random>
#include <cstdio>
#include <cstring>
......@@ -51,53 +46,27 @@
namespace sfl {
namespace {
std::string
encodeBase64(unsigned char *input, int length)
{
// init decoder
BIO *b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
// init internal buffer
BIO *bmem = BIO_new(BIO_s_mem());
// create decoder chain
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
// BIO_flush (b64);
// get pointer to data
BUF_MEM *bptr = 0;
BIO_get_mem_ptr(b64, &bptr);
std::string output(bptr->data, bptr->length);
BIO_free_all(bmem);
std::string encodeBase64(unsigned char *input, int length)
{
size_t output_length;
uint8_t *encoded_str = base64_encode(input, length, &output_length);
if (!encoded_str)
THROW_ERROR(AudioSrtpException, "Out of memory for base64 operation");
std::string output((const char *)encoded_str, output_length);
free(encoded_str);
return output;
}
std::vector<char> decodeBase64(unsigned char *input, int length)
std::string decodeBase64(unsigned char *input, int length)
{
BIO *b64, *bmem;
// init decoder and read-only BIO buffer
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
// init internal buffer
bmem = BIO_new_mem_buf(input, length);
// create encoder chain
bmem = BIO_push(b64, bmem);
std::vector<char> buffer(length, 0);
BIO_read(bmem, buffer.data(), length);
BIO_free_all(bmem);
return buffer;
size_t output_length;
uint8_t *decoded_str = base64_decode(input, length, &output_length);
if (!decoded_str)
THROW_ERROR(AudioSrtpException, "Out of memory for base64 operation");
std::string output((const char *)decoded_str, output_length);
free(decoded_str);
return output;
}
// Fills the array dest with length random bytes
......@@ -105,12 +74,16 @@ void bufferFillMasterKey(std::vector<uint8>& dest)
{
DEBUG("Init local master key");
// Prepare pseudo random generationusing Mersenne Twister
std::mt19937 eng;
std::uniform_int_distribution<uint8_t> dist(0, 255);
// Allocate memory for key
std::vector<unsigned char> random_key(dest.size());
// Generate ryptographically strong pseudo-random bytes
if (RAND_bytes(random_key.data(), dest.size()) != 1)
DEBUG("Error occured while generating cryptographically strong pseudo-random key");
// Fill the key
for (int i = 0; i < dest.size(); i++)
random_key[i] = dist(eng);
std::copy(random_key.begin(), random_key.end(), dest.begin());
}
......@@ -118,14 +91,18 @@ void bufferFillMasterKey(std::vector<uint8>& dest)
// Fills the array dest with length random bytes
void bufferFillMasterSalt(std::vector<uint8>& dest)
{
DEBUG("Init local master key");
DEBUG("Init local master salt");
// Prepare pseudo random generation using Mersenne Twister
std::mt19937 eng;
std::uniform_int_distribution<uint8_t> dist(0, 255);
// Allocate memory for key
std::vector<unsigned char> random_key(dest.size());
// Generate ryptographically strong pseudo-random bytes
if (RAND_bytes(random_key.data(), dest.size()) != 1)
DEBUG("Error occured while generating cryptographically strong pseudo-random key");
// Fill the key
for (int i = 0; i < dest.size(); i++)
random_key[i] = dist(eng);
std::copy(random_key.begin(), random_key.end(), dest.begin());
}
......@@ -276,14 +253,11 @@ void AudioSrtpSession::unBase64ConcatenatedKeys(std::string base64keys)
remoteMasterKey_.resize(sfl::CryptoSuites[remoteCryptoSuite_].masterKeyLength / BITS_PER_BYTE);
remoteMasterSalt_.resize(sfl::CryptoSuites[remoteCryptoSuite_].masterSaltLength / BITS_PER_BYTE);
// pointer to binary data
char *dataptr = (char*) base64keys.data();
// decode concatenated binary keys
std::vector<char> output(decodeBase64((unsigned char*) dataptr, strlen(dataptr)));
std::string output(decodeBase64((uint8_t *)base64keys.data(), base64keys.size()));
// copy master and slt respectively
const std::vector<char>::iterator key_end = output.begin() + remoteMasterKey_.size();
const std::string::iterator key_end = output.begin() + remoteMasterKey_.size();
if (key_end > output.end() or
(size_t) std::distance(key_end, output.end()) > remoteMasterSalt_.size())
......
/*
* Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#include <stdint.h>
#include <stdlib.h>
/* Mainly based on the following stackoverflow question:
* http://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c
*/
static const uint8_t encoding_table[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',
'3', '4', '5', '6', '7', '8', '9', '+', '/'
};
static const int mod_table[] = { 0, 2, 1 };
uint8_t *base64_encode(const uint8_t *data,
size_t input_length, size_t *output_length)
{
int i, j;
uint8_t *encoded_data;
*output_length = 4 * ((input_length + 2) / 3);
encoded_data = (uint8_t *)malloc(*output_length);
if (encoded_data == NULL)
return NULL;
for (i = 0, j = 0; i < input_length; ) {
uint8_t octet_a = i < input_length ? data[i++] : 0;
uint8_t octet_b = i < input_length ? data[i++] : 0;
uint8_t octet_c = i < input_length ? data[i++] : 0;
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
}
for (i = 0; i < mod_table[input_length % 3]; i++)
encoded_data[*output_length - 1 - i] = '=';
return encoded_data;
}
uint8_t *base64_decode(const uint8_t *data,
size_t input_length, size_t *output_length)
{
int i, j;
uint8_t decoding_table[256];
unsigned char *decoded_data;
for (i = 0; i < 64; i++)
decoding_table[(uint8_t) encoding_table[i]] = i;
if (input_length % 4 != 0)
return NULL;
*output_length = input_length / 4 * 3;
if (data[input_length - 1] == '=')
(*output_length)--;
if (data[input_length - 2] == '=')
(*output_length)--;
decoded_data = (unsigned char *)malloc(*output_length);
if (decoded_data == NULL)
return NULL;
for (i = 0, j = 0; i < input_length;) {
uint8_t sextet_a = data[i] == '=' ? 0 & i++
: decoding_table[data[i++]];
uint8_t sextet_b = data[i] == '=' ? 0 & i++
: decoding_table[data[i++]];
uint8_t sextet_c = data[i] == '=' ? 0 & i++
: decoding_table[data[i++]];
uint8_t sextet_d = data[i] == '=' ? 0 & i++
: decoding_table[data[i++]];
uint32_t triple = (sextet_a << 3 * 6) +
(sextet_b << 2 * 6) +
(sextet_c << 1 * 6) +
(sextet_d << 0 * 6);
if (j < *output_length)
decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
if (j < *output_length)
decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
if (j < *output_length)
decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
}
return decoded_data;
}
/*
* Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#ifndef H_BASE64
#define H_BASE64
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
/**
* Encode a buffer in base64.
*
* @param data the input buffer
* @param input_length the input length
* @param output_length the resulting output length
* @return a base64-encoded buffer
*
* @note callers should free the returned memory
*/
uint8_t *base64_encode(const uint8_t *data,
size_t input_length, size_t *output_length);
/**
* Decode a base64 buffer.
*
* @param data the input buffer
* @param input_length the input length
* @param output_length the resulting output length
* @return a buffer
*
* @note callers should free the returned memory
*/
uint8_t *base64_decode(const uint8_t *data,
size_t input_length, size_t *output_length);
#ifdef __cplusplus
}
#endif
#endif // H_BASE64
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment