summaryrefslogtreecommitdiff
path: root/jose/apr_jose_encode.c
diff options
context:
space:
mode:
authorGraham Leggett <minfrin@apache.org>2018-09-01 11:17:14 +0000
committerGraham Leggett <minfrin@apache.org>2018-09-01 11:17:14 +0000
commit05673b3dde8b8d3e7262e88015bee0efb46adee4 (patch)
tree5b55d0f34051c7ddeef9959e66dab5a8fb0dda96 /jose/apr_jose_encode.c
parentf0cf7790b9594f068ba0879bb08bf29a44b1b5e7 (diff)
downloadapr-05673b3dde8b8d3e7262e88015bee0efb46adee4.tar.gz
apr_jose: Add support for encoding and decoding of JSON Object
Signing and Encryption messages as per RFC7515, RFC7516, RFC7517 and RFC7519. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1839819 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'jose/apr_jose_encode.c')
-rw-r--r--jose/apr_jose_encode.c825
1 files changed, 825 insertions, 0 deletions
diff --git a/jose/apr_jose_encode.c b/jose/apr_jose_encode.c
new file mode 100644
index 000000000..43a4adc8b
--- /dev/null
+++ b/jose/apr_jose_encode.c
@@ -0,0 +1,825 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_jose.h"
+#include "apr_encode.h"
+
+static apr_status_t apr_jose_encode_base64_json(apr_bucket_brigade *brigade,
+ apr_brigade_flush flush, void *ctx, apr_json_value_t *json,
+ apr_pool_t *pool)
+{
+ apr_status_t status = APR_SUCCESS;
+
+ if (json) {
+
+ apr_bucket_brigade *bb;
+
+ bb = apr_brigade_create(pool, brigade->bucket_alloc);
+
+ status = apr_json_encode(bb, flush, ctx, json,
+ APR_JSON_FLAGS_WHITESPACE, pool);
+ if (APR_SUCCESS == status) {
+
+ char *buf;
+ apr_size_t buflen;
+ const char *buf64;
+ apr_size_t buf64len;
+
+ apr_brigade_pflatten(bb, &buf, &buflen, pool);
+ buf64 = apr_pencode_base64(pool, buf, buflen, APR_ENCODE_BASE64URL,
+ &buf64len);
+ status = apr_brigade_write(brigade, flush, ctx, buf64, buf64len);
+
+ }
+
+ }
+
+ return status;
+}
+
+static apr_status_t apr_jose_encode_compact_jwe(apr_bucket_brigade *brigade,
+ apr_brigade_flush flush, void *ctx, apr_jose_t *jose, apr_jose_cb_t *cb,
+ apr_pool_t *p)
+{
+ apr_bucket_brigade *bb = apr_brigade_create(p,
+ brigade->bucket_alloc);
+
+ apr_jose_jwe_t *jwe = jose->jose.jwe;
+
+ apr_status_t status = APR_SUCCESS;
+
+ /*
+ * 7.1. JWE Compact Serialization
+ *
+ * The JWE Compact Serialization represents encrypted content as a
+ * compact, URL-safe string. This string is:
+ *
+ * BASE64URL(UTF8(JWE Protected Header)) || '.' ||
+ */
+
+ status = apr_jose_encode_base64_json(brigade, flush, ctx,
+ jwe->encryption->protected, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ status = apr_brigade_write(brigade, flush, ctx, ".", 1);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ if (cb && cb->encrypt) {
+ status = apr_jose_encode(bb, flush, ctx, jwe->payload, cb, p);
+ if (APR_SUCCESS != status) {
+ jose->result = jwe->payload->result;
+ return status;
+ }
+ status = cb->encrypt(bb, jose, jwe->recipient, jwe->encryption,
+ cb->ctx, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ if (APR_SUCCESS == status) {
+
+ struct iovec vec[7];
+
+ /*
+ * 7. Compute the encoded key value BASE64URL(JWE Encrypted Key).
+ *
+ * 10. Compute the encoded Initialization Vector value BASE64URL(JWE
+ * Initialization Vector).
+ *
+ * 16. Compute the encoded ciphertext value BASE64URL(JWE Ciphertext).
+ *
+ * 17. Compute the encoded Authentication Tag value BASE64URL(JWE
+ * Authentication Tag).
+ *
+ * 18. If a JWE AAD value is present, compute the encoded AAD value
+ * BASE64URL(JWE AAD).
+ *
+ * 19. Create the desired serialized output. The Compact Serialization
+ * of this result is the string BASE64URL(UTF8(JWE Protected
+ * Header)) || '.' || BASE64URL(JWE Encrypted Key) || '.' ||
+ * BASE64URL(JWE Initialization Vector) || '.' || BASE64URL(JWE
+ * Ciphertext) || '.' || BASE64URL(JWE Authentication Tag). The
+ * JWE JSON Serialization is described in Section 7.2.
+ */
+
+ /*
+ * BASE64URL(JWE Encrypted Key) || '.' ||
+ */
+
+ vec[0].iov_base = (void *) apr_pencode_base64_binary(p,
+ jwe->recipient->ekey.data, jwe->recipient->ekey.len,
+ APR_ENCODE_BASE64URL, &vec[0].iov_len);
+ vec[1].iov_base = ".";
+ vec[1].iov_len = 1;
+
+ /*
+ * BASE64URL(JWE Initialization Vector) || '.' ||
+ */
+
+ vec[2].iov_base = (void *) apr_pencode_base64_binary(p,
+ jwe->encryption->iv.data, jwe->encryption->iv.len,
+ APR_ENCODE_BASE64URL, &vec[2].iov_len);
+ vec[3].iov_base = ".";
+ vec[3].iov_len = 1;
+
+ /*
+ * BASE64URL(JWE Ciphertext) || '.' ||
+ */
+
+ vec[4].iov_base = (void *) apr_pencode_base64_binary(p,
+ jwe->encryption->cipher.data, jwe->encryption->cipher.len,
+ APR_ENCODE_BASE64URL, &vec[4].iov_len);
+ vec[5].iov_base = ".";
+ vec[5].iov_len = 1;
+
+ /*
+ * BASE64URL(JWE Authentication Tag)
+ */
+
+ vec[6].iov_base = (void *)apr_pencode_base64_binary(p, jwe->encryption->tag.data, jwe->encryption->tag.len,
+ APR_ENCODE_BASE64URL, &vec[6].iov_len);
+
+ status = apr_brigade_writev(brigade, flush, ctx, vec, 7);
+
+ }
+
+ return status;
+}
+
+static apr_status_t apr_jose_encode_compact_jws(apr_bucket_brigade *brigade,
+ apr_brigade_flush flush, void *ctx, apr_jose_t *jose, apr_jose_cb_t *cb,
+ apr_pool_t *p)
+{
+ apr_bucket *e;
+ apr_bucket_brigade *bb = apr_brigade_create(p,
+ brigade->bucket_alloc);
+ apr_jose_text_t payload;
+ apr_jose_text_t payload64;
+
+ apr_jose_jws_t *jws = jose->jose.jws;
+
+ apr_status_t status;
+
+ status = apr_jose_encode(bb, flush, ctx, jws->payload, cb, p);
+ if (APR_SUCCESS != status) {
+ jose->result = jws->payload->result;
+ return status;
+ }
+
+ status = apr_brigade_pflatten(bb, (char **)&payload.text, &payload.len, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ payload64.text = apr_pencode_base64(p, payload.text, payload.len,
+ APR_ENCODE_BASE64URL, &payload64.len);
+
+ apr_brigade_cleanup(bb);
+
+ /*
+ * 7.1. JWS Compact Serialization
+ *
+ * The JWS Compact Serialization represents digitally signed or MACed
+ * content as a compact, URL-safe string. This string is:
+ *
+ * BASE64URL(UTF8(JWS Protected Header)) || '.' ||
+ */
+
+ if (jws->signature) {
+ status = apr_jose_encode_base64_json(bb, flush, ctx,
+ jws->signature->protected_header, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ status = apr_brigade_write(bb, flush, ctx, ".", 1);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ /*
+ * BASE64URL(JWS Payload) ||
+ */
+
+ e = apr_bucket_pool_create(payload64.text, payload64.len, p,
+ bb->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+
+ /*
+ * '.' || BASE64URL(JWS Signature)
+ */
+
+ if (cb && cb->sign && jws->signature) {
+ status = cb->sign(bb, jose, jws->signature, cb->ctx, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ APR_BRIGADE_CONCAT(brigade, bb);
+
+ status = apr_brigade_write(brigade, flush, ctx, ".", 1);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ if (jws->signature && jws->signature->sig.data && APR_SUCCESS == status) {
+
+ const char *buf64;
+ apr_size_t buf64len;
+
+ buf64 = apr_pencode_base64_binary(p, jws->signature->sig.data,
+ jws->signature->sig.len,
+ APR_ENCODE_BASE64URL, &buf64len);
+ status = apr_brigade_write(brigade, flush, ctx, buf64,
+ buf64len);
+
+ }
+
+ return status;
+}
+
+static apr_status_t apr_jose_encode_json_jwe(apr_bucket_brigade *brigade,
+ apr_brigade_flush flush, void *ctx, apr_jose_t *jose, apr_jose_cb_t *cb,
+ apr_pool_t *p)
+{
+
+ apr_json_value_t *json, *key, *val;
+ char *buf;
+ const char *buf64;
+ apr_size_t len;
+ apr_size_t len64;
+
+ apr_bucket_brigade *bb = apr_brigade_create(p,
+ brigade->bucket_alloc);
+
+ apr_jose_jwe_t *jwe = jose->jose.jwe;
+
+ apr_status_t status = APR_SUCCESS;
+
+ /* create our json */
+
+ json = apr_json_object_create(p);
+
+ /* create protected header */
+
+ if (jwe->encryption) {
+ apr_jose_encryption_t *e = jwe->encryption;
+
+ if (e->protected) {
+
+ status = apr_jose_encode_base64_json(bb, flush, ctx,
+ e->protected, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ status = apr_brigade_pflatten(bb, &buf, &len, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ apr_brigade_cleanup(bb);
+
+ key = apr_json_string_create(p, "protected",
+ APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf, len);
+ apr_json_object_set(json, key, val, p);
+
+ }
+
+ /* create unprotected header */
+
+ if (e->unprotected) {
+
+ key = apr_json_string_create(p, "unprotected",
+ APR_JSON_VALUE_STRING);
+ apr_json_object_set(json, key, e->unprotected, p);
+
+ }
+
+ /* create recipient */
+ if (jwe->recipient) {
+
+ apr_jose_recipient_t *recip = jwe->recipient;
+
+ /* create the payload */
+
+ status = apr_jose_encode(bb, flush, ctx, jwe->payload, cb, p);
+ if (APR_SUCCESS != status) {
+ jose->result = jwe->payload->result;
+ return status;
+ }
+
+ if (cb && cb->encrypt && recip) {
+ status = cb->encrypt(bb, jose, recip, e, cb->ctx, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ apr_brigade_cleanup(bb);
+
+ /* create header */
+
+ key = apr_json_string_create(p, "header",
+ APR_JSON_VALUE_STRING);
+ apr_json_object_set(json, key, recip->header, p);
+
+ apr_brigade_cleanup(bb);
+
+ /* create encrypted key */
+
+ buf64 = apr_pencode_base64_binary(p, recip->ekey.data,
+ recip->ekey.len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ key = apr_json_string_create(p, "encrypted_key",
+ APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(json, key, val, p);
+
+ }
+
+ /* create recipients */
+ if (jwe->recipients) {
+
+ apr_json_value_t *recips;
+ int i;
+
+ /* create recipients element */
+
+ key = apr_json_string_create(p, "recipients",
+ APR_JSON_VALUE_STRING);
+ recips = apr_json_array_create(p, jwe->recipients->nelts);
+ apr_json_object_set(json, key, recips, p);
+
+ /* populate each recipient */
+
+ for (i = 0; i < jwe->recipients->nelts; i++) {
+ apr_json_value_t *r = apr_json_object_create(p);
+ apr_jose_recipient_t *recip = APR_ARRAY_IDX(
+ jwe->recipients, i, apr_jose_recipient_t *);
+
+ if (!recip) {
+ continue;
+ }
+
+ apr_json_array_add(recips, r);
+
+ /* create the payload */
+
+ status = apr_jose_encode(bb, flush, ctx, jwe->payload, cb, p);
+ if (APR_SUCCESS != status) {
+ jose->result = jwe->payload->result;
+ return status;
+ }
+
+ if (cb && cb->encrypt && recip) {
+ status = cb->encrypt(bb, jose, recip, e, cb->ctx, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ apr_brigade_cleanup(bb);
+
+ /* create header */
+
+ key = apr_json_string_create(p, "header",
+ APR_JSON_VALUE_STRING);
+ apr_json_object_set(r, key, recip->header, p);
+
+ apr_brigade_cleanup(bb);
+
+ /* create encrypted key */
+
+ buf64 = apr_pencode_base64_binary(p, recip->ekey.data,
+ recip->ekey.len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ key = apr_json_string_create(p, "encrypted_key",
+ APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(r, key, val, p);
+
+ }
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ }
+
+ /* create iv */
+
+ if (e->iv.len) {
+
+ buf64 = apr_pencode_base64_binary(p, e->iv.data, e->iv.len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ key = apr_json_string_create(p, "iv", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(json, key, val, p);
+ }
+
+ /* create aad */
+
+ if (e->aad.len) {
+
+ buf64 = apr_pencode_base64_binary(p, e->aad.data, e->aad.len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ key = apr_json_string_create(p, "aad", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(json, key, val, p);
+ }
+
+ /* create ciphertext */
+
+ if (e->cipher.len) {
+
+ buf64 = apr_pencode_base64_binary(p, e->cipher.data, e->cipher.len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ key = apr_json_string_create(p, "ciphertext", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(json, key, val, p);
+ }
+
+ /* create tag */
+
+ if (e->tag.len) {
+
+ buf64 = apr_pencode_base64_binary(p, e->tag.data, e->tag.len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ key = apr_json_string_create(p, "tag", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(json, key, val, p);
+ }
+
+ }
+
+ /* write out our final result */
+
+ if (json) {
+ status = apr_json_encode(brigade, flush, ctx, json,
+ APR_JSON_FLAGS_WHITESPACE, p);
+ }
+
+ return status;
+}
+
+static apr_status_t apr_jose_encode_json_jws(apr_bucket_brigade *brigade,
+ apr_brigade_flush flush, void *ctx, apr_jose_t *jose, apr_jose_cb_t *cb,
+ apr_pool_t *p)
+{
+ apr_json_value_t *json, *key, *val;
+ char *buf;
+ const char *buf64;
+ apr_size_t len;
+ apr_size_t len64;
+
+ apr_bucket_brigade *bb = apr_brigade_create(p,
+ brigade->bucket_alloc);
+
+ apr_jose_jws_t *jws = jose->jose.jws;
+
+ apr_status_t status = APR_SUCCESS;
+
+ /* create our json */
+
+ json = apr_json_object_create(p);
+
+ /* calculate BASE64URL(JWS Payload) */
+
+ status = apr_jose_encode(bb, flush, ctx, jws->payload, cb, p);
+ if (APR_SUCCESS != status) {
+ jose->result = jws->payload->result;
+ return status;
+ }
+
+ status = apr_brigade_pflatten(bb, &buf, &len, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ buf64 = apr_pencode_base64(p, buf, len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ apr_brigade_cleanup(bb);
+
+ /* add the payload to our json */
+
+ key = apr_json_string_create(p, "payload", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(json, key, val, p);
+
+ /* calculate the flattened signature */
+
+ if (jws->signature) {
+
+ /* create protected header */
+
+ status = apr_jose_encode_base64_json(bb, flush, ctx,
+ jws->signature->protected_header, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ status = apr_brigade_pflatten(bb, &buf, &len, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ key = apr_json_string_create(p, "protected", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf, len);
+ apr_json_object_set(json, key, val, p);
+
+ status = apr_brigade_write(bb, flush, ctx, ".", 1);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ status = apr_brigade_write(bb, flush, ctx, buf64, len64);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ if (cb && cb->sign && jws->signature) {
+ status = cb->sign(bb, jose, jws->signature, cb->ctx, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ apr_brigade_cleanup(bb);
+
+ /* create header */
+
+ key = apr_json_string_create(p, "header", APR_JSON_VALUE_STRING);
+ apr_json_object_set(json, key, jws->signature->header, p);
+
+ apr_brigade_cleanup(bb);
+
+ /* create signature */
+
+ buf64 = apr_pencode_base64_binary(p,
+ jws->signature->sig.data, jws->signature->sig.len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ key = apr_json_string_create(p, "signature", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(json, key, val, p);
+
+ }
+
+ /* otherwise calculate the general signatures */
+
+ else if (jws->signatures) {
+
+ apr_json_value_t *sigs;
+ int i;
+
+ /* create signatures element */
+
+ key = apr_json_string_create(p, "signatures", APR_JSON_VALUE_STRING);
+ sigs = apr_json_array_create(p, jws->signatures->nelts);
+ apr_json_object_set(json, key, sigs, p);
+
+ /* populate each signature */
+
+ for (i = 0; i < jws->signatures->nelts; i++) {
+ apr_json_value_t *s = apr_json_object_create(p);
+ apr_jose_signature_t *sig = APR_ARRAY_IDX(
+ jws->signatures, i, apr_jose_signature_t *);
+
+ apr_json_array_add(sigs, s);
+
+ /* create protected header */
+
+ status = apr_jose_encode_base64_json(bb, flush, ctx,
+ sig->protected_header, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ status = apr_brigade_pflatten(bb, &buf, &len, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ /* add protected header to array */
+
+ key = apr_json_string_create(p, "protected", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf, len);
+ apr_json_object_set(s, key, val, p);
+
+ status = apr_brigade_write(bb, flush, ctx, ".", 1);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ status = apr_brigade_write(bb, flush, ctx, buf64, len64);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ if (cb && cb->sign && sig) {
+ status = cb->sign(bb, jose, sig, cb->ctx, p);
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+ }
+
+ apr_brigade_cleanup(bb);
+
+ /* create header */
+
+ key = apr_json_string_create(p, "header", APR_JSON_VALUE_STRING);
+ apr_json_object_set(s, key, sig->header, p);
+
+ apr_brigade_cleanup(bb);
+
+ /* create signature */
+
+ buf64 = apr_pencode_base64_binary(p, sig->sig.data,
+ sig->sig.len,
+ APR_ENCODE_BASE64URL, &len64);
+
+ key = apr_json_string_create(p, "signature", APR_JSON_VALUE_STRING);
+ val = apr_json_string_create(p, buf64, len64);
+ apr_json_object_set(s, key, val, p);
+
+ }
+ if (APR_SUCCESS != status) {
+ return status;
+ }
+
+ }
+
+ /* write out our final result */
+
+ if (json) {
+ status = apr_json_encode(brigade, flush, ctx, json,
+ APR_JSON_FLAGS_WHITESPACE, p);
+ }
+
+ return status;
+}
+
+apr_status_t apr_jose_encode(apr_bucket_brigade *brigade,
+ apr_brigade_flush flush, void *ctx, apr_jose_t *jose, apr_jose_cb_t *cb,
+ apr_pool_t *pool)
+{
+ apr_pool_t *p;
+ apr_status_t status = APR_EINVAL;
+
+ /* if asked to encode nothing, encode nothing */
+ if (jose == NULL) {
+ return APR_SUCCESS;
+ }
+
+ apr_pool_create(&p, pool);
+ if (p == NULL) {
+ return APR_ENOMEM;
+ }
+
+ /* first, generic data types */
+ switch (jose->type) {
+ case APR_JOSE_TYPE_JWK: {
+
+ /* do nothing for now */
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_JWKS: {
+
+ /* do nothing for now */
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_DATA: {
+
+ apr_jose_data_t *data = jose->jose.data;
+
+ if (data) {
+
+ struct iovec vec[1];
+
+ vec[0].iov_base = (void *)data->data;
+ vec[0].iov_len = data->len;
+
+ status = apr_brigade_writev(brigade, flush, ctx, vec, 1);
+ if (APR_SUCCESS != status) {
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_TEXT: {
+
+ apr_jose_text_t *text = jose->jose.text;
+
+ if (text) {
+ status = apr_brigade_write(brigade, flush, ctx, text->text,
+ text->len);
+ if (APR_SUCCESS != status) {
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_JSON: {
+
+ apr_json_value_t *json = jose->jose.json->json;
+
+ if (json) {
+ status = apr_json_encode(brigade, flush, ctx, json,
+ APR_JSON_FLAGS_WHITESPACE, p);
+ }
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_JWE: {
+
+ status = apr_jose_encode_compact_jwe(brigade, flush, ctx, jose, cb,
+ p);
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_JWE_JSON: {
+
+ status = apr_jose_encode_json_jwe(brigade, flush, ctx, jose, cb, p);
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_JWS: {
+
+ status = apr_jose_encode_compact_jws(brigade, flush, ctx, jose, cb,
+ p);
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_JWS_JSON: {
+
+ status = apr_jose_encode_json_jws(brigade, flush, ctx, jose, cb, p);
+
+ break;
+ }
+
+ case APR_JOSE_TYPE_JWT: {
+
+ apr_json_value_t *claims = jose->jose.jwt->claims;
+
+ if (claims) {
+ status = apr_json_encode(brigade, flush, ctx, claims,
+ APR_JSON_FLAGS_WHITESPACE, p);
+ }
+
+ break;
+ }
+
+ default: {
+ apr_errprintf(&jose->result, pool, NULL, 0,
+ "JOSE type '%d' not recognised", jose->type);
+
+ status = APR_ENOTIMPL;
+
+ break;
+ }
+ }
+
+ apr_pool_destroy(p);
+
+ return status;
+}