mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 08:48:39 +09:00
625 lines
30 KiB
C
625 lines
30 KiB
C
#ifndef ECE_H
|
|
#define ECE_H
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#define ECE_SALT_LENGTH 16
|
|
#define ECE_TAG_LENGTH 16
|
|
#define ECE_WEBPUSH_PRIVATE_KEY_LENGTH 32
|
|
#define ECE_WEBPUSH_PUBLIC_KEY_LENGTH 65
|
|
#define ECE_WEBPUSH_AUTH_SECRET_LENGTH 16
|
|
|
|
#define ECE_AES128GCM_MIN_RS 18
|
|
#define ECE_AES128GCM_HEADER_LENGTH 21
|
|
#define ECE_AES128GCM_MAX_KEY_ID_LENGTH 255
|
|
#define ECE_AES128GCM_PAD_SIZE 1
|
|
|
|
#define ECE_AESGCM_MIN_RS 3
|
|
#define ECE_AESGCM_PAD_SIZE 2
|
|
|
|
#define ECE_OK 0
|
|
#define ECE_ERROR_OUT_OF_MEMORY -1
|
|
#define ECE_ERROR_INVALID_PRIVATE_KEY -2
|
|
#define ECE_ERROR_INVALID_PUBLIC_KEY -3
|
|
#define ECE_ERROR_COMPUTE_SECRET -4
|
|
#define ECE_ERROR_ENCODE_PUBLIC_KEY -5
|
|
#define ECE_ERROR_DECRYPT -6
|
|
#define ECE_ERROR_DECRYPT_PADDING -7
|
|
#define ECE_ERROR_ZERO_PLAINTEXT -8
|
|
#define ECE_ERROR_SHORT_BLOCK -9
|
|
#define ECE_ERROR_SHORT_HEADER -10
|
|
#define ECE_ERROR_ZERO_CIPHERTEXT -11
|
|
#define ECE_ERROR_HKDF -12
|
|
#define ECE_ERROR_INVALID_ENCRYPTION_HEADER -13
|
|
#define ECE_ERROR_INVALID_CRYPTO_KEY_HEADER -14
|
|
#define ECE_ERROR_INVALID_RS -15
|
|
#define ECE_ERROR_INVALID_SALT -16
|
|
#define ECE_ERROR_INVALID_DH -17
|
|
#define ECE_ERROR_ENCRYPT -18
|
|
#define ECE_ERROR_ENCRYPT_PADDING -19
|
|
#define ECE_ERROR_INVALID_AUTH_SECRET -20
|
|
#define ECE_ERROR_GENERATE_KEYS -21
|
|
#define ECE_ERROR_DECRYPT_TRUNCATED -22
|
|
|
|
// Annotates a variable or parameter as unused to avoid compiler warnings.
|
|
#define ECE_UNUSED(x) (void) (x)
|
|
|
|
/*!
|
|
* The policy for appending trailing "=" characters to Base64url-encoded output.
|
|
*/
|
|
typedef enum ece_base64url_encode_policy_e {
|
|
/*! Omits padding, even if the input is not a multiple of 4. */
|
|
ECE_BASE64URL_OMIT_PADDING,
|
|
|
|
/*! Includes padding if the input is not a multiple of 4. */
|
|
ECE_BASE64URL_INCLUDE_PADDING,
|
|
} ece_base64url_encode_policy_t;
|
|
|
|
/*!
|
|
* The policy for handling trailing "=" characters in Base64url-encoded input.
|
|
*/
|
|
typedef enum ece_base64url_decode_policy_e {
|
|
/*!
|
|
* Fails decoding if the input is unpadded. RFC 4648, section 3.2 requires
|
|
* padding, unless the referring specification prohibits it.
|
|
*/
|
|
ECE_BASE64URL_REQUIRE_PADDING,
|
|
|
|
/*! Tolerates padded and unpadded input. */
|
|
ECE_BASE64URL_IGNORE_PADDING,
|
|
|
|
/*!
|
|
* Fails decoding if the input is padded. This follows the strict Base64url
|
|
* variant used in JWS (RFC 7515, Appendix C) and
|
|
* draft-ietf-httpbis-encryption-encoding-03. */
|
|
ECE_BASE64URL_REJECT_PADDING,
|
|
} ece_base64url_decode_policy_t;
|
|
|
|
/*!
|
|
* Generates a public-private ECDH key pair and authentication secret for a Web
|
|
* Push subscription.
|
|
*
|
|
* \sa ece_webpush_aes128gcm_decrypt(),
|
|
* ece_webpush_aesgcm_decrypt()
|
|
*
|
|
* \param rawRecvPrivKey[in] The subscription private key. This key should
|
|
* be stored locally, and used to decrypt incoming
|
|
* messages.
|
|
* \param rawRecvPrivKeyLen[in] The length of the subscription private key. Must
|
|
* be `ECE_WEBPUSH_PRIVATE_KEY_LENGTH`.
|
|
* \param rawRecvPubKey[in] The subscription public key, in uncompressed
|
|
* form. This key should be shared with the app
|
|
* server, and used to encrypt outgoing messages.
|
|
* \param rawRecvPubKeyLen[in] The length of the subscription public key. Must
|
|
* be `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param authSecret[in] The authentication secret. This secret should
|
|
* be stored locally and shared with the app
|
|
* server. It's used to derive the content
|
|
* encryption key and nonce.
|
|
* \param authSecretLen[in] The length of the authentication secret. Must
|
|
* be `ECE_WEBPUSH_AUTH_SECRET_LENGTH`.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if key
|
|
* generation fails.
|
|
*/
|
|
int
|
|
ece_webpush_generate_keys(uint8_t* rawRecvPrivKey, size_t rawRecvPrivKeyLen,
|
|
uint8_t* rawRecvPubKey, size_t rawRecvPubKeyLen,
|
|
uint8_t* authSecret, size_t authSecretLen);
|
|
|
|
/*!
|
|
* Calculates the maximum "aes128gcm" plaintext length. The caller should
|
|
* allocate and pass an array of this length to the "aes128gcm" decryption
|
|
* functions.
|
|
*
|
|
* \sa ece_aes128gcm_decrypt(),
|
|
* ece_webpush_aes128gcm_decrypt()
|
|
*
|
|
* \param payload[in] The encrypted payload.
|
|
* \param payloadLen[in] The length of the encrypted payload.
|
|
*
|
|
* \return The maximum plaintext length, or 0 if the payload
|
|
* header is truncated or invalid.
|
|
*/
|
|
size_t
|
|
ece_aes128gcm_plaintext_max_length(const uint8_t* payload, size_t payloadLen);
|
|
|
|
/*!
|
|
* Decrypts a message encrypted using the "aes128gcm" scheme, with a symmetric
|
|
* key. The key is shared out of band, and identified by the `keyId` parameter
|
|
* in the payload header.
|
|
*
|
|
* \sa ece_aes128gcm_plaintext_max_length(),
|
|
* ece_aes128gcm_payload_extract_params()
|
|
*
|
|
* \param ikm[in] The input keying material (IKM) for the content
|
|
* encryption key and nonce.
|
|
* \param ikmLen[in] The length of the IKM.
|
|
* \param payload[in] The encrypted payload.
|
|
* \param payloadLen[in] The length of the encrypted payload.
|
|
* \param plaintext[in] An empty array. Must be large enough to hold the
|
|
* full plaintext.
|
|
* \param plaintextLen[in,out] The input is the length of the empty `plaintext`
|
|
* array. On success, the output is set to the
|
|
* actual plaintext length, and
|
|
* `[0..plaintextLen]` contains the plaintext.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if
|
|
* the payload is empty or malformed.
|
|
*/
|
|
int
|
|
ece_aes128gcm_decrypt(const uint8_t* ikm, size_t ikmLen, const uint8_t* payload,
|
|
size_t payloadLen, uint8_t* plaintext,
|
|
size_t* plaintextLen);
|
|
|
|
/*!
|
|
* Decrypts a Web Push message encrypted using the "aes128gcm" scheme.
|
|
*
|
|
* \sa ece_aes128gcm_plaintext_max_length()
|
|
*
|
|
* \param rawRecvPrivKey[in] The subscription private key.
|
|
* \param rawRecvPrivKeyLen[in] The length of the subscription private key. Must
|
|
* be `ECE_WEBPUSH_PRIVATE_KEY_LENGTH`.
|
|
* \param authSecret[in] The authentication secret.
|
|
* \param authSecretLen[in] The length of the authentication secret. Must be
|
|
* `ECE_WEBPUSH_AUTH_SECRET_LENGTH`.
|
|
* \param payload[in] The encrypted payload.
|
|
* \param payloadLen[in] The length of the encrypted payload.
|
|
* \param plaintext[in] An empty array. Must be large enough to hold the
|
|
* full plaintext.
|
|
* \param plaintextLen[in,out] The input is the length of the empty `plaintext`
|
|
* array. On success, the output is set to the
|
|
* the actual plaintext length, and
|
|
* `[0..plaintextLen]` contains the plaintext.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if
|
|
* the payload is empty or malformed.
|
|
*/
|
|
int
|
|
ece_webpush_aes128gcm_decrypt(const uint8_t* rawRecvPrivKey,
|
|
size_t rawRecvPrivKeyLen,
|
|
const uint8_t* authSecret, size_t authSecretLen,
|
|
const uint8_t* payload, size_t payloadLen,
|
|
uint8_t* plaintext, size_t* plaintextLen);
|
|
|
|
/*!
|
|
* Calculates the maximum "aes128gcm" encrypted payload length. The caller
|
|
* should allocate and pass an array of this length to the "aes128gcm"
|
|
* encryption functions.
|
|
*
|
|
* \param rs[in] The record size. This is the length of each encrypted
|
|
* plaintext chunk, including room for the padding
|
|
* delimiter and GCM authentication tag. Must be at
|
|
* least `ECE_AES128GCM_MIN_RS`.
|
|
* \param padLen[in] The length of additional padding, used to hide the
|
|
* plaintext length. Padding is added to the plaintext
|
|
* during encryption, and discarded during decryption.
|
|
* \param plaintextLen[in] The length of the plaintext.
|
|
*
|
|
* \return The maximum payload length, or 0 if `rs` is too
|
|
* small.
|
|
*/
|
|
size_t
|
|
ece_aes128gcm_payload_max_length(uint32_t rs, size_t padLen,
|
|
size_t plaintextLen);
|
|
|
|
/*!
|
|
* Encrypts a Web Push message using the "aes128gcm" scheme. This function
|
|
* automatically generates an ephemeral ECDH key pair and a random salt.
|
|
*
|
|
* \sa ece_aes128gcm_payload_max_length()
|
|
*
|
|
* \param rawRecvPubKey[in] The subscription public key, in uncompressed
|
|
* form.
|
|
* \param rawRecvPubKeyLen[in] The length of the subscription public key. Must
|
|
* be `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param authSecret[in] The authentication secret.
|
|
* \param authSecretLen[in] The length of the authentication secret. Must be
|
|
* `ECE_WEBPUSH_AUTH_SECRET_LENGTH`.
|
|
* \param rs[in] The record size. Must be at least
|
|
* `ECE_AES128GCM_MIN_RS`.
|
|
* \param padLen[in] The length of additional padding to include in
|
|
* the ciphertext, if any.
|
|
* \param plaintext[in] The plaintext to encrypt.
|
|
* \param plaintextLen[in] The length of the plaintext.
|
|
* \param payload[in] An empty array. Must be large enough to hold the
|
|
* full payload.
|
|
* \param payloadLen[in,out] The input is the length of the empty `payload`
|
|
* array. On success, the output is set to the
|
|
* actual payload length, and
|
|
* `payload[0..payloadLen]` contains the payload.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if
|
|
* encryption fails.
|
|
*/
|
|
int
|
|
ece_webpush_aes128gcm_encrypt(const uint8_t* rawRecvPubKey,
|
|
size_t rawRecvPubKeyLen,
|
|
const uint8_t* authSecret, size_t authSecretLen,
|
|
uint32_t rs, size_t padLen,
|
|
const uint8_t* plaintext, size_t plaintextLen,
|
|
uint8_t* payload, size_t* payloadLen);
|
|
|
|
/*!
|
|
* Encrypts a Web Push message using the "aes128gcm" scheme, with an explicit
|
|
* sender key and salt. The sender key can be reused, but the salt *must* be
|
|
* unique to avoid deriving the same content encryption key for multiple
|
|
* messages.
|
|
*
|
|
* \warning In general, you should only use this function
|
|
* for testing. `ece_webpush_aes128gcm_encrypt`
|
|
* is safer because it doesn't risk accidental
|
|
* salt reuse.
|
|
*
|
|
* \sa ece_aes128gcm_payload_max_length(),
|
|
* ece_webpush_aes128gcm_encrypt()
|
|
*
|
|
* \param rawSenderPrivKey[in] The sender private key.
|
|
* \param rawSenderPrivKeyLen[in] The length of the sender private key. Must be
|
|
* `ECE_WEBPUSH_PRIVATE_KEY_LENGTH`.
|
|
* \param authSecret[in] The authentication secret.
|
|
* \param authSecretLen[in] The length of the authentication secret. Must
|
|
* be `ECE_WEBPUSH_AUTH_SECRET_LENGTH`.
|
|
* \param salt[in] The encryption salt.
|
|
* \param saltLen[in] The length of the salt. Must be
|
|
* `ECE_SALT_LENGTH`.
|
|
* \param rawRecvPubKey[in] The subscription public key, in uncompressed
|
|
* form. Must be `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param rawRecvPubKeyLen[in] The length of the subscription public key.
|
|
* \param rs[in] The record size. Must be at least
|
|
* `ECE_AES128GCM_MIN_RS`.
|
|
* \param padLen[in] The length of additional padding to include in
|
|
* the ciphertext, if any.
|
|
* \param plaintext[in] The plaintext to encrypt.
|
|
* \param plaintextLen[in] The length of the plaintext.
|
|
* \param payload[in] An empty array. Must be large enough to hold
|
|
* the full payload.
|
|
* \param payloadLen[in,out] The input is the length of the empty `payload`
|
|
* array. On success, the output is set to the
|
|
* actual payload length, and
|
|
* `payload[0..payloadLen]` contains the payload.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if
|
|
* encryption fails.
|
|
*/
|
|
int
|
|
ece_webpush_aes128gcm_encrypt_with_keys(
|
|
const uint8_t* rawSenderPrivKey, size_t rawSenderPrivKeyLen,
|
|
const uint8_t* authSecret, size_t authSecretLen, const uint8_t* salt,
|
|
size_t saltLen, const uint8_t* rawRecvPubKey, size_t rawRecvPubKeyLen,
|
|
uint32_t rs, size_t padLen, const uint8_t* plaintext, size_t plaintextLen,
|
|
uint8_t* payload, size_t* payloadLen);
|
|
|
|
/*!
|
|
* Calculates the maximum "aesgcm" ciphertext length. The caller should allocate
|
|
* and pass an array of this length to `ece_webpush_aesgcm_encrypt_with_keys`.
|
|
*
|
|
* \param rs[in] The record size. Must be least `ECE_AESGCM_MIN_RS`.
|
|
* \param padLen[in] The length of additional padding.
|
|
* \param plaintextLen[in] The length of the plaintext.
|
|
*
|
|
* \return The maximum ciphertext length, or 0 if `rs` is too
|
|
* small.
|
|
*/
|
|
size_t
|
|
ece_aesgcm_ciphertext_max_length(uint32_t rs, size_t padLen,
|
|
size_t plaintextLen);
|
|
|
|
/*!
|
|
* Encrypts a Web Push message using the "aesgcm" scheme. Like
|
|
* `ece_webpush_aes128gcm_encrypt`, this function generates a sender key pair
|
|
* and salt.
|
|
*
|
|
* \sa ece_aesgcm_ciphertext_max_length()
|
|
*
|
|
* \param rawRecvPubKey[in] The subscription public key, in uncompressed
|
|
* form.
|
|
* \param rawRecvPubKeyLen[in] The length of the subscription public key. Must
|
|
* be `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param authSecret[in] The authentication secret.
|
|
* \param authSecretLen[in] The length of the authentication secret. Must
|
|
* be `ECE_WEBPUSH_AUTH_SECRET_LENGTH`.
|
|
* \param rs[in] The record size. Must be at least
|
|
* `ECE_AES128GCM_MIN_RS`.
|
|
* \param padLen[in] The length of additional padding to include in
|
|
* the ciphertext, if any.
|
|
* \param plaintext[in] The plaintext to encrypt.
|
|
* \param plaintextLen[in] The length of the plaintext.
|
|
* \param salt[in] An empty array to hold the salt.
|
|
* \param saltLen[in] The length of the empty `salt` array. Must be
|
|
* `ECE_SALT_LENGTH`.
|
|
* \param rawSenderPubKey[in] An empty array to hold the sender public key.
|
|
* \param rawSenderPubKeyLen[in] The length of the empty `rawSenderPubKey`
|
|
* array. Must be `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param ciphertext[in] An empty array to hold the ciphertext.
|
|
* \param ciphertextLen[in, out] The input is the length of the empty
|
|
* `ciphertext` array. On success, the output is
|
|
* set to the actual ciphertext length, and
|
|
* `ciphertext[0..ciphertextLen]` contains the
|
|
* ciphertext.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if
|
|
* encryption fails.
|
|
*/
|
|
int
|
|
ece_webpush_aesgcm_encrypt(const uint8_t* rawRecvPubKey,
|
|
size_t rawRecvPubKeyLen, const uint8_t* authSecret,
|
|
size_t authSecretLen, uint32_t rs, size_t padLen,
|
|
const uint8_t* plaintext, size_t plaintextLen,
|
|
uint8_t* salt, size_t saltLen,
|
|
uint8_t* rawSenderPubKey, size_t rawSenderPubKeyLen,
|
|
uint8_t* ciphertext, size_t* ciphertextLen);
|
|
|
|
/*!
|
|
* Encrypts a Web Push message using the "aesgcm" scheme and explicit keys.
|
|
*
|
|
* \warning `ece_webpush_aesgcm_encrypt` is safer because
|
|
* it doesn't risk accidental salt reuse.
|
|
*
|
|
* \sa ece_aesgcm_ciphertext_max_length(),
|
|
* ece_webpush_aesgcm_encrypt()
|
|
*
|
|
* \param rawSenderPrivKey[in] The sender private key.
|
|
* \param rawSenderPrivKeyLen[in] The length of the sender private key. Must be
|
|
* `ECE_WEBPUSH_PRIVATE_KEY_LENGTH`.
|
|
* \param authSecret[in] The authentication secret.
|
|
* \param authSecretLen[in] The length of the authentication secret. Must
|
|
* be `ECE_WEBPUSH_AUTH_SECRET_LENGTH`.
|
|
* \param salt[in] The encryption salt.
|
|
* \param saltLen[in] The length of the salt. Must be
|
|
* `ECE_SALT_LENGTH`.
|
|
* \param rawRecvPubKey[in] The subscription public key, in uncompressed
|
|
* form. Must be `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param rawRecvPubKeyLen[in] The length of the subscription public key.
|
|
* \param rs[in] The record size. Must be at least
|
|
* `ECE_AES128GCM_MIN_RS`.
|
|
* \param padLen[in] The length of additional padding to include in
|
|
* the ciphertext, if any.
|
|
* \param plaintext[in] The plaintext to encrypt.
|
|
* \param plaintextLen[in] The length of the plaintext.
|
|
* \param ciphertext[in] An empty array. Must be large enough to hold
|
|
* the full ciphertext.
|
|
* \param ciphertextLen[in,out] The input is the length of the empty
|
|
* `ciphertext` array. On success, the output is
|
|
* set to the actual ciphertext length, and
|
|
* `ciphertext[0..ciphertextLen]` contains the
|
|
* ciphertext.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if
|
|
* encryption fails.
|
|
*/
|
|
int
|
|
ece_webpush_aesgcm_encrypt_with_keys(
|
|
const uint8_t* rawSenderPrivKey, size_t rawSenderPrivKeyLen,
|
|
const uint8_t* authSecret, size_t authSecretLen, const uint8_t* salt,
|
|
size_t saltLen, const uint8_t* rawRecvPubKey, size_t rawRecvPubKeyLen,
|
|
uint32_t rs, size_t padLen, const uint8_t* plaintext, size_t plaintextLen,
|
|
uint8_t* ciphertext, size_t* ciphertextLen);
|
|
|
|
/*!
|
|
* Calculates the maximum "aesgcm" plaintext length. The caller should allocate
|
|
* and pass an array of this length to `ece_webpush_aesgcm_decrypt`.
|
|
*
|
|
* \sa ece_webpush_aesgcm_decrypt()
|
|
*
|
|
* \param rs[in] The record size. Must be at least
|
|
* `ECE_AESGCM_MIN_RS`.
|
|
* \param ciphertextLen[in] The ciphertext length.
|
|
*
|
|
* \return The maximum plaintext length.
|
|
*/
|
|
size_t
|
|
ece_aesgcm_plaintext_max_length(uint32_t rs, size_t ciphertextLen);
|
|
|
|
/*!
|
|
* Decrypts a Web Push message encrypted using the "aesgcm" scheme.
|
|
*
|
|
* \sa ece_aesgcm_plaintext_max_length()
|
|
*
|
|
* \param rawRecvPrivKey[in] The subscription private key.
|
|
* \param rawRecvPrivKeyLen[in] The length of the subscription private key.
|
|
* Must be `ECE_WEBPUSH_PRIVATE_KEY_LENGTH`.
|
|
* \param authSecret[in] The authentication secret.
|
|
* \param authSecretLen[in] The length of the authentication secret. Must
|
|
* be `ECE_WEBPUSH_AUTH_SECRET_LENGTH`.
|
|
* \param salt[in]
|
|
* \param salt[in] The salt, from the `Encryption` header.
|
|
* \param saltLen[in] The length of the salt. Must be
|
|
* `ECE_SALT_LENGTH`.
|
|
* \param rawSenderPubKey[in] The sender public key, in uncompressed form,
|
|
* from the `Crypto-Key` header.
|
|
* \param rawSenderPubKeyLen[in] The length of the sender public key. Must be
|
|
* `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param rs[in] The record size. Must be at least
|
|
* `ECE_AESGCM_MIN_RS`.
|
|
* \param ciphertext[in] The ciphertext.
|
|
* \param ciphertextLen[in] The length of the ciphertext.
|
|
* \param plaintext[in] An empty array. Must be large enough to hold
|
|
* the full plaintext.
|
|
* \param plaintextLen[in,out] The input is the length of the empty
|
|
* `plaintext` array. On success, the output is
|
|
* set to the actual plaintext length, and
|
|
* `[0..plaintextLen]` contains the plaintext.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if the
|
|
* headers or ciphertext are malformed.
|
|
*/
|
|
int
|
|
ece_webpush_aesgcm_decrypt(const uint8_t* rawRecvPrivKey,
|
|
size_t rawRecvPrivKeyLen, const uint8_t* authSecret,
|
|
size_t authSecretLen, const uint8_t* salt,
|
|
size_t saltLen, const uint8_t* rawSenderPubKey,
|
|
size_t rawSenderPubKeyLen, uint32_t rs,
|
|
const uint8_t* ciphertext, size_t ciphertextLen,
|
|
uint8_t* plaintext, size_t* plaintextLen);
|
|
|
|
/*!
|
|
* Extracts "aes128gcm" decryption parameters from an encrypted payload.
|
|
* `salt`, `keyId`, and `ciphertext` are pointers into `payload`, and must not
|
|
* outlive it.
|
|
*
|
|
* \sa ece_aes128gcm_decrypt()
|
|
*
|
|
* \param payload[in] The encrypted payload.
|
|
* \param payloadLen[in] The length of the encrypted payload.
|
|
* \param salt[out] The encryption salt.
|
|
* \param saltLen[out] The length of the salt.
|
|
* \param keyId[out] An identifier for the keying material.
|
|
* \param keyIdLen[out] The length of the key ID.
|
|
* \param rs[out] The record size.
|
|
* \param ciphertext[out] The ciphertext.
|
|
* \param ciphertextLen[out] The length of the ciphertext.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if the
|
|
* payload header is truncated or invalid.
|
|
*/
|
|
int
|
|
ece_aes128gcm_payload_extract_params(const uint8_t* payload, size_t payloadLen,
|
|
const uint8_t** salt, size_t* saltLen,
|
|
const uint8_t** keyId, size_t* keyIdLen,
|
|
uint32_t* rs, const uint8_t** ciphertext,
|
|
size_t* ciphertextLen);
|
|
|
|
/*!
|
|
* Extracts "aesgcm" decryption parameters from the `Crypto-Key` and
|
|
* `Encryption` headers.
|
|
*
|
|
* \sa ece_webpush_aesgcm_decrypt(),
|
|
* ece_webpush_aesgcm_headers_from_params()
|
|
*
|
|
* \param cryptoKeyHeader[in] The value of the `Crypto-Key` HTTP header.
|
|
* \param encryptionHeader[in] The value of the `Encryption` HTTP header.
|
|
* \param salt[in] An empty array to hold the encryption salt,
|
|
* extracted from the `Encryption` header.
|
|
* \param saltLen[in] The length of the empty `salt` array. Must be
|
|
* `ECE_SALT_LENGTH`.
|
|
* \param rawSenderPubKey[in] An empty array to hold the sender public key,
|
|
* in uncompressed form, extracted from the
|
|
* `Crypto-Key` header.
|
|
* \param rawSenderPubKeyLen[in] The length of the empty `rawSenderPubKey`
|
|
* array. Must be `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param rs[out] The record size.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if the
|
|
* headers are malformed.
|
|
*/
|
|
int
|
|
ece_webpush_aesgcm_headers_extract_params(const char* cryptoKeyHeader,
|
|
const char* encryptionHeader,
|
|
uint8_t* salt, size_t saltLen,
|
|
uint8_t* rawSenderPubKey,
|
|
size_t rawSenderPubKeyLen,
|
|
uint32_t* rs);
|
|
|
|
/*!
|
|
* Builds the `Crypto-Key` and `Encryption` headers from the "aesgcm"
|
|
* encryption parameters.
|
|
*
|
|
* \sa ece_webpush_aesgcm_encrypt_with_keys(),
|
|
* ece_webpush_aesgcm_headers_extract_params()
|
|
*
|
|
* \param salt[in] The encryption salt, to include in the
|
|
* `Encryption` header.
|
|
* \param saltLen[in] The length of the salt. Must be
|
|
* `ECE_SALT_LENGTH`.
|
|
* \param rawSenderPubKey[in] The sender public key, in uncompressed
|
|
* form, to include in the `Crypto-Key`
|
|
* header.
|
|
* \param rawSenderPubKeyLen[in] The length of the sender public key. Must
|
|
* be `ECE_WEBPUSH_PUBLIC_KEY_LENGTH`.
|
|
* \param rs[in] The record size, to include in the
|
|
* `Encryption` header.
|
|
* \param cryptoKeyHeader[in] An empty array to hold the `Crypto-Key`
|
|
* header. May be `NULL` if
|
|
* `cryptoKeyHeaderLen` is 0. The header is
|
|
* *not* null-terminated; you'll need to add
|
|
* a trailing `'\0'` if you want to treat
|
|
* `cryptoKeyHeader` as a C string.
|
|
* \param cryptoKeyHeaderLen[in, out] The input is the length of the empty
|
|
* `cryptoKeyHeader` array. If 0, the output
|
|
* is set to the length required to hold
|
|
* the result. On success,
|
|
* `[0..cryptoKeyHeaderLen]` contains the
|
|
* header.
|
|
* \param encryptionHeader[in] An empty array to hold the `Encryption`
|
|
* header. May be `NULL` if
|
|
* `encryptionHeaderLen` is 0. Like
|
|
* `cryptoKeyHeader`, this header is not
|
|
* null-terminated.
|
|
* \param encryptionHeaderLen[in, out] The input is the length of the empty
|
|
* `encryptionHeader` array. If 0, the
|
|
* output is set to the length required to
|
|
* hold the result. On success,
|
|
* `[0..encryptionHeaderLen]` contains the
|
|
* header.
|
|
*
|
|
* \return `ECE_OK` on success, or an error code if
|
|
* `cryptoKeyHeaderLen` or
|
|
* `encryptionHeaderLen` is too small.
|
|
*/
|
|
int
|
|
ece_webpush_aesgcm_headers_from_params(const void* salt, size_t saltLen,
|
|
const void* rawSenderPubKey,
|
|
size_t rawSenderPubKeyLen, uint32_t rs,
|
|
char* cryptoKeyHeader,
|
|
size_t* cryptoKeyHeaderLen,
|
|
char* encryptionHeader,
|
|
size_t* encryptionHeaderLen);
|
|
|
|
/*!
|
|
* Converts a byte array to a Base64url-encoded (RFC 4648) string.
|
|
*
|
|
* \param binary[in] The byte array to encode.
|
|
* \param binaryLen[in] The length of the byte array.
|
|
* \param paddingPolicy[in] The policy for padding the encoded output.
|
|
* \param base64[in] An empty array to hold the encoded result. May be
|
|
* `NULL` if `base64Len` is 0. This function does
|
|
* *not* null-terminate `base64`. This makes it easier
|
|
* to include Base64url-encoded substrings in larger
|
|
* strings, but means you'll need to add a trailing
|
|
* `'\0'` if you want to treat `base64` as a C string.
|
|
* \param base64Len[in] The length of the empty `base64` array. On success,
|
|
* `base64[0..base64Len]` contains the result.
|
|
*
|
|
* \return The encoded length. If `binaryLen` is 0, returns the
|
|
* length of the array required to hold the result. If
|
|
* `binaryLen` is not large enough to hold the full
|
|
* result, returns 0.
|
|
*/
|
|
size_t
|
|
ece_base64url_encode(const void* binary, size_t binaryLen,
|
|
ece_base64url_encode_policy_t paddingPolicy, char* base64,
|
|
size_t base64Len);
|
|
|
|
/*!
|
|
* Decodes a Base64url-encoded (RFC 4648) string.
|
|
*
|
|
* \param base64[in] The encoded string.
|
|
* \param base64Len[in] The length of the encoded string.
|
|
* \param paddingPolicy[in] The policy for handling "=" padding in the encoded
|
|
* input.
|
|
* \param binary[in] An empty array to hold the decoded result. May be
|
|
* `NULL` if `binaryLen` is 0.
|
|
* \param binaryLen[in] The length of the empty `binary` array. On success,
|
|
* `binary[0..binaryLen]` contains the result.
|
|
*
|
|
* \return The actual decoded length. If `binaryLen` is 0,
|
|
* returns the length of the array
|
|
* required to hold the result. If `base64` contains
|
|
* invalid characters, or `binaryLen` is not large
|
|
* enough to hold the full result, returns 0.
|
|
*/
|
|
size_t
|
|
ece_base64url_decode(const char* base64, size_t base64Len,
|
|
ece_base64url_decode_policy_t paddingPolicy,
|
|
uint8_t* binary, size_t binaryLen);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* ECE_H */
|