summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGraham Leggett <minfrin@apache.org>2018-09-01 19:42:30 +0000
committerGraham Leggett <minfrin@apache.org>2018-09-01 19:42:30 +0000
commit49c6f8385af187c1a66b0719829e1c7f17de301b (patch)
tree94e5fc011e58f700a1fb26977614ce896bfb9d2e /test
parent05673b3dde8b8d3e7262e88015bee0efb46adee4 (diff)
downloadapr-49c6f8385af187c1a66b0719829e1c7f17de301b.tar.gz
Add header and tests for JOSE support. I need sleep.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1839838 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test')
-rw-r--r--test/testjose.c1423
1 files changed, 1423 insertions, 0 deletions
diff --git a/test/testjose.c b/test/testjose.c
new file mode 100644
index 000000000..411b7c5d0
--- /dev/null
+++ b/test/testjose.c
@@ -0,0 +1,1423 @@
+/* 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_jose.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+
+static apr_status_t sign_cb(apr_bucket_brigade *bb, apr_jose_t *jose,
+ apr_jose_signature_t *signature, void *ctx, apr_pool_t *pool)
+{
+ abts_case *tc = ctx;
+ apr_json_kv_t *alg = NULL;
+
+ if (signature) {
+ apr_json_value_t *ph = signature->protected_header;
+
+ ABTS_INT_EQUAL(tc, APR_JSON_OBJECT, ph->type);
+
+ if (ph->type == APR_JSON_OBJECT) {
+ alg = apr_json_object_get(ph, APR_JOSE_JWKSE_ALGORITHM,
+ APR_JSON_VALUE_STRING);
+ }
+ }
+
+ if (alg) {
+
+ ABTS_INT_EQUAL(tc, APR_JSON_STRING, alg->v->type);
+
+ /* unsecured jws/jwt */
+ if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "none",
+ alg->v->value.string.len)) {
+
+ signature->sig.data = (unsigned const char *) "";
+ signature->sig.len = 0;
+
+ return APR_SUCCESS;
+ }
+
+ /* hs256 jws - https://tools.ietf.org/html/rfc7515#appendix-A.1 */
+ else if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "HS256",
+ alg->v->value.string.len)) {
+
+ const unsigned char hs256[] = { 116, 24, 223, 180, 151, 153, 224,
+ 37, 79, 250, 96, 125, 216, 173, 187, 186, 22, 212, 37, 77,
+ 105, 214, 191, 240, 91, 88, 5, 88, 83, 132, 141, 121 };
+ signature->sig.data = apr_pmemdup(p, hs256, sizeof(hs256));
+ signature->sig.len = sizeof(hs256);
+
+ return APR_SUCCESS;
+ }
+
+ /* rs256 jws - https://tools.ietf.org/html/rfc7515#appendix-A.2 */
+ else if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "RS256",
+ alg->v->value.string.len)) {
+
+ const unsigned char rs256[] = { 112, 46, 33, 137, 67, 232, 143, 209,
+ 30, 181, 216, 45, 191, 120, 69, 243, 65, 6, 174, 27, 129,
+ 255, 247, 115, 17, 22, 173, 209, 113, 125, 131, 101, 109,
+ 66, 10, 253, 60, 150, 238, 221, 115, 162, 102, 62, 81, 102,
+ 104, 123, 0, 11, 135, 34, 110, 1, 135, 237, 16, 115, 249,
+ 69, 229, 130, 173, 252, 239, 22, 216, 90, 121, 142, 232,
+ 198, 109, 219, 61, 184, 151, 91, 23, 208, 148, 2, 190, 237,
+ 213, 217, 217, 112, 7, 16, 141, 178, 129, 96, 213, 248, 4,
+ 12, 167, 68, 87, 98, 184, 31, 190, 127, 249, 217, 46, 10,
+ 231, 111, 36, 242, 91, 51, 187, 230, 244, 74, 230, 30, 177,
+ 4, 10, 203, 32, 4, 77, 62, 249, 18, 142, 212, 1, 48, 121,
+ 91, 212, 189, 59, 65, 238, 202, 208, 102, 171, 101, 25, 129,
+ 253, 228, 141, 247, 127, 55, 45, 195, 139, 159, 175, 221,
+ 59, 239, 177, 139, 93, 163, 204, 60, 46, 176, 47, 158, 58,
+ 65, 214, 18, 202, 173, 21, 145, 18, 115, 160, 95, 35, 185,
+ 232, 56, 250, 175, 132, 157, 105, 132, 41, 239, 90, 30, 136,
+ 121, 130, 54, 195, 212, 14, 96, 69, 34, 165, 68, 200, 242,
+ 122, 122, 45, 184, 6, 99, 209, 108, 247, 202, 234, 86, 222,
+ 64, 92, 178, 33, 90, 69, 178, 194, 85, 102, 181, 90, 193,
+ 167, 72, 160, 112, 223, 200, 163, 42, 70, 149, 67, 208, 25,
+ 238, 251, 71 };
+ signature->sig.data = apr_pmemdup(p, rs256, sizeof(rs256));
+ signature->sig.len = sizeof(rs256);
+
+ return APR_SUCCESS;
+ }
+
+ /* es256 jws - https://tools.ietf.org/html/rfc7515#appendix-A.3 */
+ else if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "ES256",
+ alg->v->value.string.len)) {
+
+ const unsigned char es256[] = { 14, 209, 33, 83, 121, 99, 108, 72,
+ 60, 47, 127, 21, 88, 7, 212, 2, 163, 178, 40, 3, 58, 249,
+ 124, 126, 23, 129, 154, 195, 22, 158, 166, 101, 197, 10, 7,
+ 211, 140, 60, 112, 229, 216, 241, 45, 175, 8, 74, 84, 128,
+ 166, 101, 144, 197, 242, 147, 80, 154, 143, 63, 127, 138,
+ 131, 163, 84, 213 };
+ signature->sig.data = apr_pmemdup(p, es256, sizeof(es256));
+ signature->sig.len = sizeof(es256);
+
+ return APR_SUCCESS;
+ }
+
+ else {
+ apr_errprintf(&jose->result, jose->pool, NULL, 0,
+ "Header 'alg' not recognised: %.*s",
+ (int) alg->v->value.string.len, alg->v->value.string.p);
+ return APR_ENOTIMPL;
+ }
+
+ }
+
+ else {
+ apr_errprintf(&jose->result, jose->pool, NULL, 0,
+ "Header 'alg' missing");
+ return APR_ENOTIMPL;
+ }
+
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t verify_cb(apr_bucket_brigade *bb,
+ apr_jose_t *jose, apr_jose_signature_t *signature, void *ctx,
+ int *vflags, apr_pool_t *pool)
+{
+ abts_case *tc = ctx;
+ apr_json_kv_t *alg = NULL;
+
+ *vflags = APR_JOSE_FLAG_NONE;
+
+ if (signature) {
+ apr_json_value_t *ph = signature->protected_header;
+
+ ABTS_INT_EQUAL(tc, APR_JSON_OBJECT, ph->type);
+
+ alg = apr_json_object_get(ph, APR_JOSE_JWKSE_ALGORITHM,
+ APR_JSON_VALUE_STRING);
+ }
+
+ if (alg) {
+
+ ABTS_INT_EQUAL(tc, APR_JSON_STRING, alg->v->type);
+
+ /* unsecured jws/jwt */
+ if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "none",
+ alg->v->value.string.len)) {
+
+ if (!memcmp(signature->sig.data, (unsigned const char *) "",
+ signature->sig.len)) {
+ return APR_SUCCESS;
+ }
+ }
+
+ /* hs256 jws - https://tools.ietf.org/html/rfc7515#appendix-A.1 */
+ else if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "HS256",
+ alg->v->value.string.len)) {
+
+ const unsigned char hs256[] = { 116, 24, 223, 180, 151, 153, 224,
+ 37, 79, 250, 96, 125, 216, 173, 187, 186, 22, 212, 37, 77,
+ 105, 214, 191, 240, 91, 88, 5, 88, 83, 132, 141, 121 };
+
+ if (!memcmp(signature->sig.data, hs256, sizeof(hs256))) {
+ return APR_SUCCESS;
+ }
+
+ }
+
+ /* rs256 jws - https://tools.ietf.org/html/rfc7515#appendix-A.2 */
+ else if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "RS256",
+ alg->v->value.string.len)) {
+
+ const unsigned char rs256[] = { 112, 46, 33, 137, 67, 232, 143, 209,
+ 30, 181, 216, 45, 191, 120, 69, 243, 65, 6, 174, 27, 129,
+ 255, 247, 115, 17, 22, 173, 209, 113, 125, 131, 101, 109,
+ 66, 10, 253, 60, 150, 238, 221, 115, 162, 102, 62, 81, 102,
+ 104, 123, 0, 11, 135, 34, 110, 1, 135, 237, 16, 115, 249,
+ 69, 229, 130, 173, 252, 239, 22, 216, 90, 121, 142, 232,
+ 198, 109, 219, 61, 184, 151, 91, 23, 208, 148, 2, 190, 237,
+ 213, 217, 217, 112, 7, 16, 141, 178, 129, 96, 213, 248, 4,
+ 12, 167, 68, 87, 98, 184, 31, 190, 127, 249, 217, 46, 10,
+ 231, 111, 36, 242, 91, 51, 187, 230, 244, 74, 230, 30, 177,
+ 4, 10, 203, 32, 4, 77, 62, 249, 18, 142, 212, 1, 48, 121,
+ 91, 212, 189, 59, 65, 238, 202, 208, 102, 171, 101, 25, 129,
+ 253, 228, 141, 247, 127, 55, 45, 195, 139, 159, 175, 221,
+ 59, 239, 177, 139, 93, 163, 204, 60, 46, 176, 47, 158, 58,
+ 65, 214, 18, 202, 173, 21, 145, 18, 115, 160, 95, 35, 185,
+ 232, 56, 250, 175, 132, 157, 105, 132, 41, 239, 90, 30, 136,
+ 121, 130, 54, 195, 212, 14, 96, 69, 34, 165, 68, 200, 242,
+ 122, 122, 45, 184, 6, 99, 209, 108, 247, 202, 234, 86, 222,
+ 64, 92, 178, 33, 90, 69, 178, 194, 85, 102, 181, 90, 193,
+ 167, 72, 160, 112, 223, 200, 163, 42, 70, 149, 67, 208, 25,
+ 238, 251, 71 };
+
+ if (!memcmp(signature->sig.data, rs256, sizeof(rs256))) {
+ return APR_SUCCESS;
+ }
+
+ }
+
+ /* es256 jws - https://tools.ietf.org/html/rfc7515#appendix-A.3 */
+ else if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "ES256",
+ alg->v->value.string.len)) {
+
+ const unsigned char es256[] = { 14, 209, 33, 83, 121, 99, 108, 72,
+ 60, 47, 127, 21, 88, 7, 212, 2, 163, 178, 40, 3, 58, 249,
+ 124, 126, 23, 129, 154, 195, 22, 158, 166, 101, 197, 10, 7,
+ 211, 140, 60, 112, 229, 216, 241, 45, 175, 8, 74, 84, 128,
+ 166, 101, 144, 197, 242, 147, 80, 154, 143, 63, 127, 138,
+ 131, 163, 84, 213 };
+
+ if (!memcmp(signature->sig.data, es256, sizeof(es256))) {
+ return APR_SUCCESS;
+ }
+
+ return APR_SUCCESS;
+ }
+
+ else {
+ apr_errprintf(&jose->result, jose->pool, NULL, 0,
+ "Header 'alg' not recognised: %.*s",
+ (int) alg->v->value.string.len, alg->v->value.string.p);
+ return APR_ENOTIMPL;
+ }
+
+ }
+
+ else {
+ apr_errprintf(&jose->result, jose->pool, NULL, 0,
+ "Header 'alg' missing");
+ return APR_ENOTIMPL;
+ }
+
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t encrypt_cb(apr_bucket_brigade *brigade, apr_jose_t *jose,
+ apr_jose_recipient_t *recipient, apr_jose_encryption_t *encryption,
+ void *ctx, apr_pool_t *p)
+{
+ abts_case *tc = ctx;
+ apr_json_value_t *protected_header;
+ apr_json_value_t *header;
+ apr_json_kv_t *alg = NULL;
+
+ if (encryption) {
+
+ if (encryption->protected) {
+
+ protected_header = encryption->protected;
+ if (protected_header) {
+
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+
+ apr_bucket_brigade *bb = apr_brigade_create(p,
+ brigade->bucket_alloc);
+
+ apr_json_encode(bb, NULL, NULL, protected_header,
+ APR_JSON_FLAGS_WHITESPACE, p);
+
+ apr_brigade_flatten(bb, buf, &len);
+
+ /* RSAES-OAEP and AES GCM jwe - https://tools.ietf.org/html/rfc7516#appendix-A.1 */
+ if (!strncmp("{\"alg\":\"RSA-OAEP\",\"enc\":\"A256GCM\"}", buf, len)) {
+
+ const unsigned char iv[] = { 227, 197, 117, 252, 2, 219, 233,
+ 68, 180, 225, 77, 219 };
+
+ const unsigned char aad[] = { 101, 121, 74, 104, 98, 71, 99,
+ 105, 79, 105, 74, 83, 85, 48, 69, 116, 84, 48, 70, 70,
+ 85, 67, 73, 115, 73, 109, 86, 117, 89, 121, 73, 54, 73,
+ 107, 69, 121, 78, 84, 90, 72, 81, 48, 48, 105, 102, 81 };
+
+ const unsigned char cipher[] = { 229, 236, 166, 241, 53, 191,
+ 115, 196, 174, 43, 73, 109, 39, 122, 233, 96, 140, 206,
+ 120, 52, 51, 237, 48, 11, 190, 219, 186, 80, 111, 104,
+ 50, 142, 47, 167, 59, 61, 181, 127, 196, 21, 40, 82,
+ 242, 32, 123, 143, 168, 226, 73, 216, 176, 144, 138,
+ 247, 106, 60, 16, 205, 160, 109, 64, 63, 192 };
+
+ const unsigned char tag[] = { 92, 80, 104, 49, 133, 25, 161,
+ 215, 173, 101, 219, 211, 136, 91, 210, 145 };
+
+ encryption->iv.data = apr_pmemdup(p, iv, sizeof(iv));
+ encryption->iv.len = sizeof(iv);
+
+ encryption->aad.data = apr_pmemdup(p, aad, sizeof(aad));
+ encryption->aad.len = sizeof(aad);
+
+ encryption->cipher.data = apr_pmemdup(p, cipher, sizeof(cipher));
+ encryption->cipher.len = sizeof(cipher);
+
+ encryption->tag.data = apr_pmemdup(p, tag, sizeof(tag));
+ encryption->tag.len = sizeof(tag);
+
+ }
+
+ /* RSAES-PKCS1-v1_5 - https://tools.ietf.org/html/rfc7516#appendix-A.2 */
+ else if (!strncmp("{\"alg\":\"RSA1_5\",\"enc\":\"A128CBC-HS256\"}", buf, len)) {
+
+ const unsigned char iv[] = { 3, 22, 60, 12, 43, 67, 104, 105,
+ 108, 108, 105, 99, 111, 116, 104, 101 };
+
+ const unsigned char cipher[] = { 40, 57, 83, 181, 119, 33, 133,
+ 148, 198, 185, 243, 24, 152, 230, 6, 75, 129, 223, 127,
+ 19, 210, 82, 183, 230, 168, 33, 215, 104, 143, 112, 56,
+ 102 };
+
+ const unsigned char tag[] = { 246, 17, 244, 190, 4, 95, 98, 3,
+ 231, 0, 115, 157, 242, 203, 100, 191 };
+
+ encryption->iv.data = apr_pmemdup(p, iv, sizeof(iv));
+ encryption->iv.len = sizeof(iv);
+
+ encryption->cipher.data = apr_pmemdup(p, cipher, sizeof(cipher));
+ encryption->cipher.len = sizeof(cipher);
+
+ encryption->tag.data = apr_pmemdup(p, tag, sizeof(tag));
+ encryption->tag.len = sizeof(tag);
+
+ }
+
+ /* A128KW A128CBC-HS256 - https://tools.ietf.org/html/rfc7516#appendix-A.3 */
+ else if (!strncmp("{\"alg\":\"A128KW\",\"enc\":\"A128CBC-HS256\"}", buf, len)) {
+
+ const unsigned char iv[] = { 3, 22, 60, 12, 43, 67, 104, 105,
+ 108, 108, 105, 99, 111, 116, 104, 101 };
+
+ const unsigned char cipher[] = { 40, 57, 83, 181, 119, 33, 133,
+ 148, 198, 185, 243, 24, 152, 230, 6, 75, 129, 223, 127,
+ 19, 210, 82, 183, 230, 168, 33, 215, 104, 143, 112, 56,
+ 102 };
+
+ const unsigned char tag[] = { 83, 73, 191, 98, 104, 205, 211,
+ 128, 201, 189, 199, 133, 32, 38, 194, 85 };
+
+ encryption->iv.data = apr_pmemdup(p, iv, sizeof(iv));
+ encryption->iv.len = sizeof(iv);
+
+ encryption->cipher.data = apr_pmemdup(p, cipher, sizeof(cipher));
+ encryption->cipher.len = sizeof(cipher);
+
+ encryption->tag.data = apr_pmemdup(p, tag, sizeof(tag));
+ encryption->tag.len = sizeof(tag);
+
+ }
+
+ /* General JWE JSON - https://tools.ietf.org/html/rfc7516#appendix-A.4 */
+ else if (!strncmp("{\"enc\":\"A128CBC-HS256\"}", buf, len)) {
+
+ const unsigned char iv[] = { 3, 22, 60, 12, 43, 67, 104, 105,
+ 108, 108, 105, 99, 111, 116, 104, 101 };
+
+ const unsigned char cipher[] = { 40, 57, 83, 181, 119, 33, 133,
+ 148, 198, 185, 243, 24, 152, 230, 6, 75, 129, 223, 127,
+ 19, 210, 82, 183, 230, 168, 33, 215, 104, 143, 112, 56,
+ 102 };
+
+ const unsigned char tag[] = { 51, 63, 149, 60, 252, 148,
+ 225, 25, 92, 185, 139, 245, 35, 2, 47, 207 };
+
+ encryption->iv.data = apr_pmemdup(p, iv, sizeof(iv));
+ encryption->iv.len = sizeof(iv);
+
+ encryption->cipher.data = apr_pmemdup(p, cipher, sizeof(cipher));
+ encryption->cipher.len = sizeof(cipher);
+
+ encryption->tag.data = apr_pmemdup(p, tag, sizeof(tag));
+ encryption->tag.len = sizeof(tag);
+
+ }
+
+ else {
+ apr_errprintf(&jose->result, jose->pool, NULL, 0,
+ "Protected header not recognised: %.*s", (int)len, buf);
+ return APR_ENOTIMPL;
+ }
+
+
+ }
+ }
+
+
+ if (recipient) {
+ header = recipient->header;
+ if (header) {
+
+ ABTS_INT_EQUAL(tc, APR_JSON_OBJECT, header->type);
+
+ alg = apr_json_object_get(header, APR_JOSE_JWKSE_ALGORITHM,
+ APR_JSON_VALUE_STRING);
+ }
+ }
+
+ if (!alg) {
+ protected_header = encryption->protected;
+ if (protected_header) {
+
+ ABTS_INT_EQUAL(tc, APR_JSON_OBJECT, protected_header->type);
+
+ alg = apr_json_object_get(protected_header,
+ APR_JOSE_JWKSE_ALGORITHM, APR_JSON_VALUE_STRING);
+ }
+ }
+
+ if (alg && recipient) {
+
+ ABTS_INT_EQUAL(tc, APR_JSON_STRING, alg->v->type);
+
+ /* RSAES-OAEP and AES GCM jwe - https://tools.ietf.org/html/rfc7516#appendix-A.1 */
+ if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "RSA-OAEP",
+ alg->v->value.string.len)) {
+
+ const unsigned char ekey[] = { 56, 163, 154, 192, 58, 53, 222,
+ 4, 105, 218, 136, 218, 29, 94, 203, 22, 150, 92, 129,
+ 94, 211, 232, 53, 89, 41, 60, 138, 56, 196, 216, 82, 98,
+ 168, 76, 37, 73, 70, 7, 36, 8, 191, 100, 136, 196, 244,
+ 220, 145, 158, 138, 155, 4, 117, 141, 230, 199, 247,
+ 173, 45, 182, 214, 74, 177, 107, 211, 153, 11, 205, 196,
+ 171, 226, 162, 128, 171, 182, 13, 237, 239, 99, 193, 4,
+ 91, 219, 121, 223, 107, 167, 61, 119, 228, 173, 156,
+ 137, 134, 200, 80, 219, 74, 253, 56, 185, 91, 177, 34,
+ 158, 89, 154, 205, 96, 55, 18, 138, 43, 96, 218, 215,
+ 128, 124, 75, 138, 243, 85, 25, 109, 117, 140, 26, 155,
+ 249, 67, 167, 149, 231, 100, 6, 41, 65, 214, 251, 232,
+ 87, 72, 40, 182, 149, 154, 168, 31, 193, 126, 215, 89,
+ 28, 111, 219, 125, 182, 139, 235, 195, 197, 23, 234, 55,
+ 58, 63, 180, 68, 202, 206, 149, 75, 205, 248, 176, 67,
+ 39, 178, 60, 98, 193, 32, 238, 122, 96, 158, 222, 57,
+ 183, 111, 210, 55, 188, 215, 206, 180, 166, 150, 166,
+ 106, 250, 55, 229, 72, 40, 69, 214, 216, 104, 23, 40,
+ 135, 212, 28, 127, 41, 80, 175, 174, 168, 115, 171, 197,
+ 89, 116, 92, 103, 246, 83, 216, 182, 176, 84, 37, 147,
+ 35, 45, 219, 172, 99, 226, 233, 73, 37, 124, 42, 72, 49,
+ 242, 35, 127, 184, 134, 117, 114, 135, 206 };
+
+ recipient->ekey.data = apr_pmemdup(p, ekey, sizeof(ekey));
+ recipient->ekey.len = sizeof(ekey);
+
+ return APR_SUCCESS;
+ }
+
+ /* RSAES-PKCS1-v1_5 - https://tools.ietf.org/html/rfc7516#appendix-A.2 */
+ if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "RSA1_5",
+ alg->v->value.string.len)) {
+
+ const unsigned char ekey[] = { 80, 104, 72, 58, 11, 130, 236,
+ 139, 132, 189, 255, 205, 61, 86, 151, 176, 99, 40, 44,
+ 233, 176, 189, 205, 70, 202, 169, 72, 40, 226, 181, 156,
+ 223, 120, 156, 115, 232, 150, 209, 145, 133, 104, 112,
+ 237, 156, 116, 250, 65, 102, 212, 210, 103, 240, 177,
+ 61, 93, 40, 71, 231, 223, 226, 240, 157, 15, 31, 150,
+ 89, 200, 215, 198, 203, 108, 70, 117, 66, 212, 238, 193,
+ 205, 23, 161, 169, 218, 243, 203, 128, 214, 127, 253,
+ 215, 139, 43, 17, 135, 103, 179, 220, 28, 2, 212, 206,
+ 131, 158, 128, 66, 62, 240, 78, 186, 141, 125, 132, 227,
+ 60, 137, 43, 31, 152, 199, 54, 72, 34, 212, 115, 11,
+ 152, 101, 70, 42, 219, 233, 142, 66, 151, 250, 126, 146,
+ 141, 216, 190, 73, 50, 177, 146, 5, 52, 247, 28, 197,
+ 21, 59, 170, 247, 181, 89, 131, 241, 169, 182, 246, 99,
+ 15, 36, 102, 166, 182, 172, 197, 136, 230, 120, 60, 58,
+ 219, 243, 149, 94, 222, 150, 154, 194, 110, 227, 225,
+ 112, 39, 89, 233, 112, 207, 211, 241, 124, 174, 69, 221,
+ 179, 107, 196, 225, 127, 167, 112, 226, 12, 242, 16, 24,
+ 28, 120, 182, 244, 213, 244, 153, 194, 162, 69, 160,
+ 244, 248, 63, 165, 141, 4, 207, 249, 193, 79, 131, 0,
+ 169, 233, 127, 167, 101, 151, 125, 56, 112, 111, 248,
+ 29, 232, 90, 29, 147, 110, 169, 146, 114, 165, 204, 71,
+ 136, 41, 252 };
+
+ recipient->ekey.data = apr_pmemdup(p, ekey, sizeof(ekey));
+ recipient->ekey.len = sizeof(ekey);
+
+ return APR_SUCCESS;
+ }
+
+ /* A128KW A128CBC-HS256 - https://tools.ietf.org/html/rfc7516#appendix-A.3 */
+ if (alg->v->type == APR_JSON_STRING
+ && !strncmp(alg->v->value.string.p, "A128KW",
+ alg->v->value.string.len)) {
+
+ const unsigned char ekey[] = { 232, 160, 123, 211, 183, 76, 245,
+ 132, 200, 128, 123, 75, 190, 216, 22, 67, 201, 138, 193,
+ 186, 9, 91, 122, 31, 246, 90, 28, 139, 57, 3, 76, 124,
+ 193, 11, 98, 37, 173, 61, 104, 57 };
+
+ recipient->ekey.data = apr_pmemdup(p, ekey, sizeof(ekey));
+ recipient->ekey.len = sizeof(ekey);
+
+ return APR_SUCCESS;
+ }
+
+ }
+ }
+
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t decrypt_cb(apr_bucket_brigade *brigade, apr_jose_t *jose,
+ apr_jose_recipient_t *recipient, apr_jose_encryption_t *encryption,
+ apr_json_value_t *header, apr_jose_text_t *ph64, apr_jose_text_t *aad64,
+ void *ctx, int *dflags, apr_pool_t *pool)
+{
+
+ *dflags = APR_JOSE_FLAG_NONE;
+
+ if (encryption && recipient && header) {
+
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+
+ apr_bucket_brigade *bb = apr_brigade_create(p,
+ brigade->bucket_alloc);
+
+ apr_json_encode(bb, NULL, NULL, header,
+ APR_JSON_FLAGS_WHITESPACE, p);
+
+ apr_brigade_flatten(bb, buf, &len);
+
+ /* RSAES-OAEP and AES GCM jwe - https://tools.ietf.org/html/rfc7516#appendix-A.1 */
+ if (!strncmp("{\"alg\":\"RSA-OAEP\",\"enc\":\"A256GCM\"}", buf, len)) {
+
+ const char plaintext[] = { 84, 104, 101, 32, 116, 114, 117,
+ 101, 32, 115, 105, 103, 110, 32, 111, 102, 32, 105, 110,
+ 116, 101, 108, 108, 105, 103, 101, 110, 99, 101, 32, 105,
+ 115, 32, 110, 111, 116, 32, 107, 110, 111, 119, 108, 101,
+ 100, 103, 101, 32, 98, 117, 116, 32, 105, 109, 97, 103, 105,
+ 110, 97, 116, 105, 111, 110, 46 };
+
+ apr_brigade_write(brigade, NULL, NULL, plaintext, sizeof(plaintext));
+
+ return APR_SUCCESS;
+ }
+
+ /* RSAES-PKCS1-v1_5 - https://tools.ietf.org/html/rfc7516#appendix-A.2 */
+ else if (!strncmp("{\"jku\":\"https://server.example.com/keys.jwks\",\"enc\":\"A128CBC-HS256\",\"alg\":\"RSA1_5\",\"kid\":\"2011-04-29\"}", buf, len)) {
+
+ const char plaintext[] = { 76, 105, 118, 101, 32, 108, 111, 110,
+ 103, 32, 97, 110, 100, 32, 112, 114, 111, 115, 112, 101,
+ 114, 46 };
+
+ apr_brigade_write(brigade, NULL, NULL, plaintext, sizeof(plaintext));
+
+ return APR_SUCCESS;
+ }
+
+ /* Flattened JWE JSON - https://tools.ietf.org/html/rfc7516#appendix-A.5 */
+ else if (!strncmp("{\"jku\":\"https://server.example.com/keys.jwks\",\"enc\":\"A128CBC-HS256\",\"alg\":\"A128KW\",\"kid\":\"7\"}", buf, len)) {
+
+ const char plaintext[] = { 76, 105, 118, 101, 32, 108, 111, 110,
+ 103, 32, 97, 110, 100, 32, 112, 114, 111, 115, 112, 101,
+ 114, 46 };
+
+ apr_brigade_write(brigade, NULL, NULL, plaintext, sizeof(plaintext));
+
+ return APR_SUCCESS;
+ }
+
+
+ else {
+ apr_errprintf(&jose->result, pool, NULL, 0,
+ "Header not recognised: %.*s", (int)len, buf);
+ return APR_ENOTIMPL;
+ }
+
+ }
+
+ return APR_ENOTIMPL;
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7515#appendix-A.5
+ */
+static void test_jose_encode_jws_compact_unsecured(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_jose_t *jdata = NULL;
+ apr_jose_signature_t signature;
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+ apr_off_t offset;
+ apr_status_t status;
+
+ const char *ph = "{\"alg\":\"none\"}";
+ const unsigned char pl[] = {123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10,
+ 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56,
+ 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97,
+ 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111,
+ 111, 116, 34, 58, 116, 114, 117, 101, 125};
+ const char *expect = "eyJhbGciOiJub25lIn0"
+ "."
+ "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt"
+ "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ"
+ ".";
+
+ apr_jose_cb_t cb;
+
+ cb.sign = sign_cb;
+ cb.ctx = tc;
+
+ signature.header = NULL;
+ apr_json_decode(&signature.protected_header, ph, APR_JSON_VALUE_STRING, &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_jose_data_make(&jdata, "JWT", pl, sizeof(pl), p);
+ apr_jose_jws_make(&jose, &signature, NULL, jdata, p);
+
+ status = apr_jose_encode(bb, NULL, NULL, jose, &cb, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+
+ apr_brigade_flatten(bb, buf, &len);
+ ABTS_STR_NEQUAL(tc, expect, buf, len);
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7515#appendix-A.1
+ */
+static void test_jose_encode_jws_compact_hs256(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_jose_t *jdata = NULL;
+ apr_jose_signature_t signature;
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+ apr_off_t offset;
+ apr_status_t status;
+
+ const unsigned char ph[] = { 123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84,
+ 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53,
+ 54, 34, 125 };
+
+ const unsigned char pl[] = {123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10,
+ 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56,
+ 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97,
+ 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111,
+ 111, 116, 34, 58, 116, 114, 117, 101, 125};
+ const char *expect = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9"
+ "."
+ "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt"
+ "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ"
+ "."
+ "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
+
+ apr_jose_cb_t cb;
+
+ cb.sign = sign_cb;
+ cb.ctx = tc;
+
+ signature.header = NULL;
+ apr_json_decode(&signature.protected_header, (const char *) ph, sizeof(ph), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_jose_data_make(&jdata, "JWT", pl, sizeof(pl), p);
+ apr_jose_jws_make(&jose, &signature, NULL, jdata, p);
+
+ status = apr_jose_encode(bb, NULL, NULL, jose, &cb, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+
+ apr_brigade_flatten(bb, buf, &len);
+ ABTS_STR_NEQUAL(tc, expect, buf, len);
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7515#appendix-A.6
+ */
+static void test_jose_encode_jws_json_general(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_jose_t *jdata = NULL;
+ apr_jose_signature_t **signature;
+ apr_jose_signature_t signature1;
+ apr_jose_signature_t signature2;
+ apr_array_header_t *signatures = apr_array_make(p, 2,
+ sizeof(apr_jose_signature_t *));
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+ apr_off_t offset;
+ apr_status_t status;
+
+ const unsigned char pl[] = { 123, 34, 105, 115, 115, 34, 58, 34, 106, 111,
+ 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48,
+ 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58,
+ 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105,
+ 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125 };
+
+ const char *s1h = "{\"kid\":\"2010-12-29\"}";
+ const char *s1ph = "{\"alg\":\"RS256\"}";
+ const char *s2h = "{\"kid\":\"e9bc097a-ce51-4036-9562-d2ade882db0d\"}";
+ const char *s2ph = "{\"alg\":\"ES256\"}";
+
+ const char *expect = "{"
+ "\"payload\":"
+ "\"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF"
+ "tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ\","
+ "\"signatures\":["
+ "{\"protected\":\"eyJhbGciOiJSUzI1NiJ9\","
+ "\"header\":"
+ "{\"kid\":\"2010-12-29\"},"
+ "\"signature\":"
+ "\"cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ"
+ "mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb"
+ "KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl"
+ "b1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES"
+ "c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX"
+ "LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw\"},"
+ "{\"protected\":\"eyJhbGciOiJFUzI1NiJ9\","
+ "\"header\":"
+ "{\"kid\":\"e9bc097a-ce51-4036-9562-d2ade882db0d\"},"
+ "\"signature\":"
+ "\"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS"
+ "lSApmWQxfKTUJqPP3-Kg6NU1Q\"}]"
+ "}";
+
+ apr_jose_cb_t cb;
+
+ cb.sign = sign_cb;
+ cb.ctx = tc;
+
+ apr_json_decode(&signature1.header, (const char *) s1h, strlen(s1h), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+ apr_json_decode(&signature1.protected_header, (const char *) s1ph, strlen(s1ph), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+ apr_json_decode(&signature2.header, (const char *) s2h, strlen(s2h), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+ apr_json_decode(&signature2.protected_header, (const char *) s2ph, strlen(s2ph), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ signature = apr_array_push(signatures);
+ *signature = &signature1;
+ signature = apr_array_push(signatures);
+ *signature = &signature2;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_jose_data_make(&jdata, "JWT", pl, sizeof(pl), p);
+ apr_jose_jws_json_make(&jose, NULL, signatures, jdata, p);
+
+ status = apr_jose_encode(bb, NULL, NULL, jose, &cb, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+
+ apr_brigade_flatten(bb, buf, &len);
+ ABTS_STR_NEQUAL(tc, expect, buf, len);
+
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7515#appendix-A.7
+ */
+static void test_jose_encode_jws_json_flattened(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_jose_t *jdata = NULL;
+ apr_jose_signature_t signature2;
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+ apr_off_t offset;
+ apr_status_t status;
+
+ const unsigned char pl[] = { 123, 34, 105, 115, 115, 34, 58, 34, 106, 111,
+ 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48,
+ 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58,
+ 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105,
+ 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125 };
+
+ const char *s2h = "{\"kid\":\"e9bc097a-ce51-4036-9562-d2ade882db0d\"}";
+ const char *s2ph = "{\"alg\":\"ES256\"}";
+
+ const char *expect = "{"
+ "\"payload\":"
+ "\"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF"
+ "tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ\","
+ "\"protected\":\"eyJhbGciOiJFUzI1NiJ9\","
+ "\"header\":"
+ "{\"kid\":\"e9bc097a-ce51-4036-9562-d2ade882db0d\"},"
+ "\"signature\":"
+ "\"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS"
+ "lSApmWQxfKTUJqPP3-Kg6NU1Q\""
+ "}";
+
+ apr_jose_cb_t cb;
+
+ cb.sign = sign_cb;
+ cb.ctx = tc;
+
+ apr_json_decode(&signature2.header, (const char *) s2h, strlen(s2h), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+ apr_json_decode(&signature2.protected_header, (const char *) s2ph, strlen(s2ph), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_jose_data_make(&jdata, "JWT", pl, sizeof(pl), p);
+ apr_jose_jws_json_make(&jose, &signature2, NULL, jdata, p);
+
+ status = apr_jose_encode(bb, NULL, NULL, jose, &cb, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+
+ apr_brigade_flatten(bb, buf, &len);
+ ABTS_STR_NEQUAL(tc, expect, buf, len);
+
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7516#appendix-A.1
+ */
+static void test_jose_encode_jwe_compact_rsaes_oaep_aes_gcm(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_jose_t *jdata = NULL;
+ apr_jose_encryption_t *encryption;
+ apr_jose_recipient_t *recipient;
+ apr_json_value_t *header = NULL;
+ apr_json_value_t *protected_header = NULL;
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+ apr_off_t offset;
+ apr_status_t status;
+
+ const char *ph = "{\"alg\":\"RSA-OAEP\",\"enc\":\"A256GCM\"}";
+
+ const unsigned char pl[] = { 84, 104, 101, 32, 116, 114, 117, 101, 32, 115,
+ 105, 103, 110, 32, 111, 102, 32, 105, 110, 116, 101, 108, 108, 105,
+ 103, 101, 110, 99, 101, 32, 105, 115, 32, 110, 111, 116, 32, 107,
+ 110, 111, 119, 108, 101, 100, 103, 101, 32, 98, 117, 116, 32, 105,
+ 109, 97, 103, 105, 110, 97, 116, 105, 111, 110, 46 };
+
+ const char *expect = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ."
+ "OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe"
+ "ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb"
+ "Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV"
+ "mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8"
+ "1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi"
+ "6UklfCpIMfIjf7iGdXKHzg."
+ "48V1_ALb6US04U3b."
+ "5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji"
+ "SdiwkIr3ajwQzaBtQD_A."
+ "XFBoMYUZodetZdvTiFvSkQ";
+
+ apr_jose_cb_t cb;
+
+ cb.encrypt = encrypt_cb;
+ cb.ctx = tc;
+
+ apr_json_decode(&protected_header, ph, APR_JSON_VALUE_STRING, &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_jose_data_make(&jdata, "JWT", pl, sizeof(pl), p);
+ apr_jose_recipient_make(&recipient, header, p);
+ apr_jose_encryption_make(&encryption, NULL, protected_header, p);
+ apr_jose_jwe_make(&jose, recipient, NULL, encryption, jdata, p);
+
+ status = apr_jose_encode(bb, NULL, NULL, jose, &cb, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+
+ apr_brigade_flatten(bb, buf, &len);
+ ABTS_STR_NEQUAL(tc, expect, buf, len);
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7516#appendix-A.4
+ */
+static void test_jose_encode_jwe_json_general(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_jose_t *jdata = NULL;
+ apr_json_value_t *header = NULL;
+ apr_json_value_t *protected_header = NULL;
+ apr_jose_recipient_t **recipient;
+ apr_jose_recipient_t recipient1;
+ apr_jose_recipient_t recipient2;
+ apr_array_header_t *recipients = apr_array_make(p, 2,
+ sizeof(apr_jose_recipient_t *));
+ apr_jose_encryption_t *encryption;
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+ apr_off_t offset;
+ apr_status_t status;
+
+ const char *r1h = "{\"alg\":\"RSA1_5\",\"kid\":\"2011-04-29\"}";
+ const char *r2h = "{\"alg\":\"A128KW\",\"kid\":\"7\"}";
+
+ const char *ph = "{\"enc\":\"A128CBC-HS256\"}";
+ const char *h = "{\"jku\":\"https://server.example.com/keys.jwks\"}";
+
+ const unsigned char pl[] = { 76, 105, 118, 101, 32, 108, 111, 110, 103, 32,
+ 97, 110, 100, 32, 112, 114, 111, 115, 112, 101, 114, 46 };
+
+ const char *expect = "{"
+ "\"protected\":"
+ "\"eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0\","
+ "\"unprotected\":"
+ "{\"jku\":\"https://server.example.com/keys.jwks\"},"
+ "\"recipients\":["
+ "{\"header\":"
+ "{\"alg\":\"RSA1_5\",\"kid\":\"2011-04-29\"},"
+ "\"encrypted_key\":"
+ "\"UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-"
+ "kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKx"
+ "GHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3"
+ "YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPh"
+ "cCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPg"
+ "wCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A\"},"
+ "{\"header\":"
+ "{\"alg\":\"A128KW\",\"kid\":\"7\"},"
+ "\"encrypted_key\":"
+ "\"6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ\"}],"
+ "\"iv\":"
+ "\"AxY8DCtDaGlsbGljb3RoZQ\","
+ "\"ciphertext\":"
+ "\"KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY\","
+ "\"tag\":"
+ "\"Mz-VPPyU4RlcuYv1IwIvzw\""
+ "}\";";
+
+ apr_jose_cb_t cb;
+
+ cb.encrypt = encrypt_cb;
+ cb.ctx = tc;
+
+ apr_json_decode(&recipient1.header, (const char *) r1h, strlen(r1h), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+ apr_json_decode(&recipient2.header, (const char *) r2h, strlen(r2h), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ recipient = apr_array_push(recipients);
+ *recipient = &recipient1;
+ recipient = apr_array_push(recipients);
+ *recipient = &recipient2;
+
+
+
+
+ apr_json_decode(&header, h, APR_JSON_VALUE_STRING, &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+ apr_json_decode(&protected_header, ph, APR_JSON_VALUE_STRING, &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_jose_data_make(&jdata, "plain", pl, sizeof(pl), p);
+ apr_jose_encryption_make(&encryption, header, protected_header, p);
+ apr_jose_jwe_json_make(&jose, NULL, recipients, encryption, jdata, p);
+
+ status = apr_jose_encode(bb, NULL, NULL, jose, &cb, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+
+ apr_brigade_flatten(bb, buf, &len);
+ ABTS_STR_NEQUAL(tc, expect, buf, len);
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7516#appendix-A.5
+ */
+static void test_jose_encode_jwe_json_flattened(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_jose_t *jdata = NULL;
+ apr_json_value_t *header = NULL;
+ apr_json_value_t *protected_header = NULL;
+ apr_jose_recipient_t recipient;
+ apr_jose_encryption_t *encryption;
+ char buf[1024];
+ apr_size_t len = sizeof(buf);
+ apr_off_t offset;
+ apr_status_t status;
+
+ const char *rh = "{\"alg\":\"A128KW\",\"kid\":\"7\"}";
+
+ const char *ph = "{\"enc\":\"A128CBC-HS256\"}";
+ const char *h = "{\"jku\":\"https://server.example.com/keys.jwks\"}";
+
+ const unsigned char pl[] = { 76, 105, 118, 101, 32, 108, 111, 110, 103, 32,
+ 97, 110, 100, 32, 112, 114, 111, 115, 112, 101, 114, 46 };
+
+ const char *expect = "{"
+ "\"protected\":"
+ "\"eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0\","
+ "\"unprotected\":"
+ "{\"jku\":\"https://server.example.com/keys.jwks\"},"
+ "\"header\":"
+ "{\"alg\":\"A128KW\",\"kid\":\"7\"},"
+ "\"encrypted_key\":"
+ "\"6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ\","
+ "\"iv\":"
+ "\"AxY8DCtDaGlsbGljb3RoZQ\","
+ "\"ciphertext\":"
+ "\"KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY\","
+ "\"tag\":"
+ "\"Mz-VPPyU4RlcuYv1IwIvzw\""
+ "}";
+
+ apr_jose_cb_t cb;
+
+ cb.encrypt = encrypt_cb;
+ cb.ctx = tc;
+
+ apr_json_decode(&recipient.header, (const char *) rh, strlen(rh), &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ apr_json_decode(&header, h, APR_JSON_VALUE_STRING, &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+ apr_json_decode(&protected_header, ph, APR_JSON_VALUE_STRING, &offset,
+ APR_JSON_FLAGS_WHITESPACE, 10, p);
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_jose_data_make(&jdata, "plain", pl, sizeof(pl), p);
+ apr_jose_encryption_make(&encryption, header, protected_header, p);
+ apr_jose_jwe_json_make(&jose, &recipient, NULL, encryption, jdata, p);
+
+ status = apr_jose_encode(bb, NULL, NULL, jose, &cb, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+
+ apr_brigade_flatten(bb, buf, &len);
+ ABTS_STR_NEQUAL(tc, expect, buf, len);
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7515#appendix-A.5
+ */
+static void test_jose_decode_jws_compact_unsecured(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_json_kv_t *kv;
+ apr_status_t status;
+
+ const char *source = "eyJhbGciOiJub25lIn0"
+ "."
+ "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt"
+ "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ"
+ ".";
+
+ apr_jose_cb_t cb;
+
+ cb.verify = verify_cb;
+ cb.decrypt = decrypt_cb;
+ cb.ctx = tc;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_brigade_write(bb, NULL, NULL, source, strlen(source));
+
+ status = apr_jose_decode(&jose, "JWT", bb, &cb, 10, APR_JOSE_FLAG_NONE, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+ ABTS_PTR_NOTNULL(tc, jose);
+ ABTS_INT_EQUAL(tc, APR_JOSE_TYPE_JWT, jose->type);
+
+ kv = apr_json_object_get(jose->jose.jwt->claims, "iss",
+ APR_JSON_VALUE_STRING);
+ ABTS_PTR_NOTNULL(tc, kv);
+ ABTS_INT_EQUAL(tc, APR_JSON_STRING, kv->v->type);
+
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7515#appendix-A.1
+ */
+static void test_jose_decode_jws_compact_hs256(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_json_kv_t *kv;
+ apr_status_t status;
+
+ const char *source = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9"
+ "."
+ "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt"
+ "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ"
+ "."
+ "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
+
+ apr_jose_cb_t cb;
+
+ cb.verify = verify_cb;
+ cb.decrypt = decrypt_cb;
+ cb.ctx = tc;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_brigade_write(bb, NULL, NULL, source, strlen(source));
+
+ status = apr_jose_decode(&jose, "JWT", bb, &cb, 10, APR_JOSE_FLAG_NONE, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+ ABTS_PTR_NOTNULL(tc, jose);
+ ABTS_INT_EQUAL(tc, APR_JOSE_TYPE_JWT, jose->type);
+
+ kv = apr_json_object_get(jose->jose.jwt->claims, "iss",
+ APR_JSON_VALUE_STRING);
+ ABTS_PTR_NOTNULL(tc, kv);
+ ABTS_INT_EQUAL(tc, APR_JSON_STRING, kv->v->type);
+
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7515#appendix-A.6
+ */
+static void test_jose_decode_jws_json_general(abts_case *tc, void *data)
+{
+ const char *source = "{"
+ "\"payload\":"
+ "\"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF"
+ "tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ\","
+ "\"signatures\":["
+ "{\"protected\":\"eyJhbGciOiJSUzI1NiJ9\","
+ "\"header\":"
+ "{\"kid\":\"2010-12-29\"},"
+ "\"signature\":"
+ "\"cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ"
+ "mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb"
+ "KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl"
+ "b1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES"
+ "c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX"
+ "LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw\"},"
+ "{\"protected\":\"eyJhbGciOiJFUzI1NiJ9\","
+ "\"header\":"
+ "{\"kid\":\"e9bc097a-ce51-4036-9562-d2ade882db0d\"},"
+ "\"signature\":"
+ "\"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS"
+ "lSApmWQxfKTUJqPP3-Kg6NU1Q\"}]"
+ "}";
+
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_status_t status;
+
+ apr_jose_cb_t cb;
+
+ cb.verify = verify_cb;
+ cb.decrypt = decrypt_cb;
+ cb.ctx = tc;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_brigade_write(bb, NULL, NULL, source, strlen(source));
+
+ status = apr_jose_decode(&jose, "JOSE+JSON", bb, &cb, 10, APR_JOSE_FLAG_NONE, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+ ABTS_PTR_NOTNULL(tc, jose);
+
+ /*
+ * There is nothing in this structure to identify the MIME type of the payload,
+ * so raw data is returned.
+ */
+ ABTS_INT_EQUAL(tc, APR_JOSE_TYPE_DATA, jose->type);
+
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7515#appendix-A.7
+ */
+static void test_jose_decode_jws_json_flattened(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_status_t status;
+
+ const char *source = "{"
+ "\"payload\":"
+ "\"eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF"
+ "tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ\","
+ "\"protected\":\"eyJhbGciOiJFUzI1NiJ9\","
+ "\"header\":"
+ "{\"kid\":\"e9bc097a-ce51-4036-9562-d2ade882db0d\"},"
+ "\"signature\":"
+ "\"DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS"
+ "lSApmWQxfKTUJqPP3-Kg6NU1Q\""
+ "}";
+
+ apr_jose_cb_t cb;
+
+ cb.verify = verify_cb;
+ cb.decrypt = decrypt_cb;
+ cb.ctx = tc;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_brigade_write(bb, NULL, NULL, source, strlen(source));
+
+ status = apr_jose_decode(&jose, "JOSE+JSON", bb, &cb, 10, APR_JOSE_FLAG_NONE, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+ ABTS_PTR_NOTNULL(tc, jose);
+ ABTS_INT_EQUAL(tc, APR_JOSE_TYPE_DATA, jose->type);
+
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7516#appendix-A.1
+ */
+static void test_jose_decode_jwe_compact_rsaes_oaep_aes_gcm(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_status_t status;
+
+ const char *source = "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ."
+ "OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe"
+ "ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb"
+ "Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV"
+ "mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8"
+ "1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi"
+ "6UklfCpIMfIjf7iGdXKHzg."
+ "48V1_ALb6US04U3b."
+ "5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji"
+ "SdiwkIr3ajwQzaBtQD_A."
+ "XFBoMYUZodetZdvTiFvSkQ";
+
+ apr_jose_cb_t cb;
+
+ cb.verify = verify_cb;
+ cb.decrypt = decrypt_cb;
+ cb.ctx = tc;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_brigade_write(bb, NULL, NULL, source, strlen(source));
+
+ status = apr_jose_decode(&jose, "JWE", bb, &cb, 10, APR_JOSE_FLAG_NONE, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+ ABTS_PTR_NOTNULL(tc, jose);
+ ABTS_INT_EQUAL(tc, APR_JOSE_TYPE_DATA, jose->type);
+
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7516#appendix-A.4
+ */
+static void test_jose_decode_jwe_json_general(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_status_t status;
+
+ const char *source = "{"
+ "\"protected\":"
+ "\"eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0\","
+ "\"unprotected\":"
+ "{\"jku\":\"https://server.example.com/keys.jwks\"},"
+ "\"recipients\":["
+ "{\"header\":"
+ "{\"alg\":\"RSA1_5\",\"kid\":\"2011-04-29\"},"
+ "\"encrypted_key\":"
+ "\"UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-"
+ "kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKx"
+ "GHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3"
+ "YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPh"
+ "cCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPg"
+ "wCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A\"},"
+ "{\"header\":"
+ "{\"alg\":\"A128KW\",\"kid\":\"7\"},"
+ "\"encrypted_key\":"
+ "\"6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ\"}],"
+ "\"iv\":"
+ "\"AxY8DCtDaGlsbGljb3RoZQ\","
+ "\"ciphertext\":"
+ "\"KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY\","
+ "\"tag\":"
+ "\"Mz-VPPyU4RlcuYv1IwIvzw\""
+ "}";
+
+ apr_jose_cb_t cb;
+
+ cb.verify = verify_cb;
+ cb.decrypt = decrypt_cb;
+ cb.ctx = tc;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_brigade_write(bb, NULL, NULL, source, strlen(source));
+
+ status = apr_jose_decode(&jose, "JOSE+JSON", bb, &cb, 10,
+ APR_JOSE_FLAG_NONE, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+ ABTS_PTR_NOTNULL(tc, jose);
+ ABTS_INT_EQUAL(tc, APR_JOSE_TYPE_DATA, jose->type);
+
+}
+
+/**
+ * Test from https://tools.ietf.org/html/rfc7516#appendix-A.5
+ */
+static void test_jose_decode_jwe_json_flattened(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_jose_t *jose = NULL;
+ apr_status_t status;
+
+ const char *source = "{"
+ "\"protected\":"
+ "\"eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0\","
+ "\"unprotected\":"
+ "{\"jku\":\"https://server.example.com/keys.jwks\"},"
+ "\"header\":"
+ "{\"alg\":\"A128KW\",\"kid\":\"7\"},"
+ "\"encrypted_key\":"
+ "\"6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ\","
+ "\"iv\":"
+ "\"AxY8DCtDaGlsbGljb3RoZQ\","
+ "\"ciphertext\":"
+ "\"KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY\","
+ "\"tag\":"
+ "\"Mz-VPPyU4RlcuYv1IwIvzw\""
+ "}";
+
+ apr_jose_cb_t cb;
+
+ cb.verify = verify_cb;
+ cb.decrypt = decrypt_cb;
+ cb.ctx = tc;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ apr_brigade_write(bb, NULL, NULL, source, strlen(source));
+
+ status = apr_jose_decode(&jose, "JOSE+JSON", bb, &cb, 10,
+ APR_JOSE_FLAG_NONE, p);
+
+ ABTS_INT_EQUAL(tc, APR_SUCCESS, status);
+ ABTS_PTR_NOTNULL(tc, jose);
+ ABTS_INT_EQUAL(tc, APR_JOSE_TYPE_DATA, jose->type);
+
+}
+
+abts_suite *testjose(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ abts_run_test(suite, test_jose_decode_jws_compact_unsecured, NULL);
+ abts_run_test(suite, test_jose_decode_jws_compact_hs256, NULL);
+ abts_run_test(suite, test_jose_decode_jws_json_general, NULL);
+ abts_run_test(suite, test_jose_decode_jws_json_flattened, NULL);
+ abts_run_test(suite, test_jose_decode_jwe_compact_rsaes_oaep_aes_gcm, NULL);
+ abts_run_test(suite, test_jose_decode_jwe_json_general, NULL);
+ abts_run_test(suite, test_jose_decode_jwe_json_flattened, NULL);
+
+ abts_run_test(suite, test_jose_encode_jws_compact_unsecured, NULL);
+ abts_run_test(suite, test_jose_encode_jws_compact_hs256, NULL);
+ abts_run_test(suite, test_jose_encode_jws_json_general, NULL);
+ abts_run_test(suite, test_jose_encode_jws_json_flattened, NULL);
+ abts_run_test(suite, test_jose_encode_jwe_compact_rsaes_oaep_aes_gcm, NULL);
+ abts_run_test(suite, test_jose_encode_jwe_json_general, NULL);
+ abts_run_test(suite, test_jose_encode_jwe_json_flattened, NULL);
+
+ return suite;
+}