| ... | @@ -144,7 +144,7 @@ pub const Edwards25519 = struct { | ... | @@ -144,7 +144,7 @@ pub const Edwards25519 = struct { |
| 144 | | 144 | |
| 145 | inline fn pcSelect(pc: [16]Edwards25519, b: u8) Edwards25519 { | 145 | inline fn pcSelect(pc: [16]Edwards25519, b: u8) Edwards25519 { |
| 146 | var t = Edwards25519.identityElement; | 146 | var t = Edwards25519.identityElement; |
| 147 | comptime var i: u8 = 0; | 147 | comptime var i: u8 = 1; |
| 148 | inline while (i < 16) : (i += 1) { | 148 | inline while (i < 16) : (i += 1) { |
| 149 | t.cMov(pc[i], ((@as(usize, b ^ i) -% 1) >> 8) & 1); | 149 | t.cMov(pc[i], ((@as(usize, b ^ i) -% 1) >> 8) & 1); |
| 150 | } | 150 | } |
| ... | @@ -155,7 +155,6 @@ pub const Edwards25519 = struct { | ... | @@ -155,7 +155,6 @@ pub const Edwards25519 = struct { |
| 155 | var q = Edwards25519.identityElement; | 155 | var q = Edwards25519.identityElement; |
| 156 | var pos: usize = 252; | 156 | var pos: usize = 252; |
| 157 | while (true) : (pos -= 4) { | 157 | while (true) : (pos -= 4) { |
| 158 | q = q.dbl().dbl().dbl().dbl(); | | |
| 159 | const bit = (s[pos >> 3] >> @truncate(u3, pos)) & 0xf; | 158 | const bit = (s[pos >> 3] >> @truncate(u3, pos)) & 0xf; |
| 160 | if (vartime) { | 159 | if (vartime) { |
| 161 | if (bit != 0) { | 160 | if (bit != 0) { |
| ... | @@ -165,6 +164,7 @@ pub const Edwards25519 = struct { | ... | @@ -165,6 +164,7 @@ pub const Edwards25519 = struct { |
| 165 | q = q.add(pcSelect(pc, bit)); | 164 | q = q.add(pcSelect(pc, bit)); |
| 166 | } | 165 | } |
| 167 | if (pos == 0) break; | 166 | if (pos == 0) break; |
| | 167 | q = q.dbl().dbl().dbl().dbl(); |
| 168 | } | 168 | } |
| 169 | try q.rejectIdentity(); | 169 | try q.rejectIdentity(); |
| 170 | return q; | 170 | return q; |
| ... | @@ -181,32 +181,31 @@ pub const Edwards25519 = struct { | ... | @@ -181,32 +181,31 @@ pub const Edwards25519 = struct { |
| 181 | return pc; | 181 | return pc; |
| 182 | } | 182 | } |
| 183 | | 183 | |
| | 184 | const basePointPc = comptime pc: { |
| | 185 | @setEvalBranchQuota(10000); |
| | 186 | break :pc precompute(Edwards25519.basePoint); |
| | 187 | }; |
| | 188 | |
| 184 | /// Multiply an Edwards25519 point by a scalar without clamping it. | 189 | /// Multiply an Edwards25519 point by a scalar without clamping it. |
| 185 | /// Return error.WeakPublicKey if the resulting point is | 190 | /// Return error.WeakPublicKey if the resulting point is |
| 186 | /// the identity element. | 191 | /// the identity element. |
| 187 | pub fn mul(p: Edwards25519, s: [32]u8) !Edwards25519 { | 192 | pub fn mul(p: Edwards25519, s: [32]u8) !Edwards25519 { |
| 188 | var pc: [16]Edwards25519 = undefined; | 193 | const pc = if (p.is_base) basePointPc else pc: { |
| 189 | if (p.is_base) { | 194 | const xpc = precompute(p); |
| 190 | @setEvalBranchQuota(10000); | 195 | xpc[4].rejectIdentity() catch |_| return error.WeakPublicKey; |
| 191 | pc = comptime precompute(Edwards25519.basePoint); | 196 | break :pc xpc; |
| 192 | } else { | 197 | }; |
| 193 | pc = precompute(p); | | |
| 194 | pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; | | |
| 195 | } | | |
| 196 | return pcMul(pc, s, false); | 198 | return pcMul(pc, s, false); |
| 197 | } | 199 | } |
| 198 | | 200 | |
| 199 | /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* | 201 | /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* |
| 200 | /// This can be used for signature verification. | 202 | /// This can be used for signature verification. |
| 201 | pub fn mulPublic(p: Edwards25519, s: [32]u8) !Edwards25519 { | 203 | pub fn mulPublic(p: Edwards25519, s: [32]u8) !Edwards25519 { |
| 202 | var pc: [16]Edwards25519 = undefined; | 204 | const pc = if (p.is_base) basePointPc else pc: { |
| 203 | if (p.is_base) { | 205 | const xpc = precompute(p); |
| 204 | @setEvalBranchQuota(10000); | 206 | xpc[4].rejectIdentity() catch |_| return error.WeakPublicKey; |
| 205 | pc = comptime precompute(Edwards25519.basePoint); | 207 | break :pc xpc; |
| 206 | } else { | 208 | }; |
| 207 | pc = precompute(p); | | |
| 208 | pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; | | |
| 209 | } | | |
| 210 | return pcMul(pc, s, true); | 209 | return pcMul(pc, s, true); |
| 211 | } | 210 | } |
| 212 | | 211 | |
| ... | @@ -215,18 +214,15 @@ pub const Edwards25519 = struct { | ... | @@ -215,18 +214,15 @@ pub const Edwards25519 = struct { |
| 215 | pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) !Edwards25519 { | 214 | pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) !Edwards25519 { |
| 216 | var pcs: [count][16]Edwards25519 = undefined; | 215 | var pcs: [count][16]Edwards25519 = undefined; |
| 217 | for (ps) |p, i| { | 216 | for (ps) |p, i| { |
| 218 | if (p.is_base) { | 217 | pcs[i] = if (p.is_base) basePointPc else pc: { |
| 219 | @setEvalBranchQuota(10000); | 218 | const xpc = precompute(p); |
| 220 | pcs[i] = comptime precompute(Edwards25519.basePoint); | 219 | xpc[4].rejectIdentity() catch |_| return error.WeakPublicKey; |
| 221 | } else { | 220 | break :pc xpc; |
| 222 | pcs[i] = precompute(p); | 221 | }; |
| 223 | pcs[i][4].rejectIdentity() catch |_| return error.WeakPublicKey; | | |
| 224 | } | | |
| 225 | } | 222 | } |
| 226 | var q = Edwards25519.identityElement; | 223 | var q = Edwards25519.identityElement; |
| 227 | var pos: usize = 252; | 224 | var pos: usize = 252; |
| 228 | while (true) : (pos -= 4) { | 225 | while (true) : (pos -= 4) { |
| 229 | q = q.dbl().dbl().dbl().dbl(); | | |
| 230 | for (ss) |s, i| { | 226 | for (ss) |s, i| { |
| 231 | const bit = (s[pos >> 3] >> @truncate(u3, pos)) & 0xf; | 227 | const bit = (s[pos >> 3] >> @truncate(u3, pos)) & 0xf; |
| 232 | if (bit != 0) { | 228 | if (bit != 0) { |
| ... | @@ -234,6 +230,7 @@ pub const Edwards25519 = struct { | ... | @@ -234,6 +230,7 @@ pub const Edwards25519 = struct { |
| 234 | } | 230 | } |
| 235 | } | 231 | } |
| 236 | if (pos == 0) break; | 232 | if (pos == 0) break; |
| | 233 | q = q.dbl().dbl().dbl().dbl(); |
| 237 | } | 234 | } |
| 238 | try q.rejectIdentity(); | 235 | try q.rejectIdentity(); |
| 239 | return q; | 236 | return q; |