Skip to content

Commit

Permalink
added CLI encryption with contribution from Lars G.
Browse files Browse the repository at this point in the history
  • Loading branch information
Terrence Meiczinger committed Jun 7, 2014
1 parent 2834650 commit 1e549a9
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 4 deletions.
39 changes: 38 additions & 1 deletion cli/opendcp_mxf_cmd.c
Expand Up @@ -56,6 +56,8 @@ void dcp_usage() {
fprintf(fp, " -d | --end <frame> - end frame\n");
fprintf(fp, " -p | --slideshow <duration> - create slideshow with each image having duration specified (in seconds)\n");
fprintf(fp, " -l | --log_level <level> - Sets the log level 0:Quiet, 1:Error, 2:Warn (default), 3:Info, 4:Debug\n");
fprintf(fp, " -k | --key <key> - set encryption key (this enables encryption)\n");
fprintf(fp, " -u | --key_id <key id> - set encryption key id (leaving blank generates a random uuid)\n");
fprintf(fp, " -h | --help - show help\n");
fprintf(fp, " -v | --version - show version\n");
fprintf(fp, "\n\n");
Expand Down Expand Up @@ -166,6 +168,8 @@ int main (int argc, char **argv) {
char *in_path_right = NULL;
char *out_path = NULL;
filelist_t *filelist;
char key_id[40];
int key_id_flag = 0;

if (argc <= 1) {
dcp_usage();
Expand All @@ -184,6 +188,8 @@ int main (int argc, char **argv) {
{
static struct option long_options[] =
{
{"key_id", required_argument, 0, 'u'},
{"key", required_argument, 0, 'k'},
{"help", required_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"left", required_argument, 0, '1'},
Expand All @@ -202,7 +208,7 @@ int main (int argc, char **argv) {
/* getopt_long stores the option index here. */
int option_index = 0;

c = getopt_long (argc, argv, "1:2:d:i:n:o:r:s:p:l:3hv",
c = getopt_long (argc, argv, "1:2:d:i:k:n:o:r:s:p:u:l:3hv",
long_options, &option_index);

/* Detect the end of the options. */
Expand Down Expand Up @@ -305,6 +311,33 @@ int main (int argc, char **argv) {

break;

case 'k':
if (!is_key(optarg)) {
dcp_fatal(opendcp, "Invalid encryption key format");
}

if (hex2bin(optarg, opendcp->mxf.key_value, 16)) {
dcp_fatal(opendcp, "Invalid encryption key format");
}

opendcp->mxf.key_flag = 1;

break;

case 'u':
if (!is_uuid(optarg)) {
dcp_fatal(opendcp, "Invalid encryption key id format");
}

strnchrdel(optarg, key_id, sizeof(key_id), '-');

if (hex2bin(key_id, opendcp->mxf.key_id, 16)) {
dcp_fatal(opendcp, "Invalid encryption key format");
}

key_id_flag = 1;
break;

case 'v':
version();
break;
Expand Down Expand Up @@ -361,6 +394,10 @@ int main (int argc, char **argv) {
dcp_fatal(opendcp, "No input files located");
}

if (opendcp->mxf.key_flag && key_id_flag == 0) {
memset(opendcp->mxf.key_id, 0, sizeof(opendcp->mxf.key_id));
}

#ifdef _WIN32

/* check for non-ascii filenames under windows */
Expand Down
10 changes: 9 additions & 1 deletion libopendcp/asdcp_intf.cpp
Expand Up @@ -384,6 +384,14 @@ extern "C" int read_asset_info(asset_t *asset) {
}
}

/* add encrypted info, if applicable */
if (info.EncryptedEssence) {
asset->encrypted = 1;
sprintf(asset->key_id, "%.36s", Kumu::bin2UUIDhex(info.CryptographicKeyID, 16, uuid_buffer, 64));
} else {
asset->encrypted = 0;
}

return OPENDCP_NO_ERROR;
}

Expand Down Expand Up @@ -469,7 +477,7 @@ Result_t fill_writer_info(opendcp_t *opendcp, writer_info_t *writer_info) {
Kumu::GenRandomUUID(writer_info->info.ContextID);
writer_info->info.EncryptedEssence = true;

if (opendcp->mxf.key_id) {
if (is_key_value_set(opendcp->mxf.key_id, sizeof(opendcp->mxf.key_id))) {
memcpy(writer_info->info.CryptographicKeyID, opendcp->mxf.key_id, UUIDlen);
} else {
rng.FillRandom(writer_info->info.CryptographicKeyID, UUIDlen);
Expand Down
9 changes: 8 additions & 1 deletion libopendcp/opendcp.h.cmake
Expand Up @@ -247,6 +247,8 @@ typedef struct {
char aspect_ratio[20];
char digest[40];
char filename[MAX_FILENAME_LENGTH];
int encrypted;
char key_id[40];
} asset_t;

typedef struct {
Expand Down Expand Up @@ -392,8 +394,13 @@ int ensure_sequential(char *files[], int nfiles);
int order_indexed_files(char *files[], int nfiles);
filelist_t *filelist_alloc(int nfiles);
void filelist_free(filelist_t *filelist);
void strnchrdel(const char *src, char *dst, int dst_len, char d);
int strcasefind(const char *s, const char *find);
void opendcp_log_subscribe(opendcp_log_cb_t *cb);
void opendcp_log_subscribe(opendcp_log_cb_t *cb);
int hex2bin(const char* str, byte_t* buf, unsigned int buf_len);
int is_key(const char *s);
int is_uuid(const char *s);
int is_key_value_set(byte_t *key, int len);

/* opendcp context */
opendcp_t *opendcp_create();
Expand Down
98 changes: 97 additions & 1 deletion libopendcp/opendcp_common.c
Expand Up @@ -77,7 +77,7 @@ void dcp_fatal(opendcp_t *opendcp, char *format, ...) {
va_list args;
va_start(args, format);
vsnprintf(msg, sizeof(msg), format, args);
OPENDCP_LOG(LOG_ERROR, msg);
fprintf(stderr, "%s\n", msg);
va_end(args);
opendcp_delete(opendcp);
exit(OPENDCP_ERROR);
Expand All @@ -102,6 +102,80 @@ char *base64(const unsigned char *data, int length) {
}
*/

int htob(int x) {
if (x >= '0' && x <= '9')
return x - '0';

if (x >= 'A' && x <= 'F')
return x - 'A' + 10;

if (x >= 'a' && x <= 'f')
return x - 'a' + 10;

return 0;
}

int hex2bin(const char *str, byte_t *buf, unsigned int buf_len) {
int i, x = 0;

/* nothing to do */
if (str[0] == 0) {
return 0;
}

/* buffer isn't big enough */
if (strlen(str)/2 > buf_len) {
return 1;
}

/* iterate and convert */
for ( i = 0; str[i]; i+=2 ) {
if (!isxdigit(str[i]) || !isxdigit(str[i+1])) {
return 1;
}
buf[x++] = (htob(str[i]) << 4) | htob(str[i+1]);
}

return OPENDCP_NO_ERROR;
}

int is_key_value_set(byte_t *key, int len) {
int i;

for(i = 0; i < len / (int)sizeof(byte_t); i++) {
if (key[i]) {
return 1;
}
}

return 0;
}

int is_uuid(const char *s) {
return is_key(s);
}

int is_key(const char *s) {
int i, len;
char strip[40] = "";

strnchrdel(s, strip, sizeof(strip), '-');

len = strlen(strip);

if (len != 32) {
return 0;
}

for (i = 0; i < len; i++) {
if (isxdigit(strip[i]) == 0) {
return 0;
}
}

return 1;
}

int is_filename_ascii(const char *s) {
int i, len;

Expand All @@ -116,6 +190,27 @@ int is_filename_ascii(const char *s) {
return 1;
}

void strnchrdel(const char *src, char *dst, int dst_len, char d) {
int count = 0;

/* get the number of occurrences */
for (int i = 0; src[i]; i++) {
count = src[i] == d ? count++ : count;
}

/* adjust length to be the smaller of the two */
int len = dst_len > (int)strlen(src) - count ? strlen(src) - count : dst_len;

for (int i = 0; i < len; i++) {
if (src[i] != d) {
*dst++ = src[i];
} else {
len++;
}
}
*dst = '\0';
}

int strcasefind(const char *s, const char *find) {
char c, sc;
size_t len;
Expand Down Expand Up @@ -406,6 +501,7 @@ opendcp_t *opendcp_create() {
sprintf(opendcp->dcp.title, "%.80s", DCP_TITLE);
sprintf(opendcp->dcp.kind, "%.15s", DCP_KIND);
get_timestamp(opendcp->dcp.timestamp);
opendcp->mxf.write_hmac = 1;

/* initialize callbacks */
opendcp->mxf.frame_done.callback = opendcp_callback_null;
Expand Down
3 changes: 3 additions & 0 deletions libopendcp/opendcp_xml.c
Expand Up @@ -121,6 +121,9 @@ int write_cpl_asset(opendcp_t *opendcp, xmlTextWriterPtr xml, asset_t asset) {
xmlTextWriterWriteFormatElement(xml, BAD_CAST "IntrinsicDuration", "%d", asset.intrinsic_duration);
xmlTextWriterWriteFormatElement(xml, BAD_CAST "EntryPoint", "%d", asset.entry_point);
xmlTextWriterWriteFormatElement(xml, BAD_CAST "Duration", "%d", asset.duration);
if ( asset.encrypted ) {
xmlTextWriterWriteFormatElement(xml, BAD_CAST "KeyId", "%s%s", "urn:uuid:", asset.key_id);
}
if ( opendcp->dcp.digest_flag ) {
xmlTextWriterWriteFormatElement(xml, BAD_CAST "Hash", "%s", asset.digest);
}
Expand Down

0 comments on commit 1e549a9

Please sign in to comment.