summaryrefslogtreecommitdiff
path: root/include/apr_jose.h
blob: 59d0dcac7a0b74fc756db946a939824c0e3f142b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
/* 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.
 */
/**
 * @file apr_jose.h
 * @brief APR-UTIL JSON Object Signing and Encryption Library
 */
#ifndef APR_JOSE_H
#define APR_JOSE_H

/**
 * @defgroup APR_Util_JOSE JSON Object Signing and Encryption
 * @ingroup APR_Util
 * @{
 *
 * The JOSE (JSON Object Signing and Encryption) library allows the encoding
 * and decoding of JWS (JSON Web Signature), JWE (JSON Web Encryption), JWK
 * (JSON Web Key) and JWT (JSON Web Token) objects, encoded using compact
 * encoding, JSON encoding, or flattened JSON encoding.
 *
 * The following RFCs are supported:
 *
 * - https://tools.ietf.org/html/rfc7515 - JSON Web Signature (JWS)
 * - https://tools.ietf.org/html/rfc7516 - JSON Web Encryption (JWE)
 * - https://tools.ietf.org/html/rfc7517 - JSON Web Key (JWK)
 * - https://tools.ietf.org/html/rfc7519 - JSON Web Token (JWT)
 *
 * Encryption, decryption, signing and verification are implemented as
 * callbacks to the caller's specification, and are not included.
 *
 * When decrypting or verifying, the caller MUST verify that the 'alg'
 * algorithm parameter in the JOSE message matches the algorithm expected
 * by the implementation.
 *
 * It is recommended that the apr_crypto library be used to implement the
 * callbacks, however an alternatively crypto library of the caller's choice
 * may be used instead.
 */
#include "apr.h"
#include "apr_pools.h"
#include "apu_errno.h"
#include "apr_strings.h"
#include "apr_buckets.h"
#include "apr_json.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @package Apache JOSE library
 *
 */

/**
 * HMAC using SHA-256
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_HS256 "HS256"

/**
 * HMAC using SHA-384
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_HS384 "HS384"

/**
 * HMAC using SHA-512
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_HS512 "HS512"

/**
 * RSASSA-PKCS1-v1_5 using SHA-256
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_RS256 "RS256"

/**
 * RSASSA-PKCS1-v1_5 using SHA-384
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_RS384 "RS384"

/**
 * RSASSA-PKCS1-v1_5 using SHA-512
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_RS512 "RS512"

/**
 * ECDSA using P-256 and SHA-256
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_ES256 "ES256"

/**
 * ECDSA using P-384 and SHA-384
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_ES384 "ES384"

/**
 * ECDSA using P-512 and SHA-512
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_ES512 "ES512"

/**
 * RSASSA-PSS using SHA-256 and MGF1 with SHA-256
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_PS256 "PS256"

/**
 * RSASSA-PSS using SHA-384 and MGF1 with SHA-384
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_PS384 "PS384"

/**
 * RSASSA-PSS using SHA-512 and MGF1 with SHA-512
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_PS512 "PS512"

/**
 * No digital signature or MAC performed
 *
 * https://tools.ietf.org/html/rfc7518#section-3.1
 */
#define APR_JOSE_JWA_NONE "none"

/**
 * "kty" (Key Type) Parameter
 *
 * https://tools.ietf.org/html/rfc7517#section-4.1
 */
#define APR_JOSE_JWK_KEY_TYPE "kty"

/**
 * "use" (Public Key Use) Parameter
 *
 * https://tools.ietf.org/html/rfc7517#section-4.2
 */
#define APR_JOSE_JWK_PUBLIC_KEY_USE "use"

/**
 * "key_ops" (Key Operations) Parameter
 *
 * https://tools.ietf.org/html/rfc7517#section-4.3
 */
#define APR_JOSE_JWK_KEY_OPERATIONS "key_ops"

/**
 * "keys" Parameter
 *
 * https://tools.ietf.org/html/rfc7517#section-5.1
 */
#define APR_JOSE_JWK_KEYS "keys"

/**
 * "alg" (Algorithm) Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.1
 * https://tools.ietf.org/html/rfc7516#section-4.1.1
 * https://tools.ietf.org/html/rfc7517#section-4.4
 */
#define APR_JOSE_JWKSE_ALGORITHM "alg"

/**
 * "enc" (Encryption Algorithm) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-4.1.2
 */
#define APR_JOSE_JWE_ENCRYPTION "enc"

/**
 * "zip" (Compression Algorithm) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-4.1.3
 */
#define APR_JOSE_JWE_COMPRESSION "zip"

/**
 * "jku" (JWK Set URL) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.2
 * https://tools.ietf.org/html/rfc7516#section-4.1.4
 */
#define APR_JOSE_JWSE_JWK_SET_URL "jku"

/**
 * "jwk" (JSON Web Key) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.3
 * https://tools.ietf.org/html/rfc7516#section-4.1.5
 */
#define APR_JOSE_JWSE_JWK "jwk"

/**
 * "kid" (Key ID) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.4
 * https://tools.ietf.org/html/rfc7516#section-4.1.6
 */
#define APR_JOSE_JWKSE_KEYID "kid"

/**
 * "x5u" (X.509 URL) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.5
 * https://tools.ietf.org/html/rfc7516#section-4.1.7
 */
#define APR_JOSE_JWKSE_X509_URL "x5u"

/**
 * "x5c" (X.509 Certificate Chain) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.6
 * https://tools.ietf.org/html/rfc7516#section-4.1.8
 */
#define APR_JOSE_JWKSE_X509_CHAIN "x5c"

/**
 * "x5t" (X.509 Certificate SHA-1 Thumbprint) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.7
 * https://tools.ietf.org/html/rfc7516#section-4.1.9
 */
#define APR_JOSE_JWKSE_X509_SHA1_THUMBPRINT "x5t"

/**
 *"x5t#S256" (X.509 Certificate SHA-256 Thumbprint) Header
 * Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.8
 * https://tools.ietf.org/html/rfc7516#section-4.1.10
 */
#define APR_JOSE_JWKSE_X509_SHA256_THUMBPRINT "x5t#S256"

/**
 * "typ" (Type) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.9
 * https://tools.ietf.org/html/rfc7516#section-4.1.11
 */
#define APR_JOSE_JWSE_TYPE "typ"

/**
 * "cty" (Content Type) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.10
 * https://tools.ietf.org/html/rfc7516#section-4.1.12
 */
#define APR_JOSE_JWSE_CONTENT_TYPE "cty"

/**
 * "crit" (Critical) Header Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-4.1.11
 * https://tools.ietf.org/html/rfc7516#section-4.1.13
 */
#define APR_JOSE_JWSE_CRITICAL "crit"

/**
 * "payload" Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-7.2.1
 */
#define APR_JOSE_JWS_PAYLOAD "payload"

/**
 * "signatures" Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-7.2.1
 */
#define APR_JOSE_JWS_SIGNATURES "signatures"

/**
 * "protected" Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-7.2.1
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWSE_PROTECTED "protected"

/**
 * "header" Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-7.2.1
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWSE_HEADER "header"

/**
 * "signature" Parameter
 *
 * https://tools.ietf.org/html/rfc7515#section-7.2.1
 */
#define APR_JOSE_JWS_SIGNATURE "signature"

/**
 * "unprotected" Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWE_UNPROTECTED "unprotected"

/**
 * "ciphertext" Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWE_CIPHERTEXT "ciphertext"

/**
 * "recipients" Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWE_RECIPIENTS "recipients"

/**
 * "encrypted_key" Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWE_EKEY "encrypted_key"

/**
 * "iv" Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWE_IV "iv"

/**
 * "tag" Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWE_TAG "tag"

/**
 * "aad" Parameter
 *
 * https://tools.ietf.org/html/rfc7516#section-7.2.1
 */
#define APR_JOSE_JWE_AAD "aad"

/**
 * "iss" (Issuer) Claim
 *
 * https://tools.ietf.org/html/rfc7519#section-4.1.1
 */
#define APR_JOSE_JWT_ISSUER "iss"

/**
 * "sub" (Subject) Claim
 *
 * https://tools.ietf.org/html/rfc7519#section-4.1.2
 */
#define APR_JOSE_JWT_SUBJECT "sub"

/**
 * "aud" (Audience) Claim
 *
 * https://tools.ietf.org/html/rfc7519#section-4.1.3
 */
#define APR_JOSE_JWT_AUDIENCE "aud"

/**
 * "exp" (Expiration Time) Claim
 *
 * https://tools.ietf.org/html/rfc7519#section-4.1.4
 */
#define APR_JOSE_JWT_EXPIRATION_TIME "exp"

/**
 * "nbf" (Not Before) Claim
 *
 * https://tools.ietf.org/html/rfc7519#section-4.1.5
 */
#define APR_JOSE_JWT_NOT_BEFORE "nbf"

/**
 * "iat" (Issued At) Claim
 *
 * https://tools.ietf.org/html/rfc7519#section-4.1.6
 */
#define APR_JOSE_JWT_ISSUED_AT "iat"

/**
 * "jti" (JWT ID) Claim
 *
 * https://tools.ietf.org/html/rfc7519#section-4.1.7
 */
#define APR_JOSE_JWT_ID "jti"

/**
 * "typ" (Type) Header Parameter representing a JWT
 *
 * https://tools.ietf.org/html/rfc7519#section-5.1
 */
#define APR_JOSE_JWSE_TYPE_JWT "JWT"

/**
 * Default options.
 */
#define APR_JOSE_FLAG_NONE    0

/**
 * Return the full JOSE structure, instead of innermost nested structure.
 */
#define APR_JOSE_FLAG_DECODE_ALL    1

/**
 * When verifying or decrypting, break out of processing.
 *
 * If the verification or decryption failed, processing will be aborted
 * with the given error.
 *
 * If the verification or decryption succeeded, processing will be considered
 * successful and will move on to the nested structure.
 */
#define APR_JOSE_FLAG_BREAK    2

/**
 * Forward declaration of the apr_jose_t structure.
 */
typedef struct apr_jose_t apr_jose_t;

/**
 * Enum that represents the type of JOSE object.
 */
typedef enum apr_jose_type_e {
    /** No specific type. */
    APR_JOSE_TYPE_NONE = 0,
    /** JSON Web Key (JWK) */
    APR_JOSE_TYPE_JWK = 1,
    /** JSON Web Key Set (JWKS) */
    APR_JOSE_TYPE_JWKS,
    /** JSON Web Signature (JWS) - compact encoding */
    APR_JOSE_TYPE_JWS,
    /** JSON Web Signature (JWS) - JSON encoding */
    APR_JOSE_TYPE_JWS_JSON,
    /** JSON Web Encryption (JWE) - compact encoding */
    APR_JOSE_TYPE_JWE,
    /** JSON Web Encryption (JWE) - JSON encoding */
    APR_JOSE_TYPE_JWE_JSON,
    /** JSON Web Token (JWT) */
    APR_JOSE_TYPE_JWT,
    /** Generic binary data */
    APR_JOSE_TYPE_DATA,
    /** Generic text data */
    APR_JOSE_TYPE_TEXT,
    /** Generic JSON structure */
    APR_JOSE_TYPE_JSON
} apr_jose_type_e;

/**
 * Unsigned char data of a given length
 */
typedef struct apr_jose_data_t {
    /** Pointer to the data */
    const unsigned char *data;
    /** Length of the data */
    apr_size_t len;
} apr_jose_data_t;

/**
 * Signed char data of a given length
 */
typedef struct apr_jose_text_t {
    /** Pointer to the text */
    const char *text;
    /** Length of the text */
    apr_size_t len;
} apr_jose_text_t;

/**
 * JSON object
 */
typedef struct apr_jose_json_t {
    /** Parsed JSON structure. */
    apr_json_value_t *json;
} apr_jose_json_t;

/**
 * A JSON web key
 */
typedef struct apr_jose_jwk_t {
    /** Parsed JWK JSON structure */
    apr_json_value_t *key;
} apr_jose_jwk_t;

/**
 * A JSON web key set
 */
typedef struct apr_jose_jwks_t {
    /** Parsed JWK set JSON structure containing a JSON array */
    apr_json_value_t *keys;
} apr_jose_jwks_t;

/**
 * A single signature within a a JSON web signature.
 */
typedef struct apr_jose_signature_t {
    /** JWS Header */
    apr_json_value_t *header;
    /** JWS Protected Header */
    apr_json_value_t *protected_header;
    /** JWS Signature */
    apr_jose_data_t sig;
    /** Result of verification for this signature */
    apr_status_t status;
} apr_jose_signature_t;

/**
 * A JSON web signature
 */
typedef struct apr_jose_jws_t {
    /** JWS Compact / Flattened Signature */
    apr_jose_signature_t *signature;
    /** JWS General Signatures */
    apr_array_header_t *signatures;
    /** JWS Payload */
    apr_jose_t *payload;
} apr_jose_jws_t;

/**
 * An encrypted payload within a a JSON web encryption.
 */
typedef struct apr_jose_encryption_t {
    /** JWE Shared Header */
    apr_json_value_t *unprotected;
    /** JWE Protected Header */
    apr_json_value_t *protected;
    /** JWE Protected Header (basde64url) */
    apr_jose_text_t protected64;
    /** JWE Initialization Vector */
    apr_jose_data_t iv;
    /** JWE AAD */
    apr_jose_data_t aad;
    /** JWE AAD (base64url)*/
    apr_jose_text_t aad64;
    /** JWE Ciphertext */
    apr_jose_data_t cipher;
    /** JWE Authentication Tag */
    apr_jose_data_t tag;
} apr_jose_encryption_t;

/**
 * A single recipient within a a JSON web encryption.
 */
typedef struct apr_jose_recipient_t {
    /** JWE Header */
    apr_json_value_t *header;
    /** JWE Encrypted Key */
    apr_jose_data_t ekey;
    /** Result of decryption for this recipient */
    apr_status_t status;
} apr_jose_recipient_t;

/**
 * A JSON web encryption
 */
typedef struct apr_jose_jwe_t {
    /** JWE Compact / Flattened Recipient */
    apr_jose_recipient_t *recipient;
    /** JWE General Recipients */
    apr_array_header_t *recipients;
    /** JWE Encryption Parameters */
    apr_jose_encryption_t *encryption;
    /** JWE Payload */
    apr_jose_t *payload;
} apr_jose_jwe_t;

/**
 * A JSON web token
 */
typedef struct apr_jose_jwt_t {
    /** Claims associated with the JWT. */
    apr_json_value_t *claims;
} apr_jose_jwt_t;

/**
 * One JOSE structure to rule them all.
 */
struct apr_jose_t {
    /** pool used for allocation */
    apr_pool_t *pool;
    /** content type of this structure */
    const char *typ;
    /** content type of the payload */
    const char *cty;
    /** result of the operation */
    apu_err_t result;
    /** type of the value */
    apr_jose_type_e type;
    /** actual value, depending on the type */
    union {
        apr_jose_jwk_t *jwk;
        apr_jose_jwks_t *jwks;
        apr_jose_jws_t *jws;
        apr_jose_jwe_t *jwe;
        apr_jose_jwt_t *jwt;
        apr_jose_data_t *data;
        apr_jose_text_t *text;
        apr_jose_json_t *json;
    } jose;
};

/**
 * Callbacks for encryption, decryption, signing and verifying.
 */
typedef struct apr_jose_cb_t {
    /**
     * Callback that encrypts the content of the bucket brigade bb based
     * on the parameters provided by the jwe->protected_header, and writes
     * the resulting encrypted key to recipient->ekey, the initialisation vector
     * to encryption->iv, the additional authentication data to encryption->aad, the
     * cipher text to encryption->cipher, and the tag to encryption->tag.
     *
     * The encrypt function is expected to perform some or all of the
     * following steps:
     *
     *    1.   Determine the Key Management Mode employed by the algorithm used
     *         to determine the Content Encryption Key value.  (This is the
     *         algorithm recorded in the "alg" (algorithm) Header Parameter of
     *         the resulting JWE.)
     *
     *    2.   When Key Wrapping, Key Encryption, or Key Agreement with Key
     *         Wrapping are employed, generate a random CEK value.  See RFC
     *         4086 [RFC4086] for considerations on generating random values.
     *         The CEK MUST have a length equal to that required for the
     *         content encryption algorithm.
     *
     *    3.   When Direct Key Agreement or Key Agreement with Key Wrapping are
     *         employed, use the key agreement algorithm to compute the value
     *         of the agreed upon key.  When Direct Key Agreement is employed,
     *         let the CEK be the agreed upon key.  When Key Agreement with Key
     *         Wrapping is employed, the agreed upon key will be used to wrap
     *         the CEK.
     *
     *    4.   When Key Wrapping, Key Encryption, or Key Agreement with Key
     *         Wrapping are employed, encrypt the CEK to the recipient and let
     *         the result be the JWE Encrypted Key.
     *
     *    5.   When Direct Key Agreement or Direct Encryption are employed, let
     *         the JWE Encrypted Key be the empty octet sequence.
     *
     *    6.   When Direct Encryption is employed, let the CEK be the shared
     *         symmetric key.
     *
     *    8.   If the JWE JSON Serialization is being used, repeat this process
     *         (steps 1-7) for each recipient.
     *
     *    9.   Generate a random JWE Initialization Vector of the correct size
     *         for the content encryption algorithm (if required for the
     *         algorithm); otherwise, let the JWE Initialization Vector be the
     *         empty octet sequence.
     *
     *    11.  If a "zip" parameter was included, compress the plaintext using
     *         the specified compression algorithm and let M be the octet
     *         sequence representing the compressed plaintext; otherwise, let M
     *         be the octet sequence representing the plaintext.
     *
     *    12.  Create the JSON object(s) containing the desired set of Header
     *         Parameters, which together comprise the JOSE Header: one or more
     *         of the JWE Protected Header, the JWE Shared Unprotected Header,
     *         and the JWE Per-Recipient Unprotected Header.
     *
     *    13.  Compute the Encoded Protected Header value BASE64URL(UTF8(JWE
     *         Protected Header)).  If the JWE Protected Header is not present
     *         (which can only happen when using the JWE JSON Serialization and
     *         no "protected" member is present), let this value be the empty
     *         string.
     *
     *    14.  Let the Additional Authenticated Data encryption parameter be
     *         ASCII(Encoded Protected Header).  However, if a JWE AAD value is
     *         present (which can only be the case when using the JWE JSON
     *         Serialization), instead let the Additional Authenticated Data
     *         encryption parameter be ASCII(Encoded Protected Header || '.' ||
     *         BASE64URL(JWE AAD)).
     *
     *    15.  Encrypt M using the CEK, the JWE Initialization Vector, and the
     *         Additional Authenticated Data value using the specified content
     *         encryption algorithm to create the JWE Ciphertext value and the
     *         JWE Authentication Tag (which is the Authentication Tag output
     *         from the encryption operation).
     *
     * @param bb Brigade containing data to be encrypted.
     * @param jose The JOSE structure.
     * @param recipient Structure containing details of the recipient of
     *   this message.
     * @param encryption Structure to be filled out by the callback
     *   containing the encrypted message.
     * @param ctx A context.
     * @param pool The pool to use.
     * @return APR_SUCCESS if encrypted successfully, APR_ENOTIMPL if
     *   encryption is not supported, or any other suitable error. The
     *   jose->result structure may be filled out with further details of
     *   any error.
     */
    apr_status_t (*encrypt)(apr_bucket_brigade *bb, apr_jose_t *jose,
            apr_jose_recipient_t *recipient, apr_jose_encryption_t *encryption,
            void *ctx, apr_pool_t *pool);
    /**
     * Callback that decrypts the ciphertext based
     * on the parameters provided by the recipient and encryption parameters, and writes
     * the resulting decrypted value to the bucket brigade. Base64url versions of the
     * protected header and the aad are provided as part of the JWE decryption
     * mechanism.
     *
     * For security reasons, this callback MUST verify that the algorithm
     * present in the JWE matches the algorithm expected by the decoder.
     *
     * The decrypt function is expected to perform some or all of the
     * following steps:
     *
     * 6.   Determine the Key Management Mode employed by the algorithm
     * specified by the "alg" (algorithm) Header Parameter.
     *
     * 7.   Verify that the JWE uses a key known to the recipient.
     *
     * 8.   When Direct Key Agreement or Key Agreement with Key Wrapping are
     *      employed, use the key agreement algorithm to compute the value
     *      of the agreed upon key.  When Direct Key Agreement is employed,
     *      let the CEK be the agreed upon key.  When Key Agreement with Key
     *      Wrapping is employed, the agreed upon key will be used to
     *      decrypt the JWE Encrypted Key.
     *
     * 9.   When Key Wrapping, Key Encryption, or Key Agreement with Key
     *      Wrapping are employed, decrypt the JWE Encrypted Key to produce
     *      the CEK.  The CEK MUST have a length equal to that required for
     *      the content encryption algorithm.  Note that when there are
     *       multiple recipients, each recipient will only be able to decrypt
     *       JWE Encrypted Key values that were encrypted to a key in that
     *       recipient's possession.  It is therefore normal to only be able
     *       to decrypt one of the per-recipient JWE Encrypted Key values to
     *       obtain the CEK value.  Also, see Section 11.5 for security
     *       considerations on mitigating timing attacks.
     *
     *  10.  When Direct Key Agreement or Direct Encryption are employed,
     *       verify that the JWE Encrypted Key value is an empty octet
     *       sequence.
     *
     *  11.  When Direct Encryption is employed, let the CEK be the shared
     *       symmetric key.
     *
     *  12.  Record whether the CEK could be successfully determined for this
     *       recipient or not.
     *
     *  13.  If the JWE JSON Serialization is being used, repeat this process
     *       (steps 4-12) for each recipient contained in the representation.
     *
     *  14.  Compute the Encoded Protected Header value BASE64URL(UTF8(JWE
     *       Protected Header)).  If the JWE Protected Header is not present
     *       (which can only happen when using the JWE JSON Serialization and
     *       no "protected" member is present), let this value be the empty
     *       string.
     *
     *  15.  Let the Additional Authenticated Data encryption parameter be
     *       ASCII(Encoded Protected Header).  However, if a JWE AAD value is
     *       present (which can only be the case when using the JWE JSON
     *       Serialization), instead let the Additional Authenticated Data
     *       encryption parameter be ASCII(Encoded Protected Header || '.' ||
     *       BASE64URL(JWE AAD)).
     *
     *  16.  Decrypt the JWE Ciphertext using the CEK, the JWE Initialization
     *       Vector, the Additional Authenticated Data value, and the JWE
     *       Authentication Tag (which is the Authentication Tag input to the
     *       calculation) using the specified content encryption algorithm,
     *       returning the decrypted plaintext and validating the JWE
     *       Authentication Tag in the manner specified for the algorithm,
     *       rejecting the input without emitting any decrypted output if the
     *       JWE Authentication Tag is incorrect.
     *
     *  17.  If a "zip" parameter was included, uncompress the decrypted
     *       plaintext using the specified compression algorithm.
     *
     * @param bb Brigade where decrypted data is to be written.
     * @param jose The JOSE structure.
     * @param recipient Structure containing details of the recipient of
     *   this message, to be used to decrypt the message.
     * @param encryption Structure containing the encrypted message.
     * @param header The JOSE protected header.
     * @param p64 The JOSE protected header in original BASE64URL format,
     *   for use during decryption.
     * @param aad64 The JOSE additional authenticated data in original
     *   BASE64URL format, for use during decryption.
     * @param ctx A context.
     * @param dflags A pointer to a flag. Set to APR_JOSE_FLAG_NONE for
     *   decryption to continue to the next recipient in the JWE, or
     *   APR_JOSE_FLAG_BREAK to stop decrypting further recipients.
     * @param pool The pool to use.
     * @return APR_SUCCESS if decrypted successfully, APR_ENOTIMPL if
     *   decryption is not supported, or any other suitable error. The
     *   jose->result structure may be filled out with further details of
     *   any error.
     */
    apr_status_t (*decrypt)(apr_bucket_brigade *bb, 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);
    /**
     * Callback that signs the content of the bucket brigade bb based
     * on the parameters provided by the signature protected header, and writes
     * the resulting binary signature to signature->sig.
     *
     * The sign function is expected to perform some or all of the
     * following steps:
     *
     *    5.  Compute the JWS Signature in the manner defined for the
     *        particular algorithm being used over the JWS Signing Input
     *        ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' ||
     *        BASE64URL(JWS Payload)).  The "alg" (algorithm) Header Parameter
     *        MUST be present in the JOSE Header, with the algorithm value
     *        accurately representing the algorithm used to construct the JWS
     *        Signature.
     *
     * @param bb Brigade containing data to be signed.
     * @param jose The JOSE structure.
     * @param signature Structure to be filled out by the callback
     *   containing the signature of the message.
     * @param ctx A context.
     * @param pool The pool to use.
     * @return APR_SUCCESS if signed successfully, APR_ENOTIMPL if
     *   signing is not supported, or any other suitable error. The
     *   jose->result structure may be filled out with further details of
     *   any error.
     */
    apr_status_t (*sign)(apr_bucket_brigade *bb, apr_jose_t *jose,
            apr_jose_signature_t *signature, void *ctx, apr_pool_t *pool);
    /**
     * Callback that verifies the content of the bucket brigade bb based
     * on the parameters provided by the signature protected header and
     * signature->sig.
     *
     * For security reasons, this callback MUST verify that the algorithm
     * present in the JWS matches the algorithm expected by the decoder.
     *
     * The verify function is expected to perform some or all of the
     * following steps:
     *
     *   8.  Validate the JWS Signature against the JWS Signing Input
     *       ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' ||
     *       BASE64URL(JWS Payload)) in the manner defined for the algorithm
     *       being used, which MUST be accurately represented by the value of
     *       the "alg" (algorithm) Header Parameter, which MUST be present.
     *       See Section 10.6 for security considerations on algorithm
     *       validation.  Record whether the validation succeeded or not.
     *
     *   9.  If the JWS JSON Serialization is being used, repeat this process
     *       (steps 4-8) for each digital signature or MAC value contained in
     *       the representation.
     *
     *   10. If none of the validations in step 9 succeeded, then the JWS MUST
     *       be considered invalid.  Otherwise, in the JWS JSON Serialization
     *       case, return a result to the application indicating which of the
     *       validations succeeded and failed.  In the JWS Compact
     *       Serialization case, the result can simply indicate whether or not
     *       the JWS was successfully validated.
     *
     * @param bb Brigade containing data to be verified.
     * @param jose The JOSE structure.
     * @param signature Structure containing the signature to be verified.
     * @param ctx A context.
     * @param dflags A pointer to a flag. Set to APR_JOSE_FLAG_NONE for
     *   verification to continue to the next recipient in the JWE, or
     *   APR_JOSE_FLAG_BREAK to stop verifying further recipients.
     * @param pool The pool to use.
     * @return APR_SUCCESS if verified successfully, APR_ENOTIMPL if
     *   verification is not supported, or any other suitable error. The
     *   jose->result structure may be filled out with further details of
     *   any error.
     */
    apr_status_t (*verify)(apr_bucket_brigade *bb, apr_jose_t *jose,
            apr_jose_signature_t *signature, void *ctx, int *vflags,
            apr_pool_t *pool);
    /** Context to be passed to the callback. */
    void *ctx;
} apr_jose_cb_t;

/**
 * @brief Get the result of the last operation on the jose. If the result
 *        is NULL, the operation was successful.
 * @param jose - context pointer
 * @return The apu_err_t is returned.
 */
APR_DECLARE(apu_err_t *) apr_jose_error(apr_jose_t *jose)
        __attribute__((nonnull(1)));

/**
 * Make a generic JOSE structure.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param type the type of structure to create.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_make(apr_jose_t *jose, apr_jose_type_e type,
        apr_pool_t *pool)
        __attribute__((nonnull(3)));

/**
 * Make a JSON Web Key for encoding or decoding.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param key the json representing the key. May be NULL.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_jwk_make(apr_jose_t *jose,
        apr_json_value_t *key, apr_pool_t *pool)
        __attribute__((nonnull(3)));

/**
 * Make a JSON Web Key Set.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param keys the array of keys in JSON format. May be NULL.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_jwks_make(apr_jose_t *jose,
        apr_json_value_t *keys, apr_pool_t *pool)
        __attribute__((nonnull(3)));

/**
 * Make a signature structure for JWS.
 *
 * @param signature the result.
 * @param header the unprotected header.
 * @param protected the protected header.
 * @param pool the pool to use.
 * @return The apr_jose_signature_t is returned.
 */
APR_DECLARE(apr_jose_signature_t *) apr_jose_signature_make(
        apr_jose_signature_t *signature, apr_json_value_t *header,
        apr_json_value_t *protected, apr_pool_t *pool)
        __attribute__((nonnull(4)));

/**
 * Make a recipient structure for JWE.
 *
 * @param recipient the result.
 * @param unprotected the unprotected header.
 * @param pool the pool to use.
 * @return The apr_jose_recipient_t is returned.
 */
APR_DECLARE(apr_jose_recipient_t *) apr_jose_recipient_make(apr_jose_recipient_t *recipient,
        apr_json_value_t *unprotected, apr_pool_t *pool)
        __attribute__((nonnull(3)));

/**
 * Make an encryption structure for JWE.
 *
 * @param encryption the result.
 * @param unprotected the unprotected shared header.
 * @param protected the protected header.
 * @param pool the pool to use.
 * @return The apr_jose_encryption_t is returned.
 */
APR_DECLARE(apr_jose_encryption_t *) apr_jose_encryption_make(apr_jose_encryption_t *encryption,
        apr_json_value_t *unprotected, apr_json_value_t *protected,
        apr_pool_t *pool)
        __attribute__((nonnull(4)));

/**
 * Make a compact encoded JWE.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param recipient the recipient for compact / flattened JWE.
 * @param recipients the recipients array for general JWE.
 * @param encryption the encryption structure.
 * @param payload the JOSE payload to encrypt.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_jwe_make(apr_jose_t *jose,
        apr_jose_recipient_t *recipient, apr_array_header_t *recipients,
        apr_jose_encryption_t *encryption, apr_jose_t *payload,
        apr_pool_t *pool)
        __attribute__((nonnull(6)));

/**
 * Make a JSON encoded JWE.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param recipient the recipient for compact / flattened JWE.
 * @param recipients the recipients array for general JWE.
 * @param encryption the encryption structure.
 * @param payload the JOSE payload to encrypt.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_jwe_json_make(apr_jose_t *jose,
        apr_jose_recipient_t *recipient,
        apr_array_header_t *recipients, apr_jose_encryption_t *encryption,
        apr_jose_t *payload, apr_pool_t *pool)
        __attribute__((nonnull(6)));

/**
 * Make a compact encoded JWS.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param signature the header / protected header / signature used with compact or flattened syntax. May be NULL.
 * @param signatures array of header / protected header / signature used with general JSON syntax.
 * @param payload the payload to be wrapped by this JWS.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_jws_make(apr_jose_t *jose,
        apr_jose_signature_t *signature, apr_array_header_t *signatures,
        apr_jose_t *payload, apr_pool_t *pool)
        __attribute__((nonnull(5)));

/**
 * Make a JSON encoded JWS.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param signature the header / protected header / signature used with compact or flattened syntax. May be NULL.
 * @param signatures array of header / protected header / signature used with general JSON syntax.
 * @param payload the payload to be wrapped by this JWS.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_jws_json_make(apr_jose_t *jose,
        apr_jose_signature_t *signature, apr_array_header_t *signatures,
        apr_jose_t *payload, apr_pool_t *pool)
        __attribute__((nonnull(5)));

/**
 * Make a JWT claims payload.
 *
 * To create a useful JWT, this payload needs to be wrapped in a JWS
 * or JWE (or both), as required by the caller.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param claims the claims to sign.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_jwt_make(apr_jose_t *jose,
        apr_json_value_t *claims, apr_pool_t *pool)
        __attribute__((nonnull(3)));

/**
 * Make a data buffer for encoding from the given data and length.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param typ the content type of this data.
 * @param in the plaintext to sign.
 * @param inlen length of the plaintext.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_data_make(apr_jose_t *jose, const char *typ,
        const unsigned char *in, apr_size_t inlen, apr_pool_t *pool)
        __attribute__((nonnull(5)));

/**
 * Make a UTF-8 text buffer for encoding from the given string
 * and length.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param cty the content type.
 * @param in the UTF-8 encoded text string.
 * @param inlen length of the UTF-8 encoded text string.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_text_make(apr_jose_t *jose, const char *cty,
        const char *in, apr_size_t inlen, apr_pool_t *pool)
        __attribute__((nonnull(5)));

/**
 * Make a json structure for encoding.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param cty the content type.
 * @param json the json object to add.
 * @param pool pool used to allocate the result from.
 * @return The apr_jose_t is returned.
 */
APR_DECLARE(apr_jose_t *) apr_jose_json_make(apr_jose_t *jose, const char *cty,
        apr_json_value_t *json, apr_pool_t *pool)
        __attribute__((nonnull(4)));

/**
 * Sign or encrypt the apr_jose_t, and write it to the brigade.
 * @param brigade brigade the result will be appended to.
 * @param flush The flush function to use if the brigade is full
 * @param ctx The structure to pass to the flush function
 * @param jose the JOSE to encode.
 * @param cb callbacks for sign and encrypt.
 * @param pool pool to be used.
 * @return APR_SUCCESS is returned if encoding was successful, otherwise
 * an APR status code, along with an apu_err_t with an explanation
 * allocated from jose->pool.
 */
APR_DECLARE(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)
		__attribute__((nonnull(1, 4, 6)));

/**
 * Decode, decrypt and verify the utf8-encoded JOSE string into apr_jose_t.
 *
 * The JOSE structure may be nested to the given limit.
 * @param jose If jose points at NULL, a JOSE structure will be
 *   created. If the jose pointer is not NULL, the structure will
 *   be reused.
 * @param typ content type of this object.
 * @param brigade the JOSE structure to decode.
 * @param cb callbacks for verify and decrypt.
 * @param level depth limit of JOSE and JSON nesting.
 * @param flags APR_JOSE_FLAG_NONE to return payload only. APR_JOSE_FLAG_DECODE_ALL
 *   to return the full JWS/JWE structure.
 * @param pool pool used to allocate the result from.
 */
APR_DECLARE(apr_status_t) apr_jose_decode(apr_jose_t **jose, const char *typ,
        apr_bucket_brigade *brigade, apr_jose_cb_t *cb, int level, int flags,
        apr_pool_t *pool)
        __attribute__((nonnull(1, 3, 7)));


#ifdef __cplusplus
}
#endif
/** @} */
#endif /* APR_JOSE_H */