static apr_status_t apr_jose_encode_json_jws()

in jose/apr_jose_encode.c [481:672]


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;
    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 */

    apr_json_object_set(json, "payload", APR_JSON_VALUE_STRING,
            apr_json_string_create(p, buf64, len64), 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;
        }

        apr_json_object_set(json, "protected", APR_JSON_VALUE_STRING,
                apr_json_string_create(p, buf, len), 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 */

        apr_json_object_set(json, "header", APR_JSON_VALUE_STRING,
                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);

        apr_json_object_set(json, "signature", APR_JSON_VALUE_STRING,
                apr_json_string_create(p, buf64, len64), p);

    }

    /* otherwise calculate the general signatures */

    else if (jws->signatures) {

        apr_json_value_t *sigs;
        int i;

        /* create signatures element */

        sigs = apr_json_array_create(p, jws->signatures->nelts);
        apr_json_object_set(json, "signatures", APR_JSON_VALUE_STRING,
                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 */

            apr_json_object_set(s, "protected", APR_JSON_VALUE_STRING,
                    apr_json_string_create(p, buf, len), 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 */

            apr_json_object_set(s, "header", APR_JSON_VALUE_STRING,
                    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);

            apr_json_object_set(s, "signature", APR_JSON_VALUE_STRING,
                    apr_json_string_create(p, buf64, len64), 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;
}