/*- * Copyright 2016 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" struct rspamd_cryptobox_segment { guchar *data; gsize len; }; #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 256 #define rspamd_cryptobox_MAX_SIGSKBYTES 64 #define rspamd_cryptobox_MAX_SIGPKBYTES 32 #define rspamd_cryptobox_MAX_SIGBYTES 64 #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_RDRAND 0x40 typedef guchar rspamd_pk_t[rspamd_cryptobox_MAX_PKBYTES]; typedef guchar rspamd_sk_t[rspamd_cryptobox_MAX_SKBYTES]; typedef guchar rspamd_mac_t[rspamd_cryptobox_MAX_MACBYTES]; typedef guchar rspamd_nm_t[rspamd_cryptobox_MAX_NMBYTES]; typedef guchar rspamd_nonce_t[rspamd_cryptobox_MAX_NONCEBYTES]; typedef guchar rspamd_sipkey_t[rspamd_cryptobox_SIPKEYBYTES]; typedef guchar rspamd_signature_t[rspamd_cryptobox_MAX_SIGBYTES]; typedef guchar rspamd_sig_pk_t[rspamd_cryptobox_MAX_SIGPKBYTES]; typedef guchar 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 { gchar *cpu_extensions; const gchar *curve25519_impl; const gchar *ed25519_impl; const gchar *chacha20_impl; const gchar *poly1305_impl; const gchar *siphash_impl; const gchar *blake2_impl; unsigned long cpu_config; }; /** * Init cryptobox library */ struct rspamd_cryptobox_library_ctx* rspamd_cryptobox_init (void); /** * 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 (guchar *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 lenght 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 (guchar *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 (guchar *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 lenght 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 (guchar *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 (guchar *sig, gsize *siglen_p, const guchar *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 lenght * @param pk public key for verification * @return true if signature is valid, false otherwise */ bool rspamd_cryptobox_verify (const guchar *sig, const guchar *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 */ void rspamd_explicit_memzero (void * const buf, gsize buflen); /** * 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); /** * Derive key from password using PKCS#5 and HMAC-blake2 * @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 rounds number of rounds (should be reasonably high) * @return TRUE in case of success and FALSE if failed */ gboolean rspamd_cryptobox_pbkdf(const char *pass, gsize pass_len, const guint8 *salt, gsize salt_len, guint8 *key, gsize key_len, unsigned int rounds); /** * Real size of rspamd cryptobox public key */ guint rspamd_cryptobox_pk_bytes (enum rspamd_cryptobox_mode mode); /** * Real size of rspamd cryptobox signing public key */ guint rspamd_cryptobox_pk_sig_bytes (enum rspamd_cryptobox_mode mode); /** * Real size of crypto nonce */ guint rspamd_cryptobox_nonce_bytes (enum rspamd_cryptobox_mode mode); /** * Real size of rspamd cryptobox secret key */ guint rspamd_cryptobox_sk_bytes (enum rspamd_cryptobox_mode mode); /** * Real size of rspamd cryptobox signing secret key */ guint rspamd_cryptobox_sk_sig_bytes (enum rspamd_cryptobox_mode mode); /** * Real size of rspamd cryptobox shared key */ guint rspamd_cryptobox_nm_bytes (enum rspamd_cryptobox_mode mode); /** * Real size of rspamd cryptobox MAC signature */ guint rspamd_cryptobox_mac_bytes (enum rspamd_cryptobox_mode mode); /** * Real size of rspamd cryptobox digital signature */ guint rspamd_cryptobox_signature_bytes (enum rspamd_cryptobox_mode mode); /* Hash IUF interface */ typedef struct RSPAMD_ALIGNED(32) rspamd_cryptobox_hash_state_s { unsigned char opaque[256]; } 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 (void *st, const guchar *key, gsize keylen); /** * Update hash with data portion */ void rspamd_cryptobox_hash_update (void *st, const guchar *data, gsize len); /** * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length */ void rspamd_cryptobox_hash_final (void *st, guchar *out); /** * One in all function */ void rspamd_cryptobox_hash (guchar *out, const guchar *data, gsize len, const guchar *key, gsize keylen); #endif /* CRYPTOBOX_H_ */