in jose/apr_jose_decode.c [498:643]
apr_status_t apr_jose_decode_compact_jwe(apr_jose_t **jose, const char *left,
const char *right, apr_json_value_t *ph, apr_json_value_t *enc,
const char *typ, const char *cty, apr_jose_text_t *ph64,
apr_jose_cb_t *cb, int level, int flags, apr_pool_t *pool,
apr_bucket_brigade *bb)
{
const char *dot;
apr_jose_jwe_t *jwe;
apr_jose_text_t aad64;
apr_status_t status;
int dflags = APR_JOSE_FLAG_NONE;
if (!cb || !cb->decrypt) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Decryption failed: no decrypt callback provided");
return APR_EINIT;
}
*jose = apr_jose_jwe_make(*jose, NULL, NULL, NULL, NULL, pool);
if (!*jose) {
return APR_ENOMEM;
}
jwe = (*jose)->jose.jwe;
jwe->encryption = apr_jose_encryption_make(NULL, NULL,
NULL, pool);
if (!jwe->encryption) {
return APR_ENOMEM;
}
jwe->recipient = apr_jose_recipient_make(NULL, NULL, NULL, pool);
if (!jwe->recipient) {
return APR_ENOMEM;
}
/*
* Parse the JWE representation to extract the serialized values
* for the components of the JWE. When using the JWE Compact
* Serialization, these components are the base64url-encoded
* representations of the JWE Protected Header, the JWE Encrypted
* Key, the JWE Initialization Vector, the JWE Ciphertext, and the
* JWE Authentication Tag, and when using the JWE JSON
* Serialization, these components also include the base64url-
* encoded representation of the JWE AAD and the unencoded JWE
* Shared Unprotected Header and JWE Per-Recipient Unprotected
* Header values. When using the JWE Compact Serialization, the
* JWE Protected Header, the JWE Encrypted Key, the JWE
* Initialization Vector, the JWE Ciphertext, and the JWE
* Authentication Tag are represented as base64url-encoded values
* in that order, with each value being separated from the next by
* a single period ('.') character, resulting in exactly four
* delimiting period characters being used. The JWE JSON
* Serialization is described in Section 7.2.
*/
/* protected header */
if (ph) {
jwe->encryption->protected = ph;
}
/* encrypted key */
dot = memchr(left, '.', right - left);
if (!dot) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Syntax error: compact JWE decoding failed: one lonely dot");
return APR_BADCH;
}
jwe->recipient->ekey.data = apr_pdecode_base64_binary(pool, left,
dot - left, APR_ENCODE_BASE64URL, &jwe->recipient->ekey.len);
if (!jwe->recipient->ekey.data) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Syntax error: JWE ekey base64url decoding failed at %" APR_SIZE_T_FMT "",
jwe->recipient->ekey.len);
return APR_BADCH;
}
left = dot + 1;
/* iv */
dot = memchr(left, '.', right - left);
if (!dot) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Syntax error: JWE compact decoding failed: only two dots");
return APR_BADCH;
}
jwe->encryption->iv.data = apr_pdecode_base64_binary(pool, left,
dot - left, APR_ENCODE_BASE64URL, &jwe->encryption->iv.len);
if (!jwe->encryption->iv.data) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Syntax error: JWE iv base64url decoding failed at %" APR_SIZE_T_FMT "",
jwe->encryption->iv.len);
return APR_BADCH;
}
left = dot + 1;
/* ciphertext */
dot = memchr(left, '.', right - left);
if (!dot) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Syntax error: JOSE compact JWE decoding failed: only three dots");
return APR_BADCH;
}
jwe->encryption->cipher.data = apr_pdecode_base64_binary(pool, left,
dot - left, APR_ENCODE_BASE64URL, &jwe->encryption->cipher.len);
if (!jwe->encryption->cipher.data) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Syntax error: JWE ciphertext base64url decoding failed at %" APR_SIZE_T_FMT "",
jwe->encryption->cipher.len);
return APR_BADCH;
}
left = dot + 1;
/* tag */
jwe->encryption->tag.data = apr_pdecode_base64_binary(pool, left,
dot - left, APR_ENCODE_BASE64URL, &jwe->encryption->tag.len);
if (!jwe->encryption->tag.data) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Syntax error: JWE tag base64url decoding failed at %" APR_SIZE_T_FMT "",
jwe->encryption->tag.len);
return APR_BADCH;
}
/* aad is the empty string in compact serialisation */
memset(&aad64, 0, sizeof(apr_jose_text_t));
status = apr_jose_decode_jwe_recipient(jose,
bb, jwe->recipient, jwe->encryption, typ, cty, ph64, &aad64, cb,
level, &dflags, pool);
if (APR_SUCCESS != status) {
apr_errprintf(&(*jose)->result, pool, NULL, 0,
"Decryption failed: JWE decryption failed");
return status;
}
return APR_SUCCESS;
}