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
......@@ -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
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment