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