master
  1//! Cryptography.
  2
  3const std = @import("std.zig");
  4
  5pub const timing_safe = @import("crypto/timing_safe.zig");
  6
  7/// Authenticated Encryption with Associated Data
  8pub 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.
 72pub 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.
 98pub 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.
113pub const dh = struct {
114    pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
115};
116
117/// Key Encapsulation Mechanisms.
118pub 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.
125pub 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.
135pub 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.
152pub const kdf = struct {
153    pub const hkdf = @import("crypto/hkdf.zig");
154};
155
156/// MAC functions requiring single-use secret keys.
157pub 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.
179pub 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;
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.
198pub 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.
206pub 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
227pub 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.
236pub const ff = @import("crypto/ff.zig");
237
238/// This is a thread-local, cryptographically secure pseudo random number generator.
239pub const random = @import("crypto/tlcsprng.zig").interface;
240
241/// Encoding and decoding
242pub const codecs = @import("crypto/codecs.zig");
243
244pub const errors = @import("crypto/errors.zig");
245
246pub const tls = @import("crypto/tls.zig");
247pub const Certificate = @import("crypto/Certificate.zig");
248
249/// Side-channels mitigations.
250pub const SideChannelsMitigations = enum {
251    /// No additional side-channel mitigations are applied.
252    /// This is the fastest mode.
253    none,
254    /// The `basic` mode protects against most practical attacks, provided that the
255    /// application or implements proper defenses against brute-force attacks.
256    /// It offers a good balance between performance and security.
257    basic,
258    /// The `medium` mode offers increased resilience against side-channel attacks,
259    /// making most attacks unpractical even on shared/low latency environements.
260    /// This is the default mode.
261    medium,
262    /// The `full` mode offers the highest level of protection against side-channel attacks.
263    /// Note that this doesn't cover all possible attacks (especially power analysis or
264    /// thread-local attacks such as cachebleed), and that the performance impact is significant.
265    full,
266};
267
268pub const default_side_channels_mitigations = .medium;
269
270test {
271    _ = aead.ascon.AsconAead128;
272
273    _ = aead.aegis.Aegis128L;
274    _ = aead.aegis.Aegis256;
275
276    _ = aead.aes_gcm.Aes128Gcm;
277    _ = aead.aes_gcm.Aes256Gcm;
278
279    _ = aead.aes_gcm_siv.Aes128GcmSiv;
280    _ = aead.aes_gcm_siv.Aes256GcmSiv;
281
282    _ = aead.aes_siv.Aes128Siv;
283    _ = aead.aes_siv.Aes256Siv;
284
285    _ = aead.aes_ocb.Aes128Ocb;
286    _ = aead.aes_ocb.Aes256Ocb;
287
288    _ = aead.chacha_poly.ChaCha20Poly1305;
289    _ = aead.chacha_poly.ChaCha12Poly1305;
290    _ = aead.chacha_poly.ChaCha8Poly1305;
291    _ = aead.chacha_poly.XChaCha20Poly1305;
292    _ = aead.chacha_poly.XChaCha12Poly1305;
293    _ = aead.chacha_poly.XChaCha8Poly1305;
294
295    _ = aead.isap;
296    _ = aead.salsa_poly.XSalsa20Poly1305;
297
298    _ = auth.hmac;
299    _ = auth.cmac;
300    _ = auth.siphash;
301
302    _ = core.aes;
303    _ = core.Ascon;
304    _ = core.modes;
305
306    _ = dh.X25519;
307
308    _ = kem.kyber_d00;
309
310    _ = ecc.Curve25519;
311    _ = ecc.Edwards25519;
312    _ = ecc.P256;
313    _ = ecc.P384;
314    _ = ecc.Ristretto255;
315    _ = ecc.Secp256k1;
316
317    _ = hash.ascon;
318    _ = hash.blake2;
319    _ = hash.Blake3;
320    _ = hash.Md5;
321    _ = hash.Sha1;
322    _ = hash.sha2;
323    _ = hash.sha3;
324    _ = hash.composition;
325
326    _ = kdf.hkdf;
327
328    _ = onetimeauth.Ghash;
329    _ = onetimeauth.Poly1305;
330
331    _ = pwhash.Encoding;
332
333    _ = pwhash.Error;
334    _ = pwhash.HasherError;
335    _ = pwhash.KdfError;
336
337    _ = pwhash.argon2;
338    _ = pwhash.bcrypt;
339    _ = pwhash.scrypt;
340    _ = pwhash.pbkdf2;
341
342    _ = pwhash.phc_format;
343
344    _ = sign.Ed25519;
345    _ = sign.ecdsa;
346
347    _ = stream.chacha.ChaCha20IETF;
348    _ = stream.chacha.ChaCha12IETF;
349    _ = stream.chacha.ChaCha8IETF;
350    _ = stream.chacha.ChaCha20With64BitNonce;
351    _ = stream.chacha.ChaCha12With64BitNonce;
352    _ = stream.chacha.ChaCha8With64BitNonce;
353    _ = stream.chacha.XChaCha20IETF;
354    _ = stream.chacha.XChaCha12IETF;
355    _ = stream.chacha.XChaCha8IETF;
356
357    _ = stream.salsa.Salsa20;
358    _ = stream.salsa.XSalsa20;
359
360    _ = nacl.Box;
361    _ = nacl.SecretBox;
362    _ = nacl.SealedBox;
363
364    _ = secureZero;
365    _ = timing_safe;
366    _ = ff;
367    _ = random;
368    _ = errors;
369    _ = tls;
370    _ = Certificate;
371    _ = codecs;
372}
373
374test "CSPRNG" {
375    const a = random.int(u64);
376    const b = random.int(u64);
377    const c = random.int(u64);
378    try std.testing.expect(a ^ b ^ c != 0);
379}
380
381test "issue #4532: no index out of bounds" {
382    const types = [_]type{
383        hash.Md5,
384        hash.Sha1,
385        hash.sha2.Sha224,
386        hash.sha2.Sha256,
387        hash.sha2.Sha384,
388        hash.sha2.Sha512,
389        hash.sha3.Sha3_224,
390        hash.sha3.Sha3_256,
391        hash.sha3.Sha3_384,
392        hash.sha3.Sha3_512,
393        hash.blake2.Blake2s128,
394        hash.blake2.Blake2s224,
395        hash.blake2.Blake2s256,
396        hash.blake2.Blake2b128,
397        hash.blake2.Blake2b256,
398        hash.blake2.Blake2b384,
399        hash.blake2.Blake2b512,
400    };
401
402    inline for (types) |Hasher| {
403        var block = [_]u8{'#'} ** Hasher.block_length;
404        var out1: [Hasher.digest_length]u8 = undefined;
405        var out2: [Hasher.digest_length]u8 = undefined;
406        const h0 = Hasher.init(.{});
407        var h = h0;
408        h.update(block[0..]);
409        h.final(&out1);
410        h = h0;
411        h.update(block[0..1]);
412        h.update(block[1..]);
413        h.final(&out2);
414
415        try std.testing.expectEqual(out1, out2);
416    }
417}
418
419/// Sets a slice to zeroes.
420/// Prevents the store from being optimized out.
421pub fn secureZero(comptime T: type, s: []volatile T) void {
422    @memset(s, 0);
423}
424
425test secureZero {
426    var a = [_]u8{0xfe} ** 8;
427    var b = [_]u8{0xfe} ** 8;
428
429    @memset(&a, 0);
430    secureZero(u8, &b);
431
432    try std.testing.expectEqualSlices(u8, &a, &b);
433}