1 /*- 2 * Copyright 2016 Vsevolod Stakhov 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef CRYPTOBOX_H_ 17 #define CRYPTOBOX_H_ 18 19 #include "config.h" 20 21 #include <sodium.h> 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 struct rspamd_cryptobox_segment { 28 guchar *data; 29 gsize len; 30 }; 31 32 #if defined(__GNUC__) && \ 33 ((defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ >= 3 && __clang_minor__ >= 8))) || \ 34 ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) || (__GNUC__ > 4))) 35 #define RSPAMD_HAS_TARGET_ATTR 1 36 #endif 37 38 #define rspamd_cryptobox_MAX_NONCEBYTES 24 39 #define rspamd_cryptobox_MAX_PKBYTES 65 40 #define rspamd_cryptobox_MAX_SKBYTES 32 41 #define rspamd_cryptobox_MAX_MACBYTES 16 42 #define rspamd_cryptobox_MAX_NMBYTES 32 43 #define rspamd_cryptobox_SIPKEYBYTES 16 44 #define rspamd_cryptobox_HASHBYTES 64 45 #define rspamd_cryptobox_HASHKEYBYTES 64 46 #define rspamd_cryptobox_HASHSTATEBYTES sizeof(crypto_generichash_blake2b_state) + 64 47 #define rspamd_cryptobox_MAX_SIGSKBYTES 64 48 #define rspamd_cryptobox_MAX_SIGPKBYTES 32 49 #define rspamd_cryptobox_MAX_SIGBYTES 72 50 51 #define CPUID_AVX2 0x1 52 #define CPUID_AVX 0x2 53 #define CPUID_SSE2 0x4 54 #define CPUID_SSE3 0x8 55 #define CPUID_SSSE3 0x10 56 #define CPUID_SSE41 0x20 57 #define CPUID_SSE42 0x40 58 #define CPUID_RDRAND 0x80 59 60 typedef guchar rspamd_pk_t[rspamd_cryptobox_MAX_PKBYTES]; 61 typedef guchar rspamd_sk_t[rspamd_cryptobox_MAX_SKBYTES]; 62 typedef guchar rspamd_mac_t[rspamd_cryptobox_MAX_MACBYTES]; 63 typedef guchar rspamd_nm_t[rspamd_cryptobox_MAX_NMBYTES]; 64 typedef guchar rspamd_nonce_t[rspamd_cryptobox_MAX_NONCEBYTES]; 65 typedef guchar rspamd_sipkey_t[rspamd_cryptobox_SIPKEYBYTES]; 66 typedef guchar rspamd_signature_t[rspamd_cryptobox_MAX_SIGBYTES]; 67 typedef guchar rspamd_sig_pk_t[rspamd_cryptobox_MAX_SIGPKBYTES]; 68 typedef guchar rspamd_sig_sk_t[rspamd_cryptobox_MAX_SIGSKBYTES]; 69 70 enum rspamd_cryptobox_mode { 71 RSPAMD_CRYPTOBOX_MODE_25519 = 0, 72 RSPAMD_CRYPTOBOX_MODE_NIST 73 }; 74 75 struct rspamd_cryptobox_library_ctx { 76 gchar *cpu_extensions; 77 const gchar *chacha20_impl; 78 const gchar *base64_impl; 79 unsigned long cpu_config; 80 }; 81 82 /** 83 * Init cryptobox library 84 */ 85 struct rspamd_cryptobox_library_ctx *rspamd_cryptobox_init (void); 86 87 void rspamd_cryptobox_deinit (struct rspamd_cryptobox_library_ctx *); 88 /** 89 * Generate new keypair 90 * @param pk public key buffer 91 * @param sk secret key buffer 92 */ 93 void rspamd_cryptobox_keypair (rspamd_pk_t pk, rspamd_sk_t sk, 94 enum rspamd_cryptobox_mode mode); 95 96 /** 97 * Generate new keypair for signing 98 * @param pk public key buffer 99 * @param sk secret key buffer 100 */ 101 void rspamd_cryptobox_keypair_sig (rspamd_sig_pk_t pk, rspamd_sig_sk_t sk, 102 enum rspamd_cryptobox_mode mode); 103 104 /** 105 * Encrypt data inplace adding signature to sig afterwards 106 * @param data input buffer 107 * @param pk remote pubkey 108 * @param sk local secret key 109 * @param sig output signature 110 */ 111 void rspamd_cryptobox_encrypt_inplace (guchar *data, gsize len, 112 const rspamd_nonce_t nonce, 113 const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig, 114 enum rspamd_cryptobox_mode mode); 115 116 /** 117 * Encrypt segments of data inplace adding signature to sig afterwards 118 * @param segments segments of data 119 * @param cnt count of segments 120 * @param pk remote pubkey 121 * @param sk local secret key 122 * @param sig output signature 123 */ 124 void rspamd_cryptobox_encryptv_inplace (struct rspamd_cryptobox_segment *segments, 125 gsize cnt, 126 const rspamd_nonce_t nonce, 127 const rspamd_pk_t pk, const rspamd_sk_t sk, rspamd_mac_t sig, 128 enum rspamd_cryptobox_mode mode); 129 130 131 /** 132 * Decrypt and verify data chunk inplace 133 * @param data data to decrypt 134 * @param len length of data 135 * @param pk remote pubkey 136 * @param sk local privkey 137 * @param sig signature input 138 * @return TRUE if input has been verified successfully 139 */ 140 gboolean rspamd_cryptobox_decrypt_inplace (guchar *data, gsize len, 141 const rspamd_nonce_t nonce, 142 const rspamd_pk_t pk, const rspamd_sk_t sk, const rspamd_mac_t sig, 143 enum rspamd_cryptobox_mode mode); 144 145 /** 146 * Encrypt segments of data inplace adding signature to sig afterwards 147 * @param segments segments of data 148 * @param cnt count of segments 149 * @param pk remote pubkey 150 * @param sk local secret key 151 * @param sig output signature 152 */ 153 void rspamd_cryptobox_encrypt_nm_inplace (guchar *data, gsize len, 154 const rspamd_nonce_t nonce, 155 const rspamd_nm_t nm, rspamd_mac_t sig, 156 enum rspamd_cryptobox_mode mode); 157 158 /** 159 * Encrypt segments of data inplace adding signature to sig afterwards 160 * @param segments segments of data 161 * @param cnt count of segments 162 * @param pk remote pubkey 163 * @param sk local secret key 164 * @param sig output signature 165 */ 166 void rspamd_cryptobox_encryptv_nm_inplace (struct rspamd_cryptobox_segment *segments, 167 gsize cnt, 168 const rspamd_nonce_t nonce, 169 const rspamd_nm_t nm, rspamd_mac_t sig, 170 enum rspamd_cryptobox_mode mode); 171 172 173 /** 174 * Decrypt and verify data chunk inplace 175 * @param data data to decrypt 176 * @param len length of data 177 * @param pk remote pubkey 178 * @param sk local privkey 179 * @param sig signature input 180 * @return TRUE if input has been verified successfully 181 */ 182 gboolean rspamd_cryptobox_decrypt_nm_inplace (guchar *data, gsize len, 183 const rspamd_nonce_t nonce, 184 const rspamd_nm_t nm, const rspamd_mac_t sig, 185 enum rspamd_cryptobox_mode mode); 186 187 /** 188 * Generate shared secret from local sk and remote pk 189 * @param nm shared secret 190 * @param pk remote pubkey 191 * @param sk local privkey 192 */ 193 void rspamd_cryptobox_nm (rspamd_nm_t nm, const rspamd_pk_t pk, 194 const rspamd_sk_t sk, enum rspamd_cryptobox_mode mode); 195 196 /** 197 * Create digital signature for the specified message and place result in `sig` 198 * @param sig signature target 199 * @param siglen_p pointer to signature length (might be NULL) 200 * @param m input message 201 * @param mlen input length 202 * @param sk secret key 203 */ 204 void rspamd_cryptobox_sign (guchar *sig, unsigned long long *siglen_p, 205 const guchar *m, gsize mlen, 206 const rspamd_sk_t sk, 207 enum rspamd_cryptobox_mode mode); 208 209 /** 210 * Verifies digital signature for the specified message using the specified 211 * pubkey 212 * @param sig signature source 213 * @param m input message 214 * @param mlen message length 215 * @param pk public key for verification 216 * @return true if signature is valid, false otherwise 217 */ 218 bool rspamd_cryptobox_verify (const guchar *sig, 219 gsize siglen, 220 const guchar *m, 221 gsize mlen, 222 const rspamd_pk_t pk, 223 enum rspamd_cryptobox_mode mode); 224 225 /** 226 * Securely clear the buffer specified 227 * @param buf buffer to zero 228 * @param buflen length of buffer 229 */ 230 231 #define rspamd_explicit_memzero sodium_memzero 232 233 /** 234 * Constant time memcmp 235 * @param b1_ 236 * @param b2_ 237 * @param len 238 * @return 239 */ 240 #define rspamd_cryptobox_memcmp sodium_memcmp 241 242 /** 243 * Calculates siphash-2-4 for a message 244 * @param out (8 bytes output) 245 * @param in 246 * @param inlen 247 * @param k key (must be 16 bytes) 248 */ 249 void rspamd_cryptobox_siphash (unsigned char *out, const unsigned char *in, 250 unsigned long long inlen, 251 const rspamd_sipkey_t k); 252 253 enum rspamd_cryptobox_pbkdf_type { 254 RSPAMD_CRYPTOBOX_PBKDF2 = 0, 255 RSPAMD_CRYPTOBOX_CATENA 256 }; 257 258 259 /** 260 * Derive key from password using the specified algorithm 261 * @param pass input password 262 * @param pass_len length of the password 263 * @param salt input salt 264 * @param salt_len length of salt 265 * @param key output key 266 * @param key_len size of the key 267 * @param complexity empiric number of complexity (rounds for pbkdf2 and garlic for catena) 268 * @return TRUE in case of success and FALSE if failed 269 */ 270 gboolean rspamd_cryptobox_pbkdf (const char *pass, gsize pass_len, 271 const guint8 *salt, gsize salt_len, 272 guint8 *key, gsize key_len, 273 unsigned int complexity, 274 enum rspamd_cryptobox_pbkdf_type type); 275 276 277 /** 278 * Real size of rspamd cryptobox public key 279 */ 280 guint rspamd_cryptobox_pk_bytes (enum rspamd_cryptobox_mode mode); 281 282 /** 283 * Real size of rspamd cryptobox signing public key 284 */ 285 guint rspamd_cryptobox_pk_sig_bytes (enum rspamd_cryptobox_mode mode); 286 287 /** 288 * Real size of crypto nonce 289 */ 290 guint rspamd_cryptobox_nonce_bytes (enum rspamd_cryptobox_mode mode); 291 292 /** 293 * Real size of rspamd cryptobox secret key 294 */ 295 guint rspamd_cryptobox_sk_bytes (enum rspamd_cryptobox_mode mode); 296 297 /** 298 * Real size of rspamd cryptobox signing secret key 299 */ 300 guint rspamd_cryptobox_sk_sig_bytes (enum rspamd_cryptobox_mode mode); 301 302 /** 303 * Real size of rspamd cryptobox shared key 304 */ 305 guint rspamd_cryptobox_nm_bytes (enum rspamd_cryptobox_mode mode); 306 307 /** 308 * Real size of rspamd cryptobox MAC signature 309 */ 310 guint rspamd_cryptobox_mac_bytes (enum rspamd_cryptobox_mode mode); 311 312 /** 313 * Real size of rspamd cryptobox digital signature 314 */ 315 guint rspamd_cryptobox_signature_bytes (enum rspamd_cryptobox_mode mode); 316 317 /* Hash IUF interface */ 318 typedef crypto_generichash_blake2b_state rspamd_cryptobox_hash_state_t; 319 320 /** 321 * Init cryptobox hash state using key if needed, `st` must point to the buffer 322 * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then 323 * non-keyed hash is generated 324 */ 325 void rspamd_cryptobox_hash_init (rspamd_cryptobox_hash_state_t *st, 326 const guchar *key, gsize keylen); 327 328 /** 329 * Update hash with data portion 330 */ 331 void rspamd_cryptobox_hash_update (rspamd_cryptobox_hash_state_t *st, 332 const guchar *data, gsize len); 333 334 /** 335 * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length 336 */ 337 void rspamd_cryptobox_hash_final (rspamd_cryptobox_hash_state_t *st, guchar *out); 338 339 /** 340 * One in all function 341 */ 342 void rspamd_cryptobox_hash (guchar *out, 343 const guchar *data, 344 gsize len, 345 const guchar *key, 346 gsize keylen); 347 348 enum rspamd_cryptobox_fast_hash_type { 349 RSPAMD_CRYPTOBOX_XXHASH64 = 0, 350 RSPAMD_CRYPTOBOX_XXHASH32, 351 RSPAMD_CRYPTOBOX_MUMHASH, 352 RSPAMD_CRYPTOBOX_T1HA, 353 RSPAMD_CRYPTOBOX_HASHFAST, 354 RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT 355 }; 356 357 /* Non crypto hash IUF interface */ 358 typedef struct rspamd_cryptobox_fast_hash_state_s { 359 guint64 opaque[11]; 360 enum rspamd_cryptobox_fast_hash_type type; 361 } rspamd_cryptobox_fast_hash_state_t; 362 363 /** 364 * Init cryptobox hash state using key if needed, `st` must point to the buffer 365 * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then 366 * non-keyed hash is generated 367 */ 368 void rspamd_cryptobox_fast_hash_init (rspamd_cryptobox_fast_hash_state_t *st, 369 guint64 seed); 370 371 /** 372 * Init cryptobox hash state using key if needed, `st` must point to the buffer 373 * with at least rspamd_cryptobox_HASHSTATEBYTES bytes length. If keylen == 0, then 374 * non-keyed hash is generated 375 */ 376 void rspamd_cryptobox_fast_hash_init_specific (rspamd_cryptobox_fast_hash_state_t *st, 377 enum rspamd_cryptobox_fast_hash_type type, 378 guint64 seed); 379 380 /** 381 * Update hash with data portion 382 */ 383 void rspamd_cryptobox_fast_hash_update (rspamd_cryptobox_fast_hash_state_t *st, 384 const void *data, gsize len); 385 386 /** 387 * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length 388 */ 389 guint64 rspamd_cryptobox_fast_hash_final (rspamd_cryptobox_fast_hash_state_t *st); 390 391 /** 392 * One in all function 393 */ 394 guint64 rspamd_cryptobox_fast_hash (const void *data, 395 gsize len, guint64 seed); 396 397 /** 398 * Platform independent version 399 */ 400 guint64 rspamd_cryptobox_fast_hash_specific ( 401 enum rspamd_cryptobox_fast_hash_type type, 402 const void *data, 403 gsize len, guint64 seed); 404 405 /** 406 * Decode base64 using platform optimized code 407 * @param in 408 * @param inlen 409 * @param out 410 * @param outlen 411 * @return 412 */ 413 gboolean rspamd_cryptobox_base64_decode (const gchar *in, gsize inlen, 414 guchar *out, gsize *outlen); 415 416 /** 417 * Returns TRUE if data looks like a valid base64 string 418 * @param in 419 * @param inlen 420 * @return 421 */ 422 gboolean rspamd_cryptobox_base64_is_valid (const gchar *in, gsize inlen); 423 424 #ifdef __cplusplus 425 } 426 #endif 427 428 #endif /* CRYPTOBOX_H_ */ 429