123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- /*
- * Copyright 2024 Vsevolod Stakhov
- *
- * Licensed 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.
- */
- #ifndef CRYPTOBOX_H_
- #define CRYPTOBOX_H_
-
- #include "config.h"
-
- #include <sodium.h>
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- struct rspamd_cryptobox_segment {
- unsigned char *data;
- gsize len;
- };
-
- #if defined(__GNUC__) && \
- ((defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ >= 3 && __clang_minor__ >= 8))) || \
- ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) || (__GNUC__ > 4)))
- #define RSPAMD_HAS_TARGET_ATTR 1
- #endif
-
- #define rspamd_cryptobox_MAX_NONCEBYTES 24
- #define rspamd_cryptobox_MAX_PKBYTES 65
- #define rspamd_cryptobox_MAX_SKBYTES 32
- #define rspamd_cryptobox_MAX_MACBYTES 16
- #define rspamd_cryptobox_MAX_NMBYTES 32
- #define rspamd_cryptobox_SIPKEYBYTES 16
- #define rspamd_cryptobox_HASHBYTES 64
- #define rspamd_cryptobox_HASHKEYBYTES 64
- #define rspamd_cryptobox_HASHSTATEBYTES sizeof(crypto_generichash_blake2b_state) + 64
- #define rspamd_cryptobox_MAX_SIGSKBYTES 64
- #define rspamd_cryptobox_MAX_SIGPKBYTES 32
- #define rspamd_cryptobox_MAX_SIGBYTES 72
-
- #define CPUID_AVX2 0x1
- #define CPUID_AVX 0x2
- #define CPUID_SSE2 0x4
- #define CPUID_SSE3 0x8
- #define CPUID_SSSE3 0x10
- #define CPUID_SSE41 0x20
- #define CPUID_SSE42 0x40
- #define CPUID_RDRAND 0x80
-
- typedef unsigned char rspamd_pk_t[rspamd_cryptobox_MAX_PKBYTES];
- typedef unsigned char rspamd_sk_t[rspamd_cryptobox_MAX_SKBYTES];
- typedef unsigned char rspamd_mac_t[rspamd_cryptobox_MAX_MACBYTES];
- typedef unsigned char rspamd_nm_t[rspamd_cryptobox_MAX_NMBYTES];
- typedef unsigned char rspamd_nonce_t[rspamd_cryptobox_MAX_NONCEBYTES];
- typedef unsigned char rspamd_sipkey_t[rspamd_cryptobox_SIPKEYBYTES];
- typedef unsigned char rspamd_signature_t[rspamd_cryptobox_MAX_SIGBYTES];
- typedef unsigned char rspamd_sig_pk_t[rspamd_cryptobox_MAX_SIGPKBYTES];
- typedef unsigned char rspamd_sig_sk_t[rspamd_cryptobox_MAX_SIGSKBYTES];
-
- enum rspamd_cryptobox_mode {
- RSPAMD_CRYPTOBOX_MODE_25519 = 0,
- RSPAMD_CRYPTOBOX_MODE_NIST
- };
-
- struct rspamd_cryptobox_library_ctx {
- char *cpu_extensions;
- const char *chacha20_impl;
- const char *base64_impl;
- unsigned long cpu_config;
- };
-
- /**
- * Init cryptobox library
- */
- struct rspamd_cryptobox_library_ctx *rspamd_cryptobox_init(void);
-
- void rspamd_cryptobox_deinit(struct rspamd_cryptobox_library_ctx *);
- /**
- * Generate new keypair
- * @param pk public key buffer
- * @param sk secret key buffer
- */
- void rspamd_cryptobox_keypair(rspamd_pk_t pk, rspamd_sk_t sk,
- enum rspamd_cryptobox_mode mode);
-
- /**
- * Generate new keypair for signing
- * @param pk public key buffer
- * @param sk secret key buffer
- */
- void rspamd_cryptobox_keypair_sig(rspamd_sig_pk_t pk, rspamd_sig_sk_t sk,
- enum rspamd_cryptobox_mode mode);
-
- /**
- * Encrypt data inplace adding signature to sig afterwards
- * @param data input buffer
- * @param pk remote pubkey
- * @param sk local secret key
- * @param sig output signature
- */
- void rspamd_cryptobox_encrypt_inplace(unsigned char *data, gsize len,
- const rspamd_nonce_t nonce,
- const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
-
- /**
- * Encrypt segments of data inplace adding signature to sig afterwards
- * @param segments segments of data
- * @param cnt count of segments
- * @param pk remote pubkey
- * @param sk local secret key
- * @param sig output signature
- */
- void rspamd_cryptobox_encryptv_inplace(struct rspamd_cryptobox_segment *segments,
- gsize cnt,
- const rspamd_nonce_t nonce,
- const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
-
-
- /**
- * Decrypt and verify data chunk inplace
- * @param data data to decrypt
- * @param len length of data
- * @param pk remote pubkey
- * @param sk local privkey
- * @param sig signature input
- * @return TRUE if input has been verified successfully
- */
- gboolean rspamd_cryptobox_decrypt_inplace(unsigned char *data, gsize len,
- const rspamd_nonce_t nonce,
- const rspamd_pk_t pk, const rspamd_sk_t sk, const rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
-
- /**
- * Encrypt segments of data inplace adding signature to sig afterwards
- * @param segments segments of data
- * @param cnt count of segments
- * @param pk remote pubkey
- * @param sk local secret key
- * @param sig output signature
- */
- void rspamd_cryptobox_encrypt_nm_inplace(unsigned char *data, gsize len,
- const rspamd_nonce_t nonce,
- const rspamd_nm_t nm, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
-
- /**
- * Encrypt segments of data inplace adding signature to sig afterwards
- * @param segments segments of data
- * @param cnt count of segments
- * @param pk remote pubkey
- * @param sk local secret key
- * @param sig output signature
- */
- void rspamd_cryptobox_encryptv_nm_inplace(struct rspamd_cryptobox_segment *segments,
- gsize cnt,
- const rspamd_nonce_t nonce,
- const rspamd_nm_t nm, rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
-
-
- /**
- * Decrypt and verify data chunk inplace
- * @param data data to decrypt
- * @param len length of data
- * @param pk remote pubkey
- * @param sk local privkey
- * @param sig signature input
- * @return TRUE if input has been verified successfully
- */
- gboolean rspamd_cryptobox_decrypt_nm_inplace(unsigned char *data, gsize len,
- const rspamd_nonce_t nonce,
- const rspamd_nm_t nm, const rspamd_mac_t sig,
- enum rspamd_cryptobox_mode mode);
-
- /**
- * Generate shared secret from local sk and remote pk
- * @param nm shared secret
- * @param pk remote pubkey
- * @param sk local privkey
- */
- void rspamd_cryptobox_nm(rspamd_nm_t nm, const rspamd_pk_t pk,
- const rspamd_sk_t sk, enum rspamd_cryptobox_mode mode);
-
- /**
- * Create digital signature for the specified message and place result in `sig`
- * @param sig signature target
- * @param siglen_p pointer to signature length (might be NULL)
- * @param m input message
- * @param mlen input length
- * @param sk secret key
- */
- void rspamd_cryptobox_sign(unsigned char *sig, unsigned long long *siglen_p,
- const unsigned char *m, gsize mlen,
- const rspamd_sk_t sk,
- enum rspamd_cryptobox_mode mode);
-
- /**
- * Verifies digital signature for the specified message using the specified
- * pubkey
- * @param sig signature source
- * @param m input message
- * @param mlen message length
- * @param pk public key for verification
- * @return true if signature is valid, false otherwise
- */
- bool rspamd_cryptobox_verify(const unsigned char *sig,
- gsize siglen,
- const unsigned char *m,
- gsize mlen,
- const rspamd_pk_t pk,
- enum rspamd_cryptobox_mode mode);
-
- /**
- * Securely clear the buffer specified
- * @param buf buffer to zero
- * @param buflen length of buffer
- */
-
- #define rspamd_explicit_memzero sodium_memzero
-
- /**
- * Constant time memcmp
- * @param b1_
- * @param b2_
- * @param len
- * @return
- */
- #define rspamd_cryptobox_memcmp sodium_memcmp
-
- /**
- * Calculates siphash-2-4 for a message
- * @param out (8 bytes output)
- * @param in
- * @param inlen
- * @param k key (must be 16 bytes)
- */
- void rspamd_cryptobox_siphash(unsigned char *out, const unsigned char *in,
- unsigned long long inlen,
- const rspamd_sipkey_t k);
-
- enum rspamd_cryptobox_pbkdf_type {
- RSPAMD_CRYPTOBOX_PBKDF2 = 0,
- RSPAMD_CRYPTOBOX_CATENA
- };
-
-
- /**
- * Derive key from password using the specified algorithm
- * @param pass input password
- * @param pass_len length of the password
- * @param salt input salt
- * @param salt_len length of salt
- * @param key output key
- * @param key_len size of the key
- * @param complexity empiric number of complexity (rounds for pbkdf2 and garlic for catena)
- * @return TRUE in case of success and FALSE if failed
- */
- gboolean rspamd_cryptobox_pbkdf(const char *pass, gsize pass_len,
- const uint8_t *salt, gsize salt_len,
- uint8_t *key, gsize key_len,
- unsigned int complexity,
- enum rspamd_cryptobox_pbkdf_type type);
-
-
- /**
- * Real size of rspamd cryptobox public key
- */
- unsigned int rspamd_cryptobox_pk_bytes(enum rspamd_cryptobox_mode mode);
-
- /**
- * Real size of rspamd cryptobox signing public key
- */
- unsigned int rspamd_cryptobox_pk_sig_bytes(enum rspamd_cryptobox_mode mode);
-
- /**
- * Real size of crypto nonce
- */
- unsigned int rspamd_cryptobox_nonce_bytes(enum rspamd_cryptobox_mode mode);
-
- /**
- * Real size of rspamd cryptobox secret key
- */
- unsigned int rspamd_cryptobox_sk_bytes(enum rspamd_cryptobox_mode mode);
-
- /**
- * Real size of rspamd cryptobox signing secret key
- */
- unsigned int rspamd_cryptobox_sk_sig_bytes(enum rspamd_cryptobox_mode mode);
-
- /**
- * Real size of rspamd cryptobox shared key
- */
- unsigned int rspamd_cryptobox_nm_bytes(enum rspamd_cryptobox_mode mode);
-
- /**
- * Real size of rspamd cryptobox MAC signature
- */
- unsigned int rspamd_cryptobox_mac_bytes(enum rspamd_cryptobox_mode mode);
-
- /**
- * Real size of rspamd cryptobox digital signature
- */
- unsigned int rspamd_cryptobox_signature_bytes(enum rspamd_cryptobox_mode mode);
-
- /* Hash IUF interface */
- typedef crypto_generichash_blake2b_state rspamd_cryptobox_hash_state_t;
-
- /**
- * Init cryptobox hash state using key if needed, `st` must point to the buffer
- * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
- * non-keyed hash is generated
- */
- void rspamd_cryptobox_hash_init(rspamd_cryptobox_hash_state_t *st,
- const unsigned char *key, gsize keylen);
-
- /**
- * Update hash with data portion
- */
- void rspamd_cryptobox_hash_update(rspamd_cryptobox_hash_state_t *st,
- const unsigned char *data, gsize len);
-
- /**
- * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
- */
- void rspamd_cryptobox_hash_final(rspamd_cryptobox_hash_state_t *st, unsigned char *out);
-
- /**
- * One in all function
- */
- void rspamd_cryptobox_hash(unsigned char *out,
- const unsigned char *data,
- gsize len,
- const unsigned char *key,
- gsize keylen);
-
- enum rspamd_cryptobox_fast_hash_type {
- RSPAMD_CRYPTOBOX_XXHASH64 = 0,
- RSPAMD_CRYPTOBOX_XXHASH32,
- RSPAMD_CRYPTOBOX_XXHASH3,
- RSPAMD_CRYPTOBOX_MUMHASH,
- RSPAMD_CRYPTOBOX_T1HA,
- RSPAMD_CRYPTOBOX_HASHFAST,
- RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT
- };
-
- /* Non crypto hash IUF interface */
- typedef struct CRYPTO_ALIGN(64) rspamd_cryptobox_fast_hash_state_s {
- unsigned char opaque[576]; /* Required for xxhash3 */
- enum rspamd_cryptobox_fast_hash_type type;
- } rspamd_cryptobox_fast_hash_state_t;
-
-
- /**
- * Creates a new cryptobox state properly aligned
- * @return
- */
- rspamd_cryptobox_fast_hash_state_t *rspamd_cryptobox_fast_hash_new(void);
- void rspamd_cryptobox_fast_hash_free(rspamd_cryptobox_fast_hash_state_t *st);
-
- /**
- * Init cryptobox hash state using key if needed, `st` must point to the buffer
- * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
- * non-keyed hash is generated
- */
- void rspamd_cryptobox_fast_hash_init(rspamd_cryptobox_fast_hash_state_t *st,
- uint64_t seed);
-
- /**
- * Init cryptobox hash state using key if needed, `st` must point to the buffer
- * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then
- * non-keyed hash is generated
- */
- void rspamd_cryptobox_fast_hash_init_specific(rspamd_cryptobox_fast_hash_state_t *st,
- enum rspamd_cryptobox_fast_hash_type type,
- uint64_t seed);
-
- /**
- * Update hash with data portion
- */
- void rspamd_cryptobox_fast_hash_update(rspamd_cryptobox_fast_hash_state_t *st,
- const void *data, gsize len);
-
- /**
- * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length
- */
- uint64_t rspamd_cryptobox_fast_hash_final(rspamd_cryptobox_fast_hash_state_t *st);
-
- /**
- * One in all function
- */
- uint64_t rspamd_cryptobox_fast_hash(const void *data,
- gsize len, uint64_t seed);
-
- /**
- * Platform independent version
- */
- uint64_t rspamd_cryptobox_fast_hash_specific(
- enum rspamd_cryptobox_fast_hash_type type,
- const void *data,
- gsize len, uint64_t seed);
-
- /**
- * Decode base64 using platform optimized code
- * @param in
- * @param inlen
- * @param out
- * @param outlen
- * @return
- */
- gboolean rspamd_cryptobox_base64_decode(const char *in, gsize inlen,
- unsigned char *out, gsize *outlen);
-
- /**
- * Returns TRUE if data looks like a valid base64 string
- * @param in
- * @param inlen
- * @return
- */
- gboolean rspamd_cryptobox_base64_is_valid(const char *in, gsize inlen);
-
- #ifdef __cplusplus
- }
- #endif
-
- #endif /* CRYPTOBOX_H_ */
|