Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Jean-Baptiste Kempf
libaacs
Commits
fdfc19aa
Commit
fdfc19aa
authored
Oct 21, 2013
by
npzacs
Browse files
Calculate processing key using device keys
parent
21652191
Changes
6
Hide whitespace changes
Inline
Side-by-side
KEYDB.cfg
View file @
fdfc19aa
...
...
@@ -38,14 +38,17 @@
;
; Device Key entry
; ----------------
; | DK | DEVICE_KEY <HEXSTRING> | DEVICE_NODE <HEXSTRING>
; | DK | DEVICE_KEY <HEXSTRING> \
; | DEVICE_NODE <HEXSTRING> \
; | KEY_UV <HEXSTRING> \
; | KEY_U_MASK_SHIFT <HEXSTRING>
;
; The device key entry begins with the entry ID "| DK |". Within a device key
; entry are
two
hexadecimal strings. The first hexadecimal string is preceded by
; entry are
four
hexadecimal strings. The first hexadecimal string is preceded by
; the keyword "DEVICE_KEY" and is the hexadecimal string representing the device
; key. The second hexadecimal string is preceded by the keyword "DEVICE_NODE"
; and is the hexadecimal string representing the device node number. Each of
;
two
entries is delimited by a vertical bar '|'. Each device key entry must end
;
four
entries is delimited by a vertical bar '|'. Each device key entry must end
; with a newline.
;
; Note that each of these entries must end with at least one new line, as
...
...
@@ -153,7 +156,9 @@
; foo's device key
| DK | DEVICE_KEY 0x00000000000000000000000000000000 \
| DEVICE_NODE 0x0
| DEVICE_NODE 0x0 \
| KEY_UV 0x00000000 \
| KEY_U_MASK 0x00
; bar's device key
| DK | DEVICE_KEY 0x00000000000000000000000000000000 \
...
...
src/file/keydbcfg-lexer.l
View file @
fdfc19aa
...
...
@@ -59,6 +59,8 @@ DIGIT ([0-9]+)
KEYWORD_DEVICE_KEY ([Dd][Ee][Vv][Ii][Cc][Ee]_[Kk][Ee][Yy])
KEYWORD_DEVICE_NODE ([Dd][Ee][Vv][Ii][Cc][Ee]_[Nn][Oo][Dd][Ee])
KEYWORD_KEY_UV ([Kk][Ee][Yy]_[Uu][Vv])
KEYWORD_KEY_U_MASK_SHIFT ([Kk][Ee][Yy]_[Uu]_[Mm][Aa][Ss][Kk]_[Ss][Hh][Ii][Ff][Tt])
KEYWORD_HOST_PRIV_KEY ([Hh][Oo][Ss][Tt]_[Pp][Rr][Ii][Vv]_[Kk][Ee][Yy][ \t]+)
KEYWORD_HOST_CERT ([Hh][Oo][Ss][Tt]_[Cc][Ee][Rr][Tt][ \t]+)
KEYWORD_HOST_NONCE ([Hh][Oo][Ss][Tt]_[Nn][Oo][Nn][Cc][Ee][ \t]+)
...
...
@@ -112,6 +114,8 @@ BAD_ENTRY ([^\n])
{KEYWORD_DEVICE_KEY} { return KEYWORD_DEVICE_KEY; }
{KEYWORD_DEVICE_NODE} { return KEYWORD_DEVICE_NODE; }
{KEYWORD_KEY_UV} { return KEYWORD_KEY_UV; }
{KEYWORD_KEY_U_MASK_SHIFT} { return KEYWORD_KEY_U_MASK_SHIFT; }
{KEYWORD_HOST_PRIV_KEY} { return KEYWORD_HOST_PRIV_KEY; }
{KEYWORD_HOST_CERT} { return KEYWORD_HOST_CERT; }
{KEYWORD_HOST_NONCE} { return KEYWORD_HOST_NONCE; }
...
...
src/file/keydbcfg-parser.y
View file @
fdfc19aa
...
...
@@ -69,7 +69,7 @@ static dk_list *new_dk_list(void);
static pk_list *new_pk_list(void);
static cert_list *new_cert_list(void);
static void add_dk_entry(config_file *cf, char *key, char *node);
static void add_dk_entry(config_file *cf, char *key, char *node
, char *uv, char *u_mask_shift
);
static void add_pk_entry(config_file *cf, char *key);
static void add_cert_entry(config_file *cf, char *host_priv_key, char *host_cert);
...
...
@@ -114,6 +114,8 @@ extern int libaacs_yyget_lineno (void *scanner);
%token KEYWORD_DEVICE_KEY
%token KEYWORD_DEVICE_NODE
%token KEYWORD_KEY_UV
%token KEYWORD_KEY_U_MASK_SHIFT
%token KEYWORD_HOST_PRIV_KEY
%token KEYWORD_HOST_CERT
%token KEYWORD_HOST_NONCE
...
...
@@ -140,7 +142,7 @@ extern int libaacs_yyget_lineno (void *scanner);
%type <string> discid disc_title
%type <string> host_priv_key host_cert host_nonce host_key_point hexstring_list
%type <string> device_key device_node
%type <string> device_key device_node
key_uv key_u_mask_shift
%%
config_file
: config_entry_list newline_list
...
...
@@ -168,13 +170,21 @@ config_entry
;
dk_entry
: newline_list ENTRY_ID_DK device_key PUNCT_VERTICAL_BAR device_node NEWLINE
: newline_list ENTRY_ID_DK device_key PUNCT_VERTICAL_BAR device_node
PUNCT_VERTICAL_BAR key_uv PUNCT_VERTICAL_BAR key_u_mask_shift
NEWLINE
{
add_dk_entry(cf, $3, $5);
add_dk_entry(cf, $3, $5, $7, $9);
}
| newline_list ENTRY_ID_DK device_key PUNCT_VERTICAL_BAR device_node NEWLINE
{
add_dk_entry(cf, $3, $5, NULL, NULL);
}
| ENTRY_ID_DK device_key PUNCT_VERTICAL_BAR device_node PUNCT_VERTICAL_BAR key_uv PUNCT_VERTICAL_BAR key_u_mask_shift NEWLINE
{
add_dk_entry(cf, $2, $4, $6, $8);
}
| ENTRY_ID_DK device_key PUNCT_VERTICAL_BAR device_node NEWLINE
{
add_dk_entry(cf, $2, $4);
add_dk_entry(cf, $2, $4
, NULL, NULL
);
}
;
...
...
@@ -188,6 +198,16 @@ device_node
{ $$ = $2; }
;
key_uv
: KEYWORD_KEY_UV hexstring_list
{ $$ = $2; }
;
key_u_mask_shift
: KEYWORD_KEY_U_MASK_SHIFT hexstring_list
{ $$ = $2; }
;
pk_entry
: newline_list ENTRY_ID_PK hexstring_list NEWLINE
{
...
...
@@ -537,7 +557,7 @@ static dk_list *new_dk_list(void)
}
/* Function to add dk to config file */
static void add_dk_entry(config_file *cf, char *key, char *node)
static void add_dk_entry(config_file *cf, char *key, char *node
, char *uv, char *u_mask_shift
)
{
if (strlen(key) != 32) {
fprintf(stderr, "ignoring bad DK entry %s\n", key);
...
...
@@ -558,6 +578,15 @@ static void add_dk_entry(config_file *cf, char *key, char *node)
X_FREE(key);
entry->node = strtoul(node, NULL, 16);
X_FREE(node);
if (uv) {
entry->uv = strtoul(uv, NULL, 16);
X_FREE(uv);
}
if (u_mask_shift) {
entry->u_mask_shift = strtoul(u_mask_shift, NULL, 16);
X_FREE(u_mask_shift);
}
}
/* Function to return new pk_list object */
...
...
src/file/keydbcfg.h
View file @
fdfc19aa
...
...
@@ -56,6 +56,10 @@ struct dk_entry
uint8_t
key
[
16
];
unsigned
long
node
;
dk_list
*
next
;
/* optional, can be calculated */
uint32_t
uv
;
uint8_t
u_mask_shift
;
};
/* pk entry */
...
...
src/libaacs/aacs.c
View file @
fdfc19aa
...
...
@@ -156,11 +156,195 @@ static void _update_drl(MKB *mkb)
}
}
static
int
_calc_mk
(
AACS
*
aacs
,
uint8_t
*
mk
,
pk_list
*
pkl
)
static
uint32_t
_calc_v_mask
(
uint32_t
uv
)
{
uint32_t
v_mask
=
0xffffffff
;
while
(
!
(
uv
&
~
v_mask
))
{
v_mask
<<=
1
;
}
return
v_mask
;
}
static
void
_calc_pk
(
const
uint8_t
*
dk
,
uint8_t
*
pk
,
uint32_t
uv
,
uint32_t
v_mask
,
uint32_t
dev_key_v_mask
)
{
unsigned
char
left_child
[
16
],
right_child
[
16
];
crypto_aesg3
(
dk
,
left_child
,
right_child
,
pk
);
while
(
dev_key_v_mask
!=
v_mask
)
{
int
i
;
for
(
i
=
31
;
i
>=
0
;
i
--
)
{
if
(
!
(
dev_key_v_mask
&
(
1ul
<<
i
)))
{
break
;
}
}
uint8_t
curr_key
[
16
];
if
(
!
(
uv
&
(
1ul
<<
i
)))
{
memcpy
(
curr_key
,
left_child
,
16
);
}
else
{
memcpy
(
curr_key
,
right_child
,
16
);
}
crypto_aesg3
(
curr_key
,
left_child
,
right_child
,
pk
);
dev_key_v_mask
=
((
int
)
dev_key_v_mask
)
>>
1
;
}
char
str
[
40
];
DEBUG
(
DBG_AACS
,
"Processing key: %s
\n
"
,
print_hex
(
str
,
pk
,
16
));
}
static
dk_list
*
_find_dk
(
dk_list
*
dkl
,
uint32_t
*
p_dev_key_v_mask
,
uint32_t
uv
,
uint32_t
u_mask
)
{
uint32_t
device_number
=
dkl
->
node
;
uint32_t
dev_key_uv
,
dev_key_u_mask
,
dev_key_v_mask
;
unsigned
key_idx
=
0
;
for
(;
dkl
;
dkl
=
dkl
->
next
)
{
if
(
device_number
!=
dkl
->
node
)
{
/* wrong device */
continue
;
}
key_idx
++
;
dev_key_uv
=
dkl
->
uv
;
dev_key_u_mask
=
0xffffffff
<<
dkl
->
u_mask_shift
;
dev_key_v_mask
=
_calc_v_mask
(
dev_key_uv
);
if
((
u_mask
==
dev_key_u_mask
)
&&
((
uv
&
dev_key_v_mask
)
==
(
dev_key_uv
&
dev_key_v_mask
)))
{
break
;
}
}
if
(
!
dkl
)
{
DEBUG
(
DBG_AACS
|
DBG_CRIT
,
"could not find applying device key (device 0x%x)
\n
"
,
device_number
);
}
else
{
char
str
[
128
];
DEBUG
(
DBG_AACS
,
"Applying device key is #%d %s
\n
"
,
key_idx
,
print_hex
(
str
,
dkl
->
key
,
16
));
DEBUG
(
DBG_AACS
,
" UV: 0x%08x U mask: 0x%08x V mask: 0x%08x
\n
"
,
dev_key_uv
,
dev_key_u_mask
,
dev_key_v_mask
);
*
p_dev_key_v_mask
=
dev_key_v_mask
;
}
return
dkl
;
}
static
int
_calc_pk_mk
(
MKB
*
mkb
,
dk_list
*
dkl
,
uint8_t
*
mk
)
{
/* calculate processing key and media key using device keys */
const
uint8_t
*
uvs
,
*
cvalues
;
unsigned
num_uvs
;
size_t
len
;
char
str
[
128
];
/* get mkb data */
uvs
=
mkb_subdiff_records
(
mkb
,
&
len
);
cvalues
=
mkb_cvalues
(
mkb
,
&
len
);
num_uvs
=
len
/
5
;
if
(
num_uvs
<
1
)
{
return
AACS_ERROR_CORRUPTED_DISC
;
}
/* loop over all known devices */
dk_list
*
dk_num
;
uint32_t
device_number
=
(
uint32_t
)
-
1
;
for
(
dk_num
=
dkl
;
dk_num
;
dk_num
=
dk_num
->
next
)
{
/* find next device */
if
(
device_number
==
dk_num
->
node
)
{
dk_num
=
dk_num
->
next
;
continue
;
}
device_number
=
dkl
->
node
;
/* find applying subset difference */
unsigned
uvs_idx
;
uint32_t
u_mask
,
v_mask
,
uv
;
for
(
uvs_idx
=
0
;
uvs_idx
<
num_uvs
;
uvs_idx
++
)
{
const
uint8_t
*
p_uv
=
uvs
+
1
+
5
*
uvs_idx
;
uint8_t
u_mask_shift
=
p_uv
[
-
1
];
uv
=
MKINT_BE32
(
p_uv
);
if
(
!
uv
)
{
continue
;
}
if
(
u_mask_shift
&
0xc0
)
{
DEBUG
(
DBG_AACS
|
DBG_CRIT
,
"device 0x%x is revoked
\n
"
,
device_number
);
uvs_idx
=
num_uvs
;
}
else
{
u_mask
=
0xffffffff
<<
u_mask_shift
;
v_mask
=
_calc_v_mask
(
uv
);
if
(((
device_number
&
u_mask
)
==
(
uv
&
u_mask
))
&&
((
device_number
&
v_mask
)
!=
(
uv
&
v_mask
)))
{
break
;
}
}
}
if
(
uvs_idx
>=
num_uvs
)
{
DEBUG
(
DBG_AACS
|
DBG_CRIT
,
"could not find applying subset-difference for device 0x%x
\n
"
,
device_number
);
/* try next device */
continue
;
}
DEBUG
(
DBG_AACS
,
"Applying subset-difference for device 0x%x is #%d:
\n
"
,
device_number
,
uvs_idx
);
DEBUG
(
DBG_AACS
,
" UV: 0x%08x U mask: 0x%08x V mask: 0x%08x
\n
"
,
uv
,
u_mask
,
v_mask
);
/* find applying device key */
uint32_t
dev_key_v_mask
=
0
;
dk_list
*
dk
;
dk
=
_find_dk
(
dk_num
,
&
dev_key_v_mask
,
uv
,
u_mask
);
if
(
!
dk
)
{
/* try next device */
continue
;
}
/* calculate processing key */
uint8_t
pk
[
16
];
_calc_pk
(
dk
->
key
,
pk
,
uv
,
v_mask
,
dev_key_v_mask
);
/* calculate and verify media key */
if
(
_validate_pk
(
pk
,
cvalues
+
uvs_idx
*
16
,
uvs
+
1
+
uvs_idx
*
5
,
mkb_mk_dv
(
mkb
),
mk
)
==
AACS_SUCCESS
)
{
DEBUG
(
DBG_AACS
,
"Media key: %s
\n
"
,
print_hex
(
str
,
mk
,
16
));
return
AACS_SUCCESS
;
}
DEBUG
(
DBG_AACS
|
DBG_CRIT
,
"Processing key %s is invalid!
\n
"
,
print_hex
(
str
,
pk
,
16
));
/* try next device */
}
return
AACS_ERROR_NO_DK
;
}
static
int
_calc_mk
(
AACS
*
aacs
,
uint8_t
*
mk
,
pk_list
*
pkl
,
dk_list
*
dkl
)
{
int
a
,
num_uvs
=
0
;
size_t
len
;
uint8_t
*
buf
=
NULL
;
MKB
*
mkb
=
NULL
;
const
uint8_t
*
rec
,
*
uvs
;
...
...
@@ -172,9 +356,17 @@ static int _calc_mk(AACS *aacs, uint8_t *mk, pk_list *pkl)
DEBUG
(
DBG_AACS
,
"Calculate media key...
\n
"
);
if
((
mkb
=
mkb_open
(
aacs
->
path
)))
{
DEBUG
(
DBG_AACS
,
"Get UVS...
\n
"
);
_update_drl
(
mkb
);
aacs
->
mkb_version
=
mkb_version
(
mkb
);
_update_drl
(
mkb
);
/* try device keys first */
if
(
dkl
&&
_calc_pk_mk
(
mkb
,
dkl
,
mk
)
==
AACS_SUCCESS
)
{
mkb_close
(
mkb
);
return
AACS_SUCCESS
;
}
DEBUG
(
DBG_AACS
,
"Get UVS...
\n
"
);
uvs
=
mkb_subdiff_records
(
mkb
,
&
len
);
rec
=
uvs
;
while
(
rec
<
uvs
+
len
)
{
...
...
@@ -194,7 +386,6 @@ static int _calc_mk(AACS *aacs, uint8_t *mk, pk_list *pkl)
if
(
AACS_SUCCESS
==
_validate_pk
(
pkl
->
key
,
rec
+
a
*
16
,
uvs
+
1
+
a
*
5
,
mkb_mk_dv
(
mkb
),
mk
))
{
mkb_close
(
mkb
);
X_FREE
(
buf
);
char
str
[
40
];
DEBUG
(
DBG_AACS
,
"Media key: %s
\n
"
,
print_hex
(
str
,
mk
,
16
));
...
...
@@ -204,7 +395,6 @@ static int _calc_mk(AACS *aacs, uint8_t *mk, pk_list *pkl)
}
mkb_close
(
mkb
);
X_FREE
(
buf
);
DEBUG
(
DBG_AACS
|
DBG_CRIT
,
"Error calculating media key. Missing right processing key ?
\n
"
);
return
AACS_ERROR_NO_PK
;
...
...
@@ -387,7 +577,7 @@ static int _calc_vuk(AACS *aacs, uint8_t *mk, uint8_t *vuk, config_file *cf)
}
/* make sure we have media key */
error_code
=
_calc_mk
(
aacs
,
mk
,
cf
->
pkl
);
error_code
=
_calc_mk
(
aacs
,
mk
,
cf
->
pkl
,
cf
->
dkl
);
if
(
error_code
!=
AACS_SUCCESS
)
{
return
error_code
;
}
...
...
src/libaacs/aacs.h
View file @
fdfc19aa
...
...
@@ -35,6 +35,7 @@
#define AACS_ERROR_CERT_REVOKED -5
/* certificate has been revoked */
#define AACS_ERROR_MMC_OPEN -6
/* MMC open failed (no MMC drive ?) */
#define AACS_ERROR_MMC_FAILURE -7
/* MMC failed */
#define AACS_ERROR_NO_DK -8
/* no matching device key */
typedef
struct
aacs
AACS
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment