| 1 | //! Cryptography. |
| 2 | |
| 3 | const std = @import("std.zig"); |
| 4 | |
| 5 | pub const timing_safe = @import("crypto/timing_safe.zig"); |
| 6 | |
| 7 | /// Authenticated Encryption with Associated Data |
| 8 | pub const aead = struct { |
| 9 | pub const aegis = struct { |
| 10 | const variants = @import("crypto/aegis.zig"); |
| 11 | |
| 12 | pub const Aegis128X4 = variants.Aegis128X4; |
| 13 | pub const Aegis128X2 = variants.Aegis128X2; |
| 14 | pub const Aegis128L = variants.Aegis128L; |
| 15 | |
| 16 | pub const Aegis256X4 = variants.Aegis256X4; |
| 17 | pub const Aegis256X2 = variants.Aegis256X2; |
| 18 | pub const Aegis256 = variants.Aegis256; |
| 19 | |
| 20 | pub const Aegis128X4_256 = variants.Aegis128X4_256; |
| 21 | pub const Aegis128X2_256 = variants.Aegis128X2_256; |
| 22 | pub const Aegis128L_256 = variants.Aegis128L_256; |
| 23 | |
| 24 | pub const Aegis256X4_256 = variants.Aegis256X4_256; |
| 25 | pub const Aegis256X2_256 = variants.Aegis256X2_256; |
| 26 | pub const Aegis256_256 = variants.Aegis256_256; |
| 27 | }; |
| 28 | |
| 29 | pub const aes_gcm = struct { |
| 30 | pub const Aes128Gcm = @import("crypto/aes_gcm.zig").Aes128Gcm; |
| 31 | pub const Aes256Gcm = @import("crypto/aes_gcm.zig").Aes256Gcm; |
| 32 | }; |
| 33 | |
| 34 | pub const aes_gcm_siv = struct { |
| 35 | pub const Aes128GcmSiv = @import("crypto/aes_gcm_siv.zig").Aes128GcmSiv; |
| 36 | pub const Aes256GcmSiv = @import("crypto/aes_gcm_siv.zig").Aes256GcmSiv; |
| 37 | }; |
| 38 | |
| 39 | pub const aes_siv = struct { |
| 40 | pub const Aes128Siv = @import("crypto/aes_siv.zig").Aes128Siv; |
| 41 | pub const Aes256Siv = @import("crypto/aes_siv.zig").Aes256Siv; |
| 42 | }; |
| 43 | |
| 44 | pub const aes_ocb = struct { |
| 45 | pub const Aes128Ocb = @import("crypto/aes_ocb.zig").Aes128Ocb; |
| 46 | pub const Aes256Ocb = @import("crypto/aes_ocb.zig").Aes256Ocb; |
| 47 | }; |
| 48 | |
| 49 | pub const aes_ccm = @import("crypto/aes_ccm.zig"); |
| 50 | |
| 51 | pub const ascon = struct { |
| 52 | pub const AsconAead128 = @import("crypto/ascon.zig").AsconAead128; |
| 53 | }; |
| 54 | |
| 55 | pub const chacha_poly = struct { |
| 56 | pub const ChaCha20Poly1305 = @import("crypto/chacha20.zig").ChaCha20Poly1305; |
| 57 | pub const ChaCha12Poly1305 = @import("crypto/chacha20.zig").ChaCha12Poly1305; |
| 58 | pub const ChaCha8Poly1305 = @import("crypto/chacha20.zig").ChaCha8Poly1305; |
| 59 | pub const XChaCha20Poly1305 = @import("crypto/chacha20.zig").XChaCha20Poly1305; |
| 60 | pub const XChaCha12Poly1305 = @import("crypto/chacha20.zig").XChaCha12Poly1305; |
| 61 | pub const XChaCha8Poly1305 = @import("crypto/chacha20.zig").XChaCha8Poly1305; |
| 62 | }; |
| 63 | |
| 64 | pub const isap = @import("crypto/isap.zig"); |
| 65 | |
| 66 | pub const salsa_poly = struct { |
| 67 | pub const XSalsa20Poly1305 = @import("crypto/salsa20.zig").XSalsa20Poly1305; |
| 68 | }; |
| 69 | }; |
| 70 | |
| 71 | /// Authentication (MAC) functions. |
| 72 | pub const auth = struct { |
| 73 | pub const hmac = @import("crypto/hmac.zig"); |
| 74 | pub const siphash = @import("crypto/siphash.zig"); |
| 75 | pub const aegis = struct { |
| 76 | const variants = @import("crypto/aegis.zig"); |
| 77 | pub const Aegis128X4Mac = variants.Aegis128X4Mac; |
| 78 | pub const Aegis128X2Mac = variants.Aegis128X2Mac; |
| 79 | pub const Aegis128LMac = variants.Aegis128LMac; |
| 80 | |
| 81 | pub const Aegis256X4Mac = variants.Aegis256X4Mac; |
| 82 | pub const Aegis256X2Mac = variants.Aegis256X2Mac; |
| 83 | pub const Aegis256Mac = variants.Aegis256Mac; |
| 84 | |
| 85 | pub const Aegis128X4Mac_128 = variants.Aegis128X4Mac_128; |
| 86 | pub const Aegis128X2Mac_128 = variants.Aegis128X2Mac_128; |
| 87 | pub const Aegis128LMac_128 = variants.Aegis128LMac_128; |
| 88 | |
| 89 | pub const Aegis256X4Mac_128 = variants.Aegis256X4Mac_128; |
| 90 | pub const Aegis256X2Mac_128 = variants.Aegis256X2Mac_128; |
| 91 | pub const Aegis256Mac_128 = variants.Aegis256Mac_128; |
| 92 | }; |
| 93 | pub const cmac = @import("crypto/cmac.zig"); |
| 94 | pub const cbc_mac = @import("crypto/cbc_mac.zig"); |
| 95 | }; |
| 96 | |
| 97 | /// Core functions, that should rarely be used directly by applications. |
| 98 | pub const core = struct { |
| 99 | pub const aes = @import("crypto/aes.zig"); |
| 100 | pub const keccak = @import("crypto/keccak_p.zig"); |
| 101 | |
| 102 | pub const Ascon = @import("crypto/ascon.zig").State; |
| 103 | |
| 104 | /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations. |
| 105 | /// |
| 106 | /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees. |
| 107 | /// |
| 108 | /// Most applications may want to use AEADs instead. |
| 109 | pub const modes = @import("crypto/modes.zig"); |
| 110 | }; |
| 111 | |
| 112 | /// Diffie-Hellman key exchange functions. |
| 113 | pub const dh = struct { |
| 114 | pub const X25519 = @import("crypto/25519/x25519.zig").X25519; |
| 115 | }; |
| 116 | |
| 117 | /// Key Encapsulation Mechanisms. |
| 118 | pub const kem = struct { |
| 119 | pub const hybrid = @import("crypto/hybrid_kem.zig"); |
| 120 | pub const kyber_d00 = @import("crypto/ml_kem.zig").d00; |
| 121 | pub const ml_kem = @import("crypto/ml_kem.zig").nist; |
| 122 | }; |
| 123 | |
| 124 | /// Elliptic-curve arithmetic. |
| 125 | pub const ecc = struct { |
| 126 | pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; |
| 127 | pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; |
| 128 | pub const P256 = @import("crypto/pcurves/p256.zig").P256; |
| 129 | pub const P384 = @import("crypto/pcurves/p384.zig").P384; |
| 130 | pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; |
| 131 | pub const Secp256k1 = @import("crypto/pcurves/secp256k1.zig").Secp256k1; |
| 132 | }; |
| 133 | |
| 134 | /// Hash functions. |
| 135 | pub const hash = struct { |
| 136 | pub const ascon = struct { |
| 137 | const variants = @import("crypto/ascon.zig"); |
| 138 | pub const AsconHash256 = variants.AsconHash256; |
| 139 | pub const AsconXof128 = variants.AsconXof128; |
| 140 | pub const AsconCxof128 = variants.AsconCxof128; |
| 141 | }; |
| 142 | pub const blake2 = @import("crypto/blake2.zig"); |
| 143 | pub const Blake3 = @import("crypto/blake3.zig").Blake3; |
| 144 | pub const Md5 = @import("crypto/md5.zig").Md5; |
| 145 | pub const Sha1 = @import("crypto/Sha1.zig"); |
| 146 | pub const sha2 = @import("crypto/sha2.zig"); |
| 147 | pub const sha3 = @import("crypto/sha3.zig"); |
| 148 | pub const composition = @import("crypto/hash_composition.zig"); |
| 149 | }; |
| 150 | |
| 151 | /// Key derivation functions. |
| 152 | pub const kdf = struct { |
| 153 | pub const hkdf = @import("crypto/hkdf.zig"); |
| 154 | }; |
| 155 | |
| 156 | /// MAC functions requiring single-use secret keys. |
| 157 | pub const onetimeauth = struct { |
| 158 | pub const Ghash = @import("crypto/ghash_polyval.zig").Ghash; |
| 159 | pub const Polyval = @import("crypto/ghash_polyval.zig").Polyval; |
| 160 | pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; |
| 161 | }; |
| 162 | |
| 163 | /// A password hashing function derives a uniform key from low-entropy input material such as passwords. |
| 164 | /// It is intentionally slow or expensive. |
| 165 | /// |
| 166 | /// With the standard definition of a key derivation function, if a key space is small, an exhaustive search may be practical. |
| 167 | /// Password hashing functions make exhaustive searches way slower or way more expensive, even when implemented on GPUs and ASICs, by using different, optionally combined strategies: |
| 168 | /// |
| 169 | /// - Requiring a lot of computation cycles to complete |
| 170 | /// - Requiring a lot of memory to complete |
| 171 | /// - Requiring multiple CPU cores to complete |
| 172 | /// - Requiring cache-local data to complete in reasonable time |
| 173 | /// - Requiring large static tables |
| 174 | /// - Avoiding precomputations and time/memory tradeoffs |
| 175 | /// - Requiring multi-party computations |
| 176 | /// - Combining the input material with random per-entry data (salts), application-specific contexts and keys |
| 177 | /// |
| 178 | /// Password hashing functions must be used whenever sensitive data has to be directly derived from a password. |
| 179 | pub const pwhash = struct { |
| 180 | pub const Encoding = enum { |
| 181 | phc, |
| 182 | crypt, |
| 183 | }; |
| 184 | |
| 185 | pub const Error = HasherError || error{AllocatorRequired}; |
| 186 | pub const HasherError = KdfError || phc_format.Error; |
| 187 | pub const KdfError = errors.Error || std.mem.Allocator.Error || std.Thread.SpawnError || std.Io.Cancelable; |
| 188 | |
| 189 | pub const argon2 = @import("crypto/argon2.zig"); |
| 190 | pub const bcrypt = @import("crypto/bcrypt.zig"); |
| 191 | pub const scrypt = @import("crypto/scrypt.zig"); |
| 192 | pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2; |
| 193 | |
| 194 | pub const phc_format = @import("crypto/phc_encoding.zig"); |
| 195 | }; |
| 196 | |
| 197 | /// Digital signature functions. |
| 198 | pub const sign = struct { |
| 199 | pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519; |
| 200 | pub const ecdsa = @import("crypto/ecdsa.zig"); |
| 201 | pub const mldsa = @import("crypto/ml_dsa.zig"); |
| 202 | }; |
| 203 | |
| 204 | /// Stream ciphers. These do not provide any kind of authentication. |
| 205 | /// Most applications should be using AEAD constructions instead of stream ciphers directly. |
| 206 | pub const stream = struct { |
| 207 | pub const chacha = struct { |
| 208 | pub const ChaCha20IETF = @import("crypto/chacha20.zig").ChaCha20IETF; |
| 209 | pub const ChaCha12IETF = @import("crypto/chacha20.zig").ChaCha12IETF; |
| 210 | pub const ChaCha8IETF = @import("crypto/chacha20.zig").ChaCha8IETF; |
| 211 | pub const ChaCha20With64BitNonce = @import("crypto/chacha20.zig").ChaCha20With64BitNonce; |
| 212 | pub const ChaCha12With64BitNonce = @import("crypto/chacha20.zig").ChaCha12With64BitNonce; |
| 213 | pub const ChaCha8With64BitNonce = @import("crypto/chacha20.zig").ChaCha8With64BitNonce; |
| 214 | pub const XChaCha20IETF = @import("crypto/chacha20.zig").XChaCha20IETF; |
| 215 | pub const XChaCha12IETF = @import("crypto/chacha20.zig").XChaCha12IETF; |
| 216 | pub const XChaCha8IETF = @import("crypto/chacha20.zig").XChaCha8IETF; |
| 217 | }; |
| 218 | |
| 219 | pub const salsa = struct { |
| 220 | pub const Salsa = @import("crypto/salsa20.zig").Salsa; |
| 221 | pub const XSalsa = @import("crypto/salsa20.zig").XSalsa; |
| 222 | pub const Salsa20 = @import("crypto/salsa20.zig").Salsa20; |
| 223 | pub const XSalsa20 = @import("crypto/salsa20.zig").XSalsa20; |
| 224 | }; |
| 225 | }; |
| 226 | |
| 227 | pub const nacl = struct { |
| 228 | const salsa20 = @import("crypto/salsa20.zig"); |
| 229 | |
| 230 | pub const Box = salsa20.Box; |
| 231 | pub const SecretBox = salsa20.SecretBox; |
| 232 | pub const SealedBox = salsa20.SealedBox; |
| 233 | }; |
| 234 | |
| 235 | /// Finite-field arithmetic. |
| 236 | pub const ff = @import("crypto/ff.zig"); |
| 237 | |
| 238 | /// Encoding and decoding |
| 239 | pub const codecs = @import("crypto/codecs.zig"); |
| 240 | |
| 241 | pub const errors = @import("crypto/errors.zig"); |
| 242 | |
| 243 | pub const tls = @import("crypto/tls.zig"); |
| 244 | pub const Certificate = @import("crypto/Certificate.zig"); |
| 245 | |
| 246 | /// Side-channels mitigations. |
| 247 | pub const SideChannelsMitigations = enum { |
| 248 | /// No additional side-channel mitigations are applied. |
| 249 | /// This is the fastest mode. |
| 250 | none, |
| 251 | /// The `basic` mode protects against most practical attacks, provided that the |
| 252 | /// application or implements proper defenses against brute-force attacks. |
| 253 | /// It offers a good balance between performance and security. |
| 254 | basic, |
| 255 | /// The `medium` mode offers increased resilience against side-channel attacks, |
| 256 | /// making most attacks unpractical even on shared/low latency environements. |
| 257 | /// This is the default mode. |
| 258 | medium, |
| 259 | /// The `full` mode offers the highest level of protection against side-channel attacks. |
| 260 | /// Note that this doesn't cover all possible attacks (especially power analysis or |
| 261 | /// thread-local attacks such as cachebleed), and that the performance impact is significant. |
| 262 | full, |
| 263 | }; |
| 264 | |
| 265 | pub const default_side_channels_mitigations = .medium; |
| 266 | |
| 267 | test { |
| 268 | _ = aead.ascon.AsconAead128; |
| 269 | |
| 270 | _ = aead.aegis.Aegis128L; |
| 271 | _ = aead.aegis.Aegis256; |
| 272 | |
| 273 | _ = aead.aes_gcm.Aes128Gcm; |
| 274 | _ = aead.aes_gcm.Aes256Gcm; |
| 275 | |
| 276 | _ = aead.aes_gcm_siv.Aes128GcmSiv; |
| 277 | _ = aead.aes_gcm_siv.Aes256GcmSiv; |
| 278 | |
| 279 | _ = aead.aes_siv.Aes128Siv; |
| 280 | _ = aead.aes_siv.Aes256Siv; |
| 281 | |
| 282 | _ = aead.aes_ocb.Aes128Ocb; |
| 283 | _ = aead.aes_ocb.Aes256Ocb; |
| 284 | |
| 285 | _ = aead.aes_ccm; |
| 286 | |
| 287 | _ = aead.chacha_poly.ChaCha20Poly1305; |
| 288 | _ = aead.chacha_poly.ChaCha12Poly1305; |
| 289 | _ = aead.chacha_poly.ChaCha8Poly1305; |
| 290 | _ = aead.chacha_poly.XChaCha20Poly1305; |
| 291 | _ = aead.chacha_poly.XChaCha12Poly1305; |
| 292 | _ = aead.chacha_poly.XChaCha8Poly1305; |
| 293 | |
| 294 | _ = aead.isap; |
| 295 | _ = aead.salsa_poly.XSalsa20Poly1305; |
| 296 | |
| 297 | _ = auth.hmac; |
| 298 | _ = auth.cmac; |
| 299 | _ = auth.cbc_mac; |
| 300 | _ = auth.siphash; |
| 301 | |
| 302 | _ = core.aes; |
| 303 | _ = core.Ascon; |
| 304 | _ = core.modes; |
| 305 | |
| 306 | _ = dh.X25519; |
| 307 | |
| 308 | _ = kem.kyber_d00; |
| 309 | _ = kem.hybrid; |
| 310 | _ = kem.kyber_d00; |
| 311 | _ = kem.ml_kem; |
| 312 | |
| 313 | _ = ecc.Curve25519; |
| 314 | _ = ecc.Edwards25519; |
| 315 | _ = ecc.P256; |
| 316 | _ = ecc.P384; |
| 317 | _ = ecc.Ristretto255; |
| 318 | _ = ecc.Secp256k1; |
| 319 | |
| 320 | _ = hash.ascon; |
| 321 | _ = hash.blake2; |
| 322 | _ = hash.Blake3; |
| 323 | _ = hash.Md5; |
| 324 | _ = hash.Sha1; |
| 325 | _ = hash.sha2; |
| 326 | _ = hash.sha3; |
| 327 | _ = hash.composition; |
| 328 | |
| 329 | _ = kdf.hkdf; |
| 330 | |
| 331 | _ = onetimeauth.Ghash; |
| 332 | _ = onetimeauth.Poly1305; |
| 333 | |
| 334 | _ = pwhash.Encoding; |
| 335 | |
| 336 | _ = pwhash.Error; |
| 337 | _ = pwhash.HasherError; |
| 338 | _ = pwhash.KdfError; |
| 339 | |
| 340 | _ = pwhash.argon2; |
| 341 | _ = pwhash.bcrypt; |
| 342 | _ = pwhash.scrypt; |
| 343 | _ = pwhash.pbkdf2; |
| 344 | |
| 345 | _ = pwhash.phc_format; |
| 346 | |
| 347 | _ = sign.Ed25519; |
| 348 | _ = sign.ecdsa; |
| 349 | _ = sign.mldsa; |
| 350 | |
| 351 | _ = stream.chacha.ChaCha20IETF; |
| 352 | _ = stream.chacha.ChaCha12IETF; |
| 353 | _ = stream.chacha.ChaCha8IETF; |
| 354 | _ = stream.chacha.ChaCha20With64BitNonce; |
| 355 | _ = stream.chacha.ChaCha12With64BitNonce; |
| 356 | _ = stream.chacha.ChaCha8With64BitNonce; |
| 357 | _ = stream.chacha.XChaCha20IETF; |
| 358 | _ = stream.chacha.XChaCha12IETF; |
| 359 | _ = stream.chacha.XChaCha8IETF; |
| 360 | |
| 361 | _ = stream.salsa.Salsa20; |
| 362 | _ = stream.salsa.XSalsa20; |
| 363 | |
| 364 | _ = nacl.Box; |
| 365 | _ = nacl.SecretBox; |
| 366 | _ = nacl.SealedBox; |
| 367 | |
| 368 | _ = secureZero; |
| 369 | _ = timing_safe; |
| 370 | _ = ff; |
| 371 | _ = errors; |
| 372 | _ = tls; |
| 373 | _ = tls.Client; |
| 374 | _ = Certificate; |
| 375 | _ = codecs; |
| 376 | } |
| 377 | |
| 378 | test "issue #4532: no index out of bounds" { |
| 379 | const types = [_]type{ |
| 380 | hash.Md5, |
| 381 | hash.Sha1, |
| 382 | hash.sha2.Sha224, |
| 383 | hash.sha2.Sha256, |
| 384 | hash.sha2.Sha384, |
| 385 | hash.sha2.Sha512, |
| 386 | hash.sha3.Sha3_224, |
| 387 | hash.sha3.Sha3_256, |
| 388 | hash.sha3.Sha3_384, |
| 389 | hash.sha3.Sha3_512, |
| 390 | hash.blake2.Blake2s128, |
| 391 | hash.blake2.Blake2s224, |
| 392 | hash.blake2.Blake2s256, |
| 393 | hash.blake2.Blake2b128, |
| 394 | hash.blake2.Blake2b256, |
| 395 | hash.blake2.Blake2b384, |
| 396 | hash.blake2.Blake2b512, |
| 397 | }; |
| 398 | |
| 399 | inline for (types) |Hasher| { |
| 400 | var block: [Hasher.block_length]u8 = @splat('#'); |
| 401 | var out1: [Hasher.digest_length]u8 = undefined; |
| 402 | var out2: [Hasher.digest_length]u8 = undefined; |
| 403 | const h0 = Hasher.init(.{}); |
| 404 | var h = h0; |
| 405 | h.update(block[0..]); |
| 406 | h.final(&out1); |
| 407 | h = h0; |
| 408 | h.update(block[0..1]); |
| 409 | h.update(block[1..]); |
| 410 | h.final(&out2); |
| 411 | |
| 412 | try std.testing.expectEqual(out1, out2); |
| 413 | } |
| 414 | } |
| 415 | |
| 416 | /// Sets a slice to zeroes. |
| 417 | /// Prevents the store from being optimized out. |
| 418 | pub fn secureZero(comptime T: type, s: []volatile T) void { |
| 419 | @memset(s, std.mem.zeroes(T)); |
| 420 | } |
| 421 | |
| 422 | test secureZero { |
| 423 | var a: [8]u8 = @splat(0xFE); |
| 424 | var b: [8]u8 = @splat(0xFE); |
| 425 | |
| 426 | @memset(&a, 0); |
| 427 | secureZero(u8, &b); |
| 428 | |
| 429 | try std.testing.expectEqualSlices(u8, &a, &b); |
| 430 | } |