authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2021-04-20 19:57:27+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-04-20 19:57:27+02:00
log10f2d6278946485f057f65bbb3c094a6fcde1adf
treed7e4f5182e5fd226a705fb3bfbab9d35faa1e1ef
parent1e06a74348d11e4eef456a067dc5065c1e8b1ee9
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

std/crypto: use finer-grained error sets in function signatures (#8558)

std/crypto: use finer-grained error sets in function signatures Returning the `crypto.Error` error set for all crypto operations was very convenient to ensure that errors were used consistently, and to avoid having multiple error names for the same thing. The flipside is that callers were forced to always handle all possible errors, even those that could never be returned by a function. This PR makes all functions return union sets of the actual errors they can return. The error sets themselves are all limited to a single error. Larger sets are useful for platform-specific APIs, but we don't have any of these in `std/crypto`, and I couldn't find any meaningful way to build larger sets.

19 files changed, 148 insertions(+), 114 deletions(-)

lib/std/crypto.zig+1-1
...@@ -154,7 +154,7 @@ pub const random = &@import("crypto/tlcsprng.zig").interface;...@@ -154,7 +154,7 @@ pub const random = &@import("crypto/tlcsprng.zig").interface;
154154
155const std = @import("std.zig");155const std = @import("std.zig");
156156
157pub const Error = @import("crypto/error.zig").Error;157pub const errors = @import("crypto/errors.zig");
158158
159test "crypto" {159test "crypto" {
160 const please_windows_dont_oom = std.Target.current.os.tag == .windows;160 const please_windows_dont_oom = std.Target.current.os.tag == .windows;
lib/std/crypto/25519/curve25519.zig+12-8
...@@ -4,7 +4,11 @@...@@ -4,7 +4,11 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const Error = std.crypto.Error;7const crypto = std.crypto;
8
9const IdentityElementError = crypto.errors.IdentityElementError;
10const NonCanonicalError = crypto.errors.NonCanonicalError;
11const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
812
9/// Group operations over Curve25519.13/// Group operations over Curve25519.
10pub const Curve25519 = struct {14pub const Curve25519 = struct {
...@@ -29,12 +33,12 @@ pub const Curve25519 = struct {...@@ -29,12 +33,12 @@ pub const Curve25519 = struct {
29 pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint };33 pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint };
3034
31 /// Check that the encoding of a Curve25519 point is canonical.35 /// Check that the encoding of a Curve25519 point is canonical.
32 pub fn rejectNonCanonical(s: [32]u8) Error!void {36 pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
33 return Fe.rejectNonCanonical(s, false);37 return Fe.rejectNonCanonical(s, false);
34 }38 }
3539
36 /// Reject the neutral element.40 /// Reject the neutral element.
37 pub fn rejectIdentity(p: Curve25519) Error!void {41 pub fn rejectIdentity(p: Curve25519) IdentityElementError!void {
38 if (p.x.isZero()) {42 if (p.x.isZero()) {
39 return error.IdentityElement;43 return error.IdentityElement;
40 }44 }
...@@ -45,7 +49,7 @@ pub const Curve25519 = struct {...@@ -45,7 +49,7 @@ pub const Curve25519 = struct {
45 return p.dbl().dbl().dbl();49 return p.dbl().dbl().dbl();
46 }50 }
4751
48 fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) Error!Curve25519 {52 fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) IdentityElementError!Curve25519 {
49 var x1 = p.x;53 var x1 = p.x;
50 var x2 = Fe.one;54 var x2 = Fe.one;
51 var z2 = Fe.zero;55 var z2 = Fe.zero;
...@@ -86,7 +90,7 @@ pub const Curve25519 = struct {...@@ -86,7 +90,7 @@ pub const Curve25519 = struct {
86 /// way to use Curve25519 for a DH operation.90 /// way to use Curve25519 for a DH operation.
87 /// Return error.IdentityElement if the resulting point is91 /// Return error.IdentityElement if the resulting point is
88 /// the identity element.92 /// the identity element.
89 pub fn clampedMul(p: Curve25519, s: [32]u8) Error!Curve25519 {93 pub fn clampedMul(p: Curve25519, s: [32]u8) IdentityElementError!Curve25519 {
90 var t: [32]u8 = s;94 var t: [32]u8 = s;
91 scalar.clamp(&t);95 scalar.clamp(&t);
92 return try ladder(p, t, 255);96 return try ladder(p, t, 255);
...@@ -96,16 +100,16 @@ pub const Curve25519 = struct {...@@ -96,16 +100,16 @@ pub const Curve25519 = struct {
96 /// Return error.IdentityElement if the resulting point is100 /// Return error.IdentityElement if the resulting point is
97 /// the identity element or error.WeakPublicKey if the public101 /// the identity element or error.WeakPublicKey if the public
98 /// key is a low-order point.102 /// key is a low-order point.
99 pub fn mul(p: Curve25519, s: [32]u8) Error!Curve25519 {103 pub fn mul(p: Curve25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Curve25519 {
100 const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;104 const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;
101 _ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey;105 _ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey;
102 return try ladder(p, s, 256);106 return try ladder(p, s, 256);
103 }107 }
104108
105 /// Compute the Curve25519 equivalent to an Edwards25519 point.109 /// Compute the Curve25519 equivalent to an Edwards25519 point.
106 pub fn fromEdwards25519(p: std.crypto.ecc.Edwards25519) Error!Curve25519 {110 pub fn fromEdwards25519(p: crypto.ecc.Edwards25519) IdentityElementError!Curve25519 {
107 try p.clearCofactor().rejectIdentity();111 try p.clearCofactor().rejectIdentity();
108 const one = std.crypto.ecc.Edwards25519.Fe.one;112 const one = crypto.ecc.Edwards25519.Fe.one;
109 const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd)113 const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd)
110 return Curve25519{ .x = x };114 return Curve25519{ .x = x };
111 }115 }
lib/std/crypto/25519/ed25519.zig+16-9
...@@ -8,8 +8,15 @@ const crypto = std.crypto;...@@ -8,8 +8,15 @@ const crypto = std.crypto;
8const debug = std.debug;8const debug = std.debug;
9const fmt = std.fmt;9const fmt = std.fmt;
10const mem = std.mem;10const mem = std.mem;
11
11const Sha512 = crypto.hash.sha2.Sha512;12const Sha512 = crypto.hash.sha2.Sha512;
12const Error = crypto.Error;13
14const EncodingError = crypto.errors.EncodingError;
15const IdentityElementError = crypto.errors.IdentityElementError;
16const NonCanonicalError = crypto.errors.NonCanonicalError;
17const SignatureVerificationError = crypto.errors.SignatureVerificationError;
18const KeyMismatchError = crypto.errors.KeyMismatchError;
19const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
1320
14/// Ed25519 (EdDSA) signatures.21/// Ed25519 (EdDSA) signatures.
15pub const Ed25519 = struct {22pub const Ed25519 = struct {
...@@ -41,7 +48,7 @@ pub const Ed25519 = struct {...@@ -41,7 +48,7 @@ pub const Ed25519 = struct {
41 ///48 ///
42 /// For this reason, an EdDSA secret key is commonly called a seed,49 /// For this reason, an EdDSA secret key is commonly called a seed,
43 /// from which the actual secret is derived.50 /// from which the actual secret is derived.
44 pub fn create(seed: ?[seed_length]u8) Error!KeyPair {51 pub fn create(seed: ?[seed_length]u8) IdentityElementError!KeyPair {
45 const ss = seed orelse ss: {52 const ss = seed orelse ss: {
46 var random_seed: [seed_length]u8 = undefined;53 var random_seed: [seed_length]u8 = undefined;
47 crypto.random.bytes(&random_seed);54 crypto.random.bytes(&random_seed);
...@@ -51,7 +58,7 @@ pub const Ed25519 = struct {...@@ -51,7 +58,7 @@ pub const Ed25519 = struct {
51 var h = Sha512.init(.{});58 var h = Sha512.init(.{});
52 h.update(&ss);59 h.update(&ss);
53 h.final(&az);60 h.final(&az);
54 const p = try Curve.basePoint.clampedMul(az[0..32].*);61 const p = Curve.basePoint.clampedMul(az[0..32].*) catch return error.IdentityElement;
55 var sk: [secret_length]u8 = undefined;62 var sk: [secret_length]u8 = undefined;
56 mem.copy(u8, &sk, &ss);63 mem.copy(u8, &sk, &ss);
57 const pk = p.toBytes();64 const pk = p.toBytes();
...@@ -72,7 +79,7 @@ pub const Ed25519 = struct {...@@ -72,7 +79,7 @@ pub const Ed25519 = struct {
72 /// Sign a message using a key pair, and optional random noise.79 /// Sign a message using a key pair, and optional random noise.
73 /// Having noise creates non-standard, non-deterministic signatures,80 /// Having noise creates non-standard, non-deterministic signatures,
74 /// but has been proven to increase resilience against fault attacks.81 /// but has been proven to increase resilience against fault attacks.
75 pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) Error![signature_length]u8 {82 pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) (IdentityElementError || WeakPublicKeyError || KeyMismatchError)![signature_length]u8 {
76 const seed = key_pair.secret_key[0..seed_length];83 const seed = key_pair.secret_key[0..seed_length];
77 const public_key = key_pair.secret_key[seed_length..];84 const public_key = key_pair.secret_key[seed_length..];
78 if (!mem.eql(u8, public_key, &key_pair.public_key)) {85 if (!mem.eql(u8, public_key, &key_pair.public_key)) {
...@@ -113,7 +120,7 @@ pub const Ed25519 = struct {...@@ -113,7 +120,7 @@ pub const Ed25519 = struct {
113120
114 /// Verify an Ed25519 signature given a message and a public key.121 /// Verify an Ed25519 signature given a message and a public key.
115 /// Returns error.SignatureVerificationFailed is the signature verification failed.122 /// Returns error.SignatureVerificationFailed is the signature verification failed.
116 pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) Error!void {123 pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) (SignatureVerificationError || WeakPublicKeyError || EncodingError || NonCanonicalError || IdentityElementError)!void {
117 const r = sig[0..32];124 const r = sig[0..32];
118 const s = sig[32..64];125 const s = sig[32..64];
119 try Curve.scalar.rejectNonCanonical(s.*);126 try Curve.scalar.rejectNonCanonical(s.*);
...@@ -146,7 +153,7 @@ pub const Ed25519 = struct {...@@ -146,7 +153,7 @@ pub const Ed25519 = struct {
146 };153 };
147154
148 /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one155 /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one
149 pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) Error!void {156 pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void {
150 var r_batch: [count][32]u8 = undefined;157 var r_batch: [count][32]u8 = undefined;
151 var s_batch: [count][32]u8 = undefined;158 var s_batch: [count][32]u8 = undefined;
152 var a_batch: [count]Curve = undefined;159 var a_batch: [count]Curve = undefined;
...@@ -180,7 +187,7 @@ pub const Ed25519 = struct {...@@ -180,7 +187,7 @@ pub const Ed25519 = struct {
180187
181 var z_batch: [count]Curve.scalar.CompressedScalar = undefined;188 var z_batch: [count]Curve.scalar.CompressedScalar = undefined;
182 for (z_batch) |*z| {189 for (z_batch) |*z| {
183 std.crypto.random.bytes(z[0..16]);190 crypto.random.bytes(z[0..16]);
184 mem.set(u8, z[16..], 0);191 mem.set(u8, z[16..], 0);
185 }192 }
186193
...@@ -233,8 +240,8 @@ test "ed25519 batch verification" {...@@ -233,8 +240,8 @@ test "ed25519 batch verification" {
233 const key_pair = try Ed25519.KeyPair.create(null);240 const key_pair = try Ed25519.KeyPair.create(null);
234 var msg1: [32]u8 = undefined;241 var msg1: [32]u8 = undefined;
235 var msg2: [32]u8 = undefined;242 var msg2: [32]u8 = undefined;
236 std.crypto.random.bytes(&msg1);243 crypto.random.bytes(&msg1);
237 std.crypto.random.bytes(&msg2);244 crypto.random.bytes(&msg2);
238 const sig1 = try Ed25519.sign(&msg1, key_pair, null);245 const sig1 = try Ed25519.sign(&msg1, key_pair, null);
239 const sig2 = try Ed25519.sign(&msg2, key_pair, null);246 const sig2 = try Ed25519.sign(&msg2, key_pair, null);
240 var signature_batch = [_]Ed25519.BatchElement{247 var signature_batch = [_]Ed25519.BatchElement{
lib/std/crypto/25519/edwards25519.zig+23-17
...@@ -4,10 +4,16 @@...@@ -4,10 +4,16 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const crypto = std.crypto;
7const debug = std.debug;8const debug = std.debug;
8const fmt = std.fmt;9const fmt = std.fmt;
9const mem = std.mem;10const mem = std.mem;
10const Error = std.crypto.Error;11
12const EncodingError = crypto.errors.EncodingError;
13const IdentityElementError = crypto.errors.IdentityElementError;
14const NonCanonicalError = crypto.errors.NonCanonicalError;
15const NotSquareError = crypto.errors.NotSquareError;
16const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
1117
12/// Group operations over Edwards25519.18/// Group operations over Edwards25519.
13pub const Edwards25519 = struct {19pub const Edwards25519 = struct {
...@@ -26,7 +32,7 @@ pub const Edwards25519 = struct {...@@ -26,7 +32,7 @@ pub const Edwards25519 = struct {
26 is_base: bool = false,32 is_base: bool = false,
2733
28 /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates.34 /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates.
29 pub fn fromBytes(s: [encoded_length]u8) Error!Edwards25519 {35 pub fn fromBytes(s: [encoded_length]u8) EncodingError!Edwards25519 {
30 const z = Fe.one;36 const z = Fe.one;
31 const y = Fe.fromBytes(s);37 const y = Fe.fromBytes(s);
32 var u = y.sq();38 var u = y.sq();
...@@ -56,7 +62,7 @@ pub const Edwards25519 = struct {...@@ -56,7 +62,7 @@ pub const Edwards25519 = struct {
56 }62 }
5763
58 /// Check that the encoding of a point is canonical.64 /// Check that the encoding of a point is canonical.
59 pub fn rejectNonCanonical(s: [32]u8) Error!void {65 pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
60 return Fe.rejectNonCanonical(s, true);66 return Fe.rejectNonCanonical(s, true);
61 }67 }
6268
...@@ -81,7 +87,7 @@ pub const Edwards25519 = struct {...@@ -81,7 +87,7 @@ pub const Edwards25519 = struct {
81 const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };87 const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };
8288
83 /// Reject the neutral element.89 /// Reject the neutral element.
84 pub fn rejectIdentity(p: Edwards25519) Error!void {90 pub fn rejectIdentity(p: Edwards25519) IdentityElementError!void {
85 if (p.x.isZero()) {91 if (p.x.isZero()) {
86 return error.IdentityElement;92 return error.IdentityElement;
87 }93 }
...@@ -177,7 +183,7 @@ pub const Edwards25519 = struct {...@@ -177,7 +183,7 @@ pub const Edwards25519 = struct {
177 // Based on real-world benchmarks, we only use this for multi-scalar multiplication.183 // Based on real-world benchmarks, we only use this for multi-scalar multiplication.
178 // NAF could be useful to half the size of precomputation tables, but we intentionally184 // NAF could be useful to half the size of precomputation tables, but we intentionally
179 // avoid these to keep the standard library lightweight.185 // avoid these to keep the standard library lightweight.
180 fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 {186 fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 {
181 std.debug.assert(vartime);187 std.debug.assert(vartime);
182 const e = nonAdjacentForm(s);188 const e = nonAdjacentForm(s);
183 var q = Edwards25519.identityElement;189 var q = Edwards25519.identityElement;
...@@ -197,7 +203,7 @@ pub const Edwards25519 = struct {...@@ -197,7 +203,7 @@ pub const Edwards25519 = struct {
197 }203 }
198204
199 // Scalar multiplication with a 4-bit window and the first 15 multiples.205 // Scalar multiplication with a 4-bit window and the first 15 multiples.
200 fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 {206 fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 {
201 var q = Edwards25519.identityElement;207 var q = Edwards25519.identityElement;
202 var pos: usize = 252;208 var pos: usize = 252;
203 while (true) : (pos -= 4) {209 while (true) : (pos -= 4) {
...@@ -233,12 +239,12 @@ pub const Edwards25519 = struct {...@@ -233,12 +239,12 @@ pub const Edwards25519 = struct {
233 };239 };
234240
235 /// Multiply an Edwards25519 point by a scalar without clamping it.241 /// Multiply an Edwards25519 point by a scalar without clamping it.
236 /// Return error.WeakPublicKey if the resulting point is242 /// Return error.WeakPublicKey if the base generates a small-order group,
237 /// the identity element.243 /// and error.IdentityElement if the result is the identity element.
238 pub fn mul(p: Edwards25519, s: [32]u8) Error!Edwards25519 {244 pub fn mul(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
239 const pc = if (p.is_base) basePointPc else pc: {245 const pc = if (p.is_base) basePointPc else pc: {
240 const xpc = precompute(p, 15);246 const xpc = precompute(p, 15);
241 xpc[4].rejectIdentity() catch |_| return error.WeakPublicKey;247 xpc[4].rejectIdentity() catch return error.WeakPublicKey;
242 break :pc xpc;248 break :pc xpc;
243 };249 };
244 return pcMul16(pc, s, false);250 return pcMul16(pc, s, false);
...@@ -246,7 +252,7 @@ pub const Edwards25519 = struct {...@@ -246,7 +252,7 @@ pub const Edwards25519 = struct {
246252
247 /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME*253 /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME*
248 /// This can be used for signature verification.254 /// This can be used for signature verification.
249 pub fn mulPublic(p: Edwards25519, s: [32]u8) Error!Edwards25519 {255 pub fn mulPublic(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
250 if (p.is_base) {256 if (p.is_base) {
251 return pcMul16(basePointPc, s, true);257 return pcMul16(basePointPc, s, true);
252 } else {258 } else {
...@@ -258,7 +264,7 @@ pub const Edwards25519 = struct {...@@ -258,7 +264,7 @@ pub const Edwards25519 = struct {
258264
259 /// Multiscalar multiplication *IN VARIABLE TIME* for public data265 /// Multiscalar multiplication *IN VARIABLE TIME* for public data
260 /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually266 /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually
261 pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) Error!Edwards25519 {267 pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
262 var pcs: [count][9]Edwards25519 = undefined;268 var pcs: [count][9]Edwards25519 = undefined;
263 for (ps) |p, i| {269 for (ps) |p, i| {
264 if (p.is_base) {270 if (p.is_base) {
...@@ -297,14 +303,14 @@ pub const Edwards25519 = struct {...@@ -297,14 +303,14 @@ pub const Edwards25519 = struct {
297 /// This is strongly recommended for DH operations.303 /// This is strongly recommended for DH operations.
298 /// Return error.WeakPublicKey if the resulting point is304 /// Return error.WeakPublicKey if the resulting point is
299 /// the identity element.305 /// the identity element.
300 pub fn clampedMul(p: Edwards25519, s: [32]u8) Error!Edwards25519 {306 pub fn clampedMul(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
301 var t: [32]u8 = s;307 var t: [32]u8 = s;
302 scalar.clamp(&t);308 scalar.clamp(&t);
303 return mul(p, t);309 return mul(p, t);
304 }310 }
305311
306 // montgomery -- recover y = sqrt(x^3 + A*x^2 + x)312 // montgomery -- recover y = sqrt(x^3 + A*x^2 + x)
307 fn xmontToYmont(x: Fe) Error!Fe {313 fn xmontToYmont(x: Fe) NotSquareError!Fe {
308 var x2 = x.sq();314 var x2 = x.sq();
309 const x3 = x.mul(x2);315 const x3 = x.mul(x2);
310 x2 = x2.mul32(Fe.edwards25519a_32);316 x2 = x2.mul32(Fe.edwards25519a_32);
...@@ -367,7 +373,7 @@ pub const Edwards25519 = struct {...@@ -367,7 +373,7 @@ pub const Edwards25519 = struct {
367373
368 fn stringToPoints(comptime n: usize, ctx: []const u8, s: []const u8) [n]Edwards25519 {374 fn stringToPoints(comptime n: usize, ctx: []const u8, s: []const u8) [n]Edwards25519 {
369 debug.assert(n <= 2);375 debug.assert(n <= 2);
370 const H = std.crypto.hash.sha2.Sha512;376 const H = crypto.hash.sha2.Sha512;
371 const h_l: usize = 48;377 const h_l: usize = 48;
372 var xctx = ctx;378 var xctx = ctx;
373 var hctx: [H.digest_length]u8 = undefined;379 var hctx: [H.digest_length]u8 = undefined;
...@@ -485,8 +491,8 @@ test "edwards25519 packing/unpacking" {...@@ -485,8 +491,8 @@ test "edwards25519 packing/unpacking" {
485test "edwards25519 point addition/substraction" {491test "edwards25519 point addition/substraction" {
486 var s1: [32]u8 = undefined;492 var s1: [32]u8 = undefined;
487 var s2: [32]u8 = undefined;493 var s2: [32]u8 = undefined;
488 std.crypto.random.bytes(&s1);494 crypto.random.bytes(&s1);
489 std.crypto.random.bytes(&s2);495 crypto.random.bytes(&s2);
490 const p = try Edwards25519.basePoint.clampedMul(s1);496 const p = try Edwards25519.basePoint.clampedMul(s1);
491 const q = try Edwards25519.basePoint.clampedMul(s2);497 const q = try Edwards25519.basePoint.clampedMul(s2);
492 const r = p.add(q).add(q).sub(q).sub(q);498 const r = p.add(q).add(q).sub(q).sub(q);
lib/std/crypto/25519/field.zig+6-3
...@@ -4,9 +4,12 @@...@@ -4,9 +4,12 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const crypto = std.crypto;
7const readIntLittle = std.mem.readIntLittle;8const readIntLittle = std.mem.readIntLittle;
8const writeIntLittle = std.mem.writeIntLittle;9const writeIntLittle = std.mem.writeIntLittle;
9const Error = std.crypto.Error;10
11const NonCanonicalError = crypto.errors.NonCanonicalError;
12const NotSquareError = crypto.errors.NotSquareError;
1013
11pub const Fe = struct {14pub const Fe = struct {
12 limbs: [5]u64,15 limbs: [5]u64,
...@@ -113,7 +116,7 @@ pub const Fe = struct {...@@ -113,7 +116,7 @@ pub const Fe = struct {
113 }116 }
114117
115 /// Reject non-canonical encodings of an element, possibly ignoring the top bit118 /// Reject non-canonical encodings of an element, possibly ignoring the top bit
116 pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) Error!void {119 pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) NonCanonicalError!void {
117 var c: u16 = (s[31] & 0x7f) ^ 0x7f;120 var c: u16 = (s[31] & 0x7f) ^ 0x7f;
118 comptime var i = 30;121 comptime var i = 30;
119 inline while (i > 0) : (i -= 1) {122 inline while (i > 0) : (i -= 1) {
...@@ -413,7 +416,7 @@ pub const Fe = struct {...@@ -413,7 +416,7 @@ pub const Fe = struct {
413 }416 }
414417
415 /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square418 /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square
416 pub fn sqrt(x2: Fe) Error!Fe {419 pub fn sqrt(x2: Fe) NotSquareError!Fe {
417 var x2_copy = x2;420 var x2_copy = x2;
418 const x = x2.uncheckedSqrt();421 const x = x2.uncheckedSqrt();
419 const check = x.sq().sub(x2_copy);422 const check = x.sq().sub(x2_copy);
lib/std/crypto/25519/ristretto255.zig+9-5
...@@ -5,7 +5,11 @@...@@ -5,7 +5,11 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const fmt = std.fmt;7const fmt = std.fmt;
8const Error = std.crypto.Error;8
9const EncodingError = std.crypto.errors.EncodingError;
10const IdentityElementError = std.crypto.errors.IdentityElementError;
11const NonCanonicalError = std.crypto.errors.NonCanonicalError;
12const WeakPublicKeyError = std.crypto.errors.WeakPublicKeyError;
913
10/// Group operations over Edwards25519.14/// Group operations over Edwards25519.
11pub const Ristretto255 = struct {15pub const Ristretto255 = struct {
...@@ -35,7 +39,7 @@ pub const Ristretto255 = struct {...@@ -35,7 +39,7 @@ pub const Ristretto255 = struct {
35 return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() };39 return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() };
36 }40 }
3741
38 fn rejectNonCanonical(s: [encoded_length]u8) Error!void {42 fn rejectNonCanonical(s: [encoded_length]u8) NonCanonicalError!void {
39 if ((s[0] & 1) != 0) {43 if ((s[0] & 1) != 0) {
40 return error.NonCanonical;44 return error.NonCanonical;
41 }45 }
...@@ -43,7 +47,7 @@ pub const Ristretto255 = struct {...@@ -43,7 +47,7 @@ pub const Ristretto255 = struct {
43 }47 }
4448
45 /// Reject the neutral element.49 /// Reject the neutral element.
46 pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) Error!void {50 pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) IdentityElementError!void {
47 return p.p.rejectIdentity();51 return p.p.rejectIdentity();
48 }52 }
4953
...@@ -51,7 +55,7 @@ pub const Ristretto255 = struct {...@@ -51,7 +55,7 @@ pub const Ristretto255 = struct {
51 pub const basePoint = Ristretto255{ .p = Curve.basePoint };55 pub const basePoint = Ristretto255{ .p = Curve.basePoint };
5256
53 /// Decode a Ristretto255 representative.57 /// Decode a Ristretto255 representative.
54 pub fn fromBytes(s: [encoded_length]u8) Error!Ristretto255 {58 pub fn fromBytes(s: [encoded_length]u8) (NonCanonicalError || EncodingError)!Ristretto255 {
55 try rejectNonCanonical(s);59 try rejectNonCanonical(s);
56 const s_ = Fe.fromBytes(s);60 const s_ = Fe.fromBytes(s);
57 const ss = s_.sq(); // s^261 const ss = s_.sq(); // s^2
...@@ -154,7 +158,7 @@ pub const Ristretto255 = struct {...@@ -154,7 +158,7 @@ pub const Ristretto255 = struct {
154 /// Multiply a Ristretto255 element with a scalar.158 /// Multiply a Ristretto255 element with a scalar.
155 /// Return error.WeakPublicKey if the resulting element is159 /// Return error.WeakPublicKey if the resulting element is
156 /// the identity element.160 /// the identity element.
157 pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) Error!Ristretto255 {161 pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) (IdentityElementError || WeakPublicKeyError)!Ristretto255 {
158 return Ristretto255{ .p = try p.p.mul(s) };162 return Ristretto255{ .p = try p.p.mul(s) };
159 }163 }
160164
lib/std/crypto/25519/scalar.zig+3-2
...@@ -5,7 +5,8 @@...@@ -5,7 +5,8 @@
5// and substantial portions of the software.5// and substantial portions of the software.
6const std = @import("std");6const std = @import("std");
7const mem = std.mem;7const mem = std.mem;
8const Error = std.crypto.Error;8
9const NonCanonicalError = std.crypto.errors.NonCanonicalError;
910
10/// 2^252 + 2774231777737235353585193779088364849311/// 2^252 + 27742317777372353535851937790883648493
11pub const field_size = [32]u8{12pub const field_size = [32]u8{
...@@ -19,7 +20,7 @@ pub const CompressedScalar = [32]u8;...@@ -19,7 +20,7 @@ pub const CompressedScalar = [32]u8;
19pub const zero = [_]u8{0} ** 32;20pub const zero = [_]u8{0} ** 32;
2021
21/// Reject a scalar whose encoding is not canonical.22/// Reject a scalar whose encoding is not canonical.
22pub fn rejectNonCanonical(s: [32]u8) Error!void {23pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
23 var c: u8 = 0;24 var c: u8 = 0;
24 var n: u8 = 1;25 var n: u8 = 1;
25 var i: usize = 31;26 var i: usize = 31;
lib/std/crypto/25519/x25519.zig+9-6
...@@ -9,7 +9,10 @@ const mem = std.mem;...@@ -9,7 +9,10 @@ const mem = std.mem;
9const fmt = std.fmt;9const fmt = std.fmt;
1010
11const Sha512 = crypto.hash.sha2.Sha512;11const Sha512 = crypto.hash.sha2.Sha512;
12const Error = crypto.Error;12
13const EncodingError = crypto.errors.EncodingError;
14const IdentityElementError = crypto.errors.IdentityElementError;
15const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
1316
14/// X25519 DH function.17/// X25519 DH function.
15pub const X25519 = struct {18pub const X25519 = struct {
...@@ -32,7 +35,7 @@ pub const X25519 = struct {...@@ -32,7 +35,7 @@ pub const X25519 = struct {
32 secret_key: [secret_length]u8,35 secret_key: [secret_length]u8,
3336
34 /// Create a new key pair using an optional seed.37 /// Create a new key pair using an optional seed.
35 pub fn create(seed: ?[seed_length]u8) Error!KeyPair {38 pub fn create(seed: ?[seed_length]u8) IdentityElementError!KeyPair {
36 const sk = seed orelse sk: {39 const sk = seed orelse sk: {
37 var random_seed: [seed_length]u8 = undefined;40 var random_seed: [seed_length]u8 = undefined;
38 crypto.random.bytes(&random_seed);41 crypto.random.bytes(&random_seed);
...@@ -45,7 +48,7 @@ pub const X25519 = struct {...@@ -45,7 +48,7 @@ pub const X25519 = struct {
45 }48 }
4649
47 /// Create a key pair from an Ed25519 key pair50 /// Create a key pair from an Ed25519 key pair
48 pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) Error!KeyPair {51 pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) (IdentityElementError || EncodingError)!KeyPair {
49 const seed = ed25519_key_pair.secret_key[0..32];52 const seed = ed25519_key_pair.secret_key[0..32];
50 var az: [Sha512.digest_length]u8 = undefined;53 var az: [Sha512.digest_length]u8 = undefined;
51 Sha512.hash(seed, &az, .{});54 Sha512.hash(seed, &az, .{});
...@@ -60,13 +63,13 @@ pub const X25519 = struct {...@@ -60,13 +63,13 @@ pub const X25519 = struct {
60 };63 };
6164
62 /// Compute the public key for a given private key.65 /// Compute the public key for a given private key.
63 pub fn recoverPublicKey(secret_key: [secret_length]u8) Error![public_length]u8 {66 pub fn recoverPublicKey(secret_key: [secret_length]u8) IdentityElementError![public_length]u8 {
64 const q = try Curve.basePoint.clampedMul(secret_key);67 const q = try Curve.basePoint.clampedMul(secret_key);
65 return q.toBytes();68 return q.toBytes();
66 }69 }
6770
68 /// Compute the X25519 equivalent to an Ed25519 public eky.71 /// Compute the X25519 equivalent to an Ed25519 public eky.
69 pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) Error![public_length]u8 {72 pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) (IdentityElementError || EncodingError)![public_length]u8 {
70 const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key);73 const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key);
71 const pk = try Curve.fromEdwards25519(pk_ed);74 const pk = try Curve.fromEdwards25519(pk_ed);
72 return pk.toBytes();75 return pk.toBytes();
...@@ -75,7 +78,7 @@ pub const X25519 = struct {...@@ -75,7 +78,7 @@ pub const X25519 = struct {
75 /// Compute the scalar product of a public key and a secret scalar.78 /// Compute the scalar product of a public key and a secret scalar.
76 /// Note that the output should not be used as a shared secret without79 /// Note that the output should not be used as a shared secret without
77 /// hashing it first.80 /// hashing it first.
78 pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) Error![shared_length]u8 {81 pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) IdentityElementError![shared_length]u8 {
79 const q = try Curve.fromBytes(public_key).clampedMul(secret_key);82 const q = try Curve.fromBytes(public_key).clampedMul(secret_key);
80 return q.toBytes();83 return q.toBytes();
81 }84 }
lib/std/crypto/aegis.zig+3-3
...@@ -8,7 +8,7 @@ const std = @import("std");...@@ -8,7 +8,7 @@ const std = @import("std");
8const mem = std.mem;8const mem = std.mem;
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const AesBlock = std.crypto.core.aes.Block;10const AesBlock = std.crypto.core.aes.Block;
11const Error = std.crypto.Error;11const AuthenticationError = std.crypto.errors.AuthenticationError;
1212
13const State128L = struct {13const State128L = struct {
14 blocks: [8]AesBlock,14 blocks: [8]AesBlock,
...@@ -137,7 +137,7 @@ pub const Aegis128L = struct {...@@ -137,7 +137,7 @@ pub const Aegis128L = struct {
137 /// ad: Associated Data137 /// ad: Associated Data
138 /// npub: public nonce138 /// npub: public nonce
139 /// k: private key139 /// k: private key
140 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {140 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
141 assert(c.len == m.len);141 assert(c.len == m.len);
142 var state = State128L.init(key, npub);142 var state = State128L.init(key, npub);
143 var src: [32]u8 align(16) = undefined;143 var src: [32]u8 align(16) = undefined;
...@@ -299,7 +299,7 @@ pub const Aegis256 = struct {...@@ -299,7 +299,7 @@ pub const Aegis256 = struct {
299 /// ad: Associated Data299 /// ad: Associated Data
300 /// npub: public nonce300 /// npub: public nonce
301 /// k: private key301 /// k: private key
302 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {302 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
303 assert(c.len == m.len);303 assert(c.len == m.len);
304 var state = State256.init(key, npub);304 var state = State256.init(key, npub);
305 var src: [16]u8 align(16) = undefined;305 var src: [16]u8 align(16) = undefined;
lib/std/crypto/aes_gcm.zig+2-2
...@@ -12,7 +12,7 @@ const debug = std.debug;...@@ -12,7 +12,7 @@ const debug = std.debug;
12const Ghash = std.crypto.onetimeauth.Ghash;12const Ghash = std.crypto.onetimeauth.Ghash;
13const mem = std.mem;13const mem = std.mem;
14const modes = crypto.core.modes;14const modes = crypto.core.modes;
15const Error = crypto.Error;15const AuthenticationError = crypto.errors.AuthenticationError;
1616
17pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128);17pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128);
18pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256);18pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256);
...@@ -60,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type {...@@ -60,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type {
60 }60 }
61 }61 }
6262
63 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {63 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
64 assert(c.len == m.len);64 assert(c.len == m.len);
6565
66 const aes = Aes.initEnc(key);66 const aes = Aes.initEnc(key);
lib/std/crypto/aes_ocb.zig+2-2
...@@ -10,7 +10,7 @@ const aes = crypto.core.aes;...@@ -10,7 +10,7 @@ const aes = crypto.core.aes;
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const math = std.math;11const math = std.math;
12const mem = std.mem;12const mem = std.mem;
13const Error = crypto.Error;13const AuthenticationError = crypto.errors.AuthenticationError;
1414
15pub const Aes128Ocb = AesOcb(aes.Aes128);15pub const Aes128Ocb = AesOcb(aes.Aes128);
16pub const Aes256Ocb = AesOcb(aes.Aes256);16pub const Aes256Ocb = AesOcb(aes.Aes256);
...@@ -179,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type {...@@ -179,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type {
179 /// ad: Associated Data179 /// ad: Associated Data
180 /// npub: public nonce180 /// npub: public nonce
181 /// k: secret key181 /// k: secret key
182 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {182 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
183 assert(c.len == m.len);183 assert(c.len == m.len);
184184
185 const aes_enc_ctx = Aes.initEnc(key);185 const aes_enc_ctx = Aes.initEnc(key);
lib/std/crypto/bcrypt.zig+6-5
...@@ -12,7 +12,8 @@ const mem = std.mem;...@@ -12,7 +12,8 @@ const mem = std.mem;
12const debug = std.debug;12const debug = std.debug;
13const testing = std.testing;13const testing = std.testing;
14const utils = crypto.utils;14const utils = crypto.utils;
15const Error = crypto.Error;15const EncodingError = crypto.errors.EncodingError;
16const PasswordVerificationError = crypto.errors.PasswordVerificationError;
1617
17const salt_length: usize = 16;18const salt_length: usize = 16;
18const salt_str_length: usize = 22;19const salt_str_length: usize = 22;
...@@ -179,7 +180,7 @@ const Codec = struct {...@@ -179,7 +180,7 @@ const Codec = struct {
179 debug.assert(j == b64.len);180 debug.assert(j == b64.len);
180 }181 }
181182
182 fn decode(bin: []u8, b64: []const u8) Error!void {183 fn decode(bin: []u8, b64: []const u8) EncodingError!void {
183 var i: usize = 0;184 var i: usize = 0;
184 var j: usize = 0;185 var j: usize = 0;
185 while (j < bin.len) {186 while (j < bin.len) {
...@@ -204,7 +205,7 @@ const Codec = struct {...@@ -204,7 +205,7 @@ const Codec = struct {
204 }205 }
205};206};
206207
207fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) Error![hash_length]u8 {208fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) ![hash_length]u8 {
208 var state = State{};209 var state = State{};
209 var password_buf: [73]u8 = undefined;210 var password_buf: [73]u8 = undefined;
210 const trimmed_len = math.min(password.len, password_buf.len - 1);211 const trimmed_len = math.min(password.len, password_buf.len - 1);
...@@ -252,14 +253,14 @@ fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8)...@@ -252,14 +253,14 @@ fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8)
252/// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes.253/// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes.
253/// If this is an issue for your application, hash the password first using a function such as SHA-512,254/// If this is an issue for your application, hash the password first using a function such as SHA-512,
254/// and then use the resulting hash as the password parameter for bcrypt.255/// and then use the resulting hash as the password parameter for bcrypt.
255pub fn strHash(password: []const u8, rounds_log: u6) Error![hash_length]u8 {256pub fn strHash(password: []const u8, rounds_log: u6) ![hash_length]u8 {
256 var salt: [salt_length]u8 = undefined;257 var salt: [salt_length]u8 = undefined;
257 crypto.random.bytes(&salt);258 crypto.random.bytes(&salt);
258 return strHashInternal(password, rounds_log, salt);259 return strHashInternal(password, rounds_log, salt);
259}260}
260261
261/// Verify that a previously computed hash is valid for a given password.262/// Verify that a previously computed hash is valid for a given password.
262pub fn strVerify(h: [hash_length]u8, password: []const u8) Error!void {263pub fn strVerify(h: [hash_length]u8, password: []const u8) (EncodingError || PasswordVerificationError)!void {
263 if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding;264 if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding;
264 if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding;265 if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding;
265 const rounds_log_str = h[4..][0..2];266 const rounds_log_str = h[4..][0..2];
lib/std/crypto/chacha20.zig+3-3
...@@ -13,7 +13,7 @@ const testing = std.testing;...@@ -13,7 +13,7 @@ const testing = std.testing;
13const maxInt = math.maxInt;13const maxInt = math.maxInt;
14const Vector = std.meta.Vector;14const Vector = std.meta.Vector;
15const Poly1305 = std.crypto.onetimeauth.Poly1305;15const Poly1305 = std.crypto.onetimeauth.Poly1305;
16const Error = std.crypto.Error;16const AuthenticationError = std.crypto.errors.AuthenticationError;
1717
18/// IETF-variant of the ChaCha20 stream cipher, as designed for TLS.18/// IETF-variant of the ChaCha20 stream cipher, as designed for TLS.
19pub const ChaCha20IETF = ChaChaIETF(20);19pub const ChaCha20IETF = ChaChaIETF(20);
...@@ -521,7 +521,7 @@ fn ChaChaPoly1305(comptime rounds_nb: usize) type {...@@ -521,7 +521,7 @@ fn ChaChaPoly1305(comptime rounds_nb: usize) type {
521 /// npub: public nonce521 /// npub: public nonce
522 /// k: private key522 /// k: private key
523 /// NOTE: the check of the authentication tag is currently not done in constant time523 /// NOTE: the check of the authentication tag is currently not done in constant time
524 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {524 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
525 assert(c.len == m.len);525 assert(c.len == m.len);
526526
527 var polyKey = [_]u8{0} ** 32;527 var polyKey = [_]u8{0} ** 32;
...@@ -583,7 +583,7 @@ fn XChaChaPoly1305(comptime rounds_nb: usize) type {...@@ -583,7 +583,7 @@ fn XChaChaPoly1305(comptime rounds_nb: usize) type {
583 /// ad: Associated Data583 /// ad: Associated Data
584 /// npub: public nonce584 /// npub: public nonce
585 /// k: private key585 /// k: private key
586 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {586 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
587 const extended = extend(k, npub, rounds_nb);587 const extended = extend(k, npub, rounds_nb);
588 return ChaChaPoly1305(rounds_nb).decrypt(m, c, tag, ad, extended.nonce, extended.key);588 return ChaChaPoly1305(rounds_nb).decrypt(m, c, tag, ad, extended.nonce, extended.key);
589 }589 }
lib/std/crypto/error.zig deleted-34
...@@ -1,34 +0,0 @@
1pub const Error = error{
2 /// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key
3 AuthenticationFailed,
4
5 /// The requested output length is too long for the chosen algorithm
6 OutputTooLong,
7
8 /// Finite field operation returned the identity element
9 IdentityElement,
10
11 /// Encoded input cannot be decoded
12 InvalidEncoding,
13
14 /// The signature does't verify for the given message and public key
15 SignatureVerificationFailed,
16
17 /// Both a public and secret key have been provided, but they are incompatible
18 KeyMismatch,
19
20 /// Encoded input is not in canonical form
21 NonCanonical,
22
23 /// Square root has no solutions
24 NotSquare,
25
26 /// Verification string doesn't match the provided password and parameters
27 PasswordVerificationFailed,
28
29 /// Parameters would be insecure to use
30 WeakParameters,
31
32 /// Public key would be insecure to use
33 WeakPublicKey,
34};
lib/std/crypto/errors.zig created+35
...@@ -0,0 +1,35 @@
1/// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key
2pub const AuthenticationError = error{AuthenticationFailed};
3
4/// The requested output length is too long for the chosen algorithm
5pub const OutputTooLongError = error{OutputTooLong};
6
7/// Finite field operation returned the identity element
8pub const IdentityElementError = error{IdentityElement};
9
10/// Encoded input cannot be decoded
11pub const EncodingError = error{InvalidEncoding};
12
13/// The signature does't verify for the given message and public key
14pub const SignatureVerificationError = error{SignatureVerificationFailed};
15
16/// Both a public and secret key have been provided, but they are incompatible
17pub const KeyMismatchError = error{KeyMismatch};
18
19/// Encoded input is not in canonical form
20pub const NonCanonicalError = error{NonCanonical};
21
22/// Square root has no solutions
23pub const NotSquareError = error{NotSquare};
24
25/// Verification string doesn't match the provided password and parameters
26pub const PasswordVerificationError = error{PasswordVerificationFailed};
27
28/// Parameters would be insecure to use
29pub const WeakParametersError = error{WeakParameters};
30
31/// Public key would be insecure to use
32pub const WeakPublicKeyError = error{WeakPublicKey};
33
34/// Any error related to cryptography operations
35pub const Error = AuthenticationError || OutputTooLongError || IdentityElementError || EncodingError || SignatureVerificationError || KeyMismatchError || NonCanonicalError || NotSquareError || PasswordVerificationError || WeakParametersError || WeakPublicKeyError;
lib/std/crypto/gimli.zig+2-2
...@@ -20,7 +20,7 @@ const assert = std.debug.assert;...@@ -20,7 +20,7 @@ const assert = std.debug.assert;
20const testing = std.testing;20const testing = std.testing;
21const htest = @import("test.zig");21const htest = @import("test.zig");
22const Vector = std.meta.Vector;22const Vector = std.meta.Vector;
23const Error = std.crypto.Error;23const AuthenticationError = std.crypto.errors.AuthenticationError;
2424
25pub const State = struct {25pub const State = struct {
26 pub const BLOCKBYTES = 48;26 pub const BLOCKBYTES = 48;
...@@ -393,7 +393,7 @@ pub const Aead = struct {...@@ -393,7 +393,7 @@ pub const Aead = struct {
393 /// npub: public nonce393 /// npub: public nonce
394 /// k: private key394 /// k: private key
395 /// NOTE: the check of the authentication tag is currently not done in constant time395 /// NOTE: the check of the authentication tag is currently not done in constant time
396 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {396 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
397 assert(c.len == m.len);397 assert(c.len == m.len);
398398
399 var state = Aead.init(ad, npub, k);399 var state = Aead.init(ad, npub, k);
lib/std/crypto/isap.zig+2-2
...@@ -3,7 +3,7 @@ const debug = std.debug;...@@ -3,7 +3,7 @@ const debug = std.debug;
3const mem = std.mem;3const mem = std.mem;
4const math = std.math;4const math = std.math;
5const testing = std.testing;5const testing = std.testing;
6const Error = std.crypto.Error;6const AuthenticationError = std.crypto.errors.AuthenticationError;
77
8/// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks.8/// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks.
9/// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/isap-spec-round2.pdf9/// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/isap-spec-round2.pdf
...@@ -218,7 +218,7 @@ pub const IsapA128A = struct {...@@ -218,7 +218,7 @@ pub const IsapA128A = struct {
218 tag.* = mac(c, ad, npub, key);218 tag.* = mac(c, ad, npub, key);
219 }219 }
220220
221 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {221 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
222 var computed_tag = mac(c, ad, npub, key);222 var computed_tag = mac(c, ad, npub, key);
223 var acc: u8 = 0;223 var acc: u8 = 0;
224 for (computed_tag) |_, j| {224 for (computed_tag) |_, j| {
lib/std/crypto/pbkdf2.zig+3-2
...@@ -7,7 +7,8 @@...@@ -7,7 +7,8 @@
7const std = @import("std");7const std = @import("std");
8const mem = std.mem;8const mem = std.mem;
9const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
10const Error = std.crypto.Error;10const OutputTooLongError = std.crypto.errors.OutputTooLongError;
11const WeakParametersError = std.crypto.errors.WeakParametersError;
1112
12// RFC 2898 Section 5.213// RFC 2898 Section 5.2
13//14//
...@@ -55,7 +56,7 @@ const Error = std.crypto.Error;...@@ -55,7 +56,7 @@ const Error = std.crypto.Error;
55/// the dk. It is common to tune this parameter to achieve approximately 100ms.56/// the dk. It is common to tune this parameter to achieve approximately 100ms.
56///57///
57/// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`.58/// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`.
58pub fn pbkdf2(dk: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) Error!void {59pub fn pbkdf2(dk: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) (WeakParametersError || OutputTooLongError)!void {
59 if (rounds < 1) return error.WeakParameters;60 if (rounds < 1) return error.WeakParameters;
6061
61 const dk_len = dk.len;62 const dk_len = dk.len;
lib/std/crypto/salsa20.zig+11-8
...@@ -15,7 +15,10 @@ const Vector = std.meta.Vector;...@@ -15,7 +15,10 @@ const Vector = std.meta.Vector;
15const Poly1305 = crypto.onetimeauth.Poly1305;15const Poly1305 = crypto.onetimeauth.Poly1305;
16const Blake2b = crypto.hash.blake2.Blake2b;16const Blake2b = crypto.hash.blake2.Blake2b;
17const X25519 = crypto.dh.X25519;17const X25519 = crypto.dh.X25519;
18const Error = crypto.Error;18
19const AuthenticationError = crypto.errors.AuthenticationError;
20const IdentityElementError = crypto.errors.IdentityElementError;
21const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
1922
20const Salsa20VecImpl = struct {23const Salsa20VecImpl = struct {
21 const Lane = Vector(4, u32);24 const Lane = Vector(4, u32);
...@@ -399,7 +402,7 @@ pub const XSalsa20Poly1305 = struct {...@@ -399,7 +402,7 @@ pub const XSalsa20Poly1305 = struct {
399 /// ad: Associated Data402 /// ad: Associated Data
400 /// npub: public nonce403 /// npub: public nonce
401 /// k: private key404 /// k: private key
402 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {405 pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
403 debug.assert(c.len == m.len);406 debug.assert(c.len == m.len);
404 const extended = extend(k, npub);407 const extended = extend(k, npub);
405 var block0 = [_]u8{0} ** 64;408 var block0 = [_]u8{0} ** 64;
...@@ -447,7 +450,7 @@ pub const SecretBox = struct {...@@ -447,7 +450,7 @@ pub const SecretBox = struct {
447450
448 /// Verify and decrypt `c` using a nonce `npub` and a key `k`.451 /// Verify and decrypt `c` using a nonce `npub` and a key `k`.
449 /// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message.452 /// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message.
450 pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {453 pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
451 if (c.len < tag_length) {454 if (c.len < tag_length) {
452 return error.AuthenticationFailed;455 return error.AuthenticationFailed;
453 }456 }
...@@ -482,20 +485,20 @@ pub const Box = struct {...@@ -482,20 +485,20 @@ pub const Box = struct {
482 pub const KeyPair = X25519.KeyPair;485 pub const KeyPair = X25519.KeyPair;
483486
484 /// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key.487 /// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key.
485 pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) Error![shared_length]u8 {488 pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError)![shared_length]u8 {
486 const p = try X25519.scalarmult(secret_key, public_key);489 const p = try X25519.scalarmult(secret_key, public_key);
487 const zero = [_]u8{0} ** 16;490 const zero = [_]u8{0} ** 16;
488 return Salsa20Impl.hsalsa20(zero, p);491 return Salsa20Impl.hsalsa20(zero, p);
489 }492 }
490493
491 /// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`.494 /// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`.
492 pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void {495 pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError)!void {
493 const shared_key = try createSharedSecret(public_key, secret_key);496 const shared_key = try createSharedSecret(public_key, secret_key);
494 return SecretBox.seal(c, m, npub, shared_key);497 return SecretBox.seal(c, m, npub, shared_key);
495 }498 }
496499
497 /// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`.500 /// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`.
498 pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void {501 pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError || AuthenticationError)!void {
499 const shared_key = try createSharedSecret(public_key, secret_key);502 const shared_key = try createSharedSecret(public_key, secret_key);
500 return SecretBox.open(m, c, npub, shared_key);503 return SecretBox.open(m, c, npub, shared_key);
501 }504 }
...@@ -528,7 +531,7 @@ pub const SealedBox = struct {...@@ -528,7 +531,7 @@ pub const SealedBox = struct {
528531
529 /// Encrypt a message `m` for a recipient whose public key is `public_key`.532 /// Encrypt a message `m` for a recipient whose public key is `public_key`.
530 /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added.533 /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added.
531 pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) Error!void {534 pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) (WeakPublicKeyError || IdentityElementError)!void {
532 debug.assert(c.len == m.len + seal_length);535 debug.assert(c.len == m.len + seal_length);
533 var ekp = try KeyPair.create(null);536 var ekp = try KeyPair.create(null);
534 const nonce = createNonce(ekp.public_key, public_key);537 const nonce = createNonce(ekp.public_key, public_key);
...@@ -539,7 +542,7 @@ pub const SealedBox = struct {...@@ -539,7 +542,7 @@ pub const SealedBox = struct {
539542
540 /// Decrypt a message using a key pair.543 /// Decrypt a message using a key pair.
541 /// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata.544 /// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata.
542 pub fn open(m: []u8, c: []const u8, keypair: KeyPair) Error!void {545 pub fn open(m: []u8, c: []const u8, keypair: KeyPair) (IdentityElementError || WeakPublicKeyError || AuthenticationError)!void {
543 if (c.len < seal_length) {546 if (c.len < seal_length) {
544 return error.AuthenticationFailed;547 return error.AuthenticationFailed;
545 }548 }