Skip to content

Commit

Permalink
UPDATE: Expose protected header from imported/created JWE and JWS
Browse files Browse the repository at this point in the history
  • Loading branch information
linuxwolf committed Apr 12, 2016
1 parent 70e5c5a commit 6d1d1be
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 21 deletions.
11 changes: 11 additions & 0 deletions include/cjose/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ cjose_header_t *cjose_header_new(
cjose_err *err);


/**
* Retains an existing header object. Callers must use this method if the
* header will be used past the scope it was created in (e.g., from a
* `cjose_jws_t` object).
*
* \param header[in] the header object to be retained.
* \returns the retained header object
*/
cjose_header_t *cjose_header_retain(
cjose_header_t *header);

/**
* Releases an existing header object. Callers must use this method
* to dispose of header rather than directly free'ing a cjose_header
Expand Down
16 changes: 14 additions & 2 deletions include/cjose/jwe.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ typedef struct _cjose_jwe_int cjose_jwe_t;
* (e.g. (dir), the provided JWK must be symmetric (e.g. oct).
*
* \param jwk [in] the key to use for encrypting the JWE.
* \param header [in] additional header values to include in the JWE header.
* \param protected_header [in] additional header values to include in the JWE header.
* \param plaintext [in] the plaintext to be encrypted in the JWE payload.
* \param plaintext_len [in] the length of the plaintext.
* \param err [out] An optional error object which can be used to get additional
Expand All @@ -54,7 +54,7 @@ typedef struct _cjose_jwe_int cjose_jwe_t;
*/
cjose_jwe_t *cjose_jwe_encrypt(
const cjose_jwk_t *jwk,
cjose_header_t *header,
cjose_header_t *protected_header,
const uint8_t *plaintext,
size_t plaintext_len,
cjose_err *err);
Expand Down Expand Up @@ -115,6 +115,18 @@ uint8_t *cjose_jwe_decrypt(
cjose_err *err);


/**
* Returns the protected header of the JWE object.
*
* **NOTE:** The returned header is still owned by the JWE object. Users must
* call `cjose_header_retain()` if it is expected to be valid after the
* owning `cjose_jwe_t` is released.
*
* \param jwe [in] the JWE object for which the protected header is requested.
* \returns the (parsed) protected header
*/
cjose_header_t *cjose_jwe_get_protected(cjose_jwe_t *jwe);

/**
* Releases the given JWE object.
*
Expand Down
16 changes: 14 additions & 2 deletions include/cjose/jws.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ typedef struct _cjose_jws_int cjose_jws_t;
* and JWK.
*
* \param jwk [in] the key to use for signing the JWS.
* \param header [in] header values to include in the JWS header.
* \param protected_header [in] header values to include in the JWS header.
* \param plaintext [in] the plaintext to be signed as the JWS payload.
* \param plaintext_len [in] the length of the plaintext.
* \param err [out] An optional error object which can be used to get additional
Expand All @@ -47,7 +47,7 @@ typedef struct _cjose_jws_int cjose_jws_t;
*/
cjose_jws_t *cjose_jws_sign(
const cjose_jwk_t *jwk,
cjose_header_t *header,
cjose_header_t *protected_header,
const uint8_t *plaintext,
size_t plaintext_len,
cjose_err *err);
Expand Down Expand Up @@ -128,6 +128,18 @@ bool cjose_jws_get_plaintext(
cjose_err *err);


/**
* Returns the protected header of the JWS payload.
*
* **NOTE:** The returned header is still owned by the JWS object. Users must
* call `cjose_header_retain()` if it is expected to be valid after the
* owning `cjose_jws_t` is released.
*
* \param jws [in] the JWS object for which the protected header is requested.
* \returns the (parsed) protected header
*/
cjose_header_t *cjose_jws_get_protected(cjose_jws_t *jws);

/**
* Releases the given JWS object.
*
Expand Down
10 changes: 10 additions & 0 deletions src/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ cjose_header_t *cjose_header_new(
return retval;
}

////////////////////////////////////////////////////////////////////////////////
cjose_header_t *cjose_header_retain(
cjose_header_t *header)
{
if (NULL != header)
{
header = json_incref(header);
}
return header;
}

////////////////////////////////////////////////////////////////////////////////
void cjose_header_release(
Expand Down
2 changes: 2 additions & 0 deletions src/include/jwe_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ typedef struct _jwe_fntable_int
// JWE object
struct _cjose_jwe_int
{
json_t *hdr; // header JSON object

struct _cjose_jwe_part_int part[5]; // the 5 JWE parts

uint8_t *cek; // content-encryption key
Expand Down
42 changes: 29 additions & 13 deletions src/jwe.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static bool _cjose_jwe_malloc(
{
if (RAND_bytes((unsigned char *)*buffer, bytes) != 1)
{
free(*buffer);
cjose_get_dealloc()(*buffer);
CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
return false;
}
Expand All @@ -98,6 +98,10 @@ static bool _cjose_jwe_build_hdr(
cjose_header_t *header,
cjose_err *err)
{
// save header object as part of the JWE (and incr. refcount)
jwe->hdr = header;
json_incref(jwe->hdr);

// serialize the header
char *hdr_str = json_dumps(header, JSON_ENCODE_ANY | JSON_PRESERVE_ORDER);
if (NULL == hdr_str)
Expand Down Expand Up @@ -569,14 +573,14 @@ static bool _cjose_jwe_decrypt_dat_a256gcm(
////////////////////////////////////////////////////////////////////////////////
cjose_jwe_t *cjose_jwe_encrypt(
const cjose_jwk_t *jwk,
cjose_header_t *header,
cjose_header_t *protected_header,
const uint8_t *plaintext,
size_t plaintext_len,
cjose_err *err)
{
cjose_jwe_t *jwe = NULL;

if (NULL == jwk || NULL == header)
if (NULL == jwk || NULL == protected_header)
{
CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
return NULL;
Expand All @@ -585,7 +589,7 @@ cjose_jwe_t *cjose_jwe_encrypt(
// if not already set, add kid header to JWE to match that of JWK
const char *kid = cjose_jwk_get_kid(jwk, err);
if (NULL != kid) {
if (!cjose_header_set(header, CJOSE_HDR_KID, kid, err))
if (!cjose_header_set(protected_header, CJOSE_HDR_KID, kid, err))
{
CJOSE_ERROR(err, CJOSE_ERR_INVALID_STATE);
return false;
Expand All @@ -599,14 +603,14 @@ cjose_jwe_t *cjose_jwe_encrypt(
}

// validate JWE header
if (!_cjose_jwe_validate_hdr(jwe, header, err))
if (!_cjose_jwe_validate_hdr(jwe, protected_header, err))
{
cjose_jwe_release(jwe);
return NULL;
}

// build JWE header
if (!_cjose_jwe_build_hdr(jwe, header, err))
if (!_cjose_jwe_build_hdr(jwe, protected_header, err))
{
cjose_jwe_release(jwe);
return NULL;
Expand Down Expand Up @@ -645,6 +649,11 @@ void cjose_jwe_release(
{
return;
}
if (NULL != jwe->hdr)
{
json_decref(jwe->hdr);
}

for (int i = 0; i < 5; ++i)
{
cjose_get_dealloc()(jwe->part[i].raw);
Expand All @@ -655,7 +664,6 @@ void cjose_jwe_release(
cjose_get_dealloc()(jwe);
}


////////////////////////////////////////////////////////////////////////////////
char *cjose_jwe_export(
cjose_jwe_t *jwe,
Expand Down Expand Up @@ -797,24 +805,22 @@ cjose_jwe_t *cjose_jwe_import(
}

// deserialize JSON header
json_t *header = json_loadb(
(const char *)jwe->part[0].raw, jwe->part[0].raw_len, 0, NULL);
if (NULL == header)
jwe->hdr = json_loadb(
(const char *)jwe->part[0].raw, jwe->part[0].raw_len, 0, NULL);
if (NULL == jwe->hdr)
{
CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
cjose_jwe_release(jwe);
return NULL;
}

// validate the JSON header
if (!_cjose_jwe_validate_hdr(jwe, header, err))
if (!_cjose_jwe_validate_hdr(jwe, jwe->hdr, err))
{
json_decref(header);
CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
cjose_jwe_release(jwe);
return NULL;
}
json_decref(header);

return jwe;
}
Expand Down Expand Up @@ -853,3 +859,13 @@ uint8_t *cjose_jwe_decrypt(

return content;
}

////////////////////////////////////////////////////////////////////////////////
cjose_header_t *cjose_jwe_get_protected(cjose_jwe_t *jwe)
{
if (NULL == jwe)
{
return NULL;
}
return jwe->hdr;
}
18 changes: 15 additions & 3 deletions src/jws.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,14 +371,14 @@ static bool _cjose_jws_build_cser(
////////////////////////////////////////////////////////////////////////////////
cjose_jws_t *cjose_jws_sign(
const cjose_jwk_t *jwk,
cjose_header_t *header,
cjose_header_t *protected_header,
const uint8_t *plaintext,
size_t plaintext_len,
cjose_err *err)
{
cjose_jws_t *jws = NULL;

if (NULL == jwk || NULL == header || NULL == plaintext)
if (NULL == jwk || NULL == protected_header || NULL == plaintext)
{
CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG);
return NULL;
Expand All @@ -394,7 +394,7 @@ cjose_jws_t *cjose_jws_sign(
memset(jws, 0, sizeof(cjose_jws_t));

// build JWS header
if (!_cjose_jws_build_hdr(jws, header, err))
if (!_cjose_jws_build_hdr(jws, protected_header, err))
{
cjose_jws_release(jws);
return NULL;
Expand Down Expand Up @@ -784,3 +784,15 @@ bool cjose_jws_get_plaintext(

return true;
}

////////////////////////////////////////////////////////////////////////////////
cjose_header_t *cjose_jws_get_protected(
cjose_jws_t *jws)
{
if (NULL == jws)
{
return NULL;
}

return jws->hdr;
}
16 changes: 16 additions & 0 deletions test/check_header.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ START_TEST(test_cjose_header_new_release)
}
END_TEST

START_TEST(test_cjose_header_retain_release)
{
cjose_err err;

cjose_header_t *header = cjose_header_new(&err);
ck_assert_msg(NULL != header, "cjose_header_new failed");

header = cjose_header_retain(header);
ck_assert_msg(NULL != header, "cjose_header_retain failed");

cjose_header_release(header);

cjose_header_release(header);
}
END_TEST

START_TEST(test_cjose_header_set_get)
{
Expand Down Expand Up @@ -70,6 +85,7 @@ Suite *cjose_header_suite()

TCase *tc_header = tcase_create("core");
tcase_add_test(tc_header, test_cjose_header_new_release);
tcase_add_test(tc_header, test_cjose_header_retain_release);
tcase_add_test(tc_header, test_cjose_header_set_get);
suite_add_tcase(suite, tc_header);

Expand Down
4 changes: 4 additions & 0 deletions test/check_jwe.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ static void _self_encrypt_self_decrypt_with_key(
ck_assert_msg(NULL != jwe1,
"cjose_jwe_encrypt failed: %s, file: %s, function: %s, line: %ld",
err.message, err.file, err.function, err.line);
ck_assert(hdr == cjose_jwe_get_protected(jwe1));

// get the compact serialization of JWE
char *compact = cjose_jwe_export(jwe1, &err);
Expand All @@ -140,6 +141,9 @@ static void _self_encrypt_self_decrypt_with_key(
err.message, err.file, err.function, err.line);

// confirm plain2 == plain1
ck_assert(json_equal(
cjose_jwe_get_protected(jwe1),
cjose_jwe_get_protected(jwe2)));
ck_assert_msg(
plain2_len == strlen(plain1),
"length of decrypted plaintext does not match length of original, "
Expand Down
8 changes: 7 additions & 1 deletion test/check_jws.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static void _self_sign_self_verify(
ck_assert_msg(NULL != jws1, "cjose_jws_sign failed: "
"%s, file: %s, function: %s, line: %ld",
err->message, err->file, err->function, err->line);
ck_assert(hdr == cjose_jws_get_protected(jws1));

// get the compact serialization of JWS
char *compact = NULL;
Expand All @@ -77,7 +78,7 @@ static void _self_sign_self_verify(
// verify the deserialized JWS
ck_assert_msg(cjose_jws_verify(jws2, jwk, err), "cjose_jws_verify failed");

// get the verifyed plaintext
// get the verified plaintext
uint8_t *plain2 = NULL;
size_t plain2_len = 0;
ck_assert_msg(
Expand All @@ -86,6 +87,11 @@ static void _self_sign_self_verify(
"%s, file: %s, function: %s, line: %ld",
err->message, err->file, err->function, err->line);

// confirm equal headers
ck_assert(json_equal(
cjose_jws_get_protected(jws1),
cjose_jws_get_protected(jws2)));

// confirm plain2 == plain1
ck_assert_msg(
plain2_len == strlen(plain1),
Expand Down

0 comments on commit 6d1d1be

Please sign in to comment.