Browse Source

core/crypto/poly1305: The final addition is NOT mod p

Yawning Angel 1 year ago
parent
commit
a45721e9ad
1 changed files with 17 additions and 9 deletions
  1. 17 9
      core/crypto/poly1305/poly1305.odin

+ 17 - 9
core/crypto/poly1305/poly1305.odin

@@ -9,6 +9,7 @@ package poly1305
 import "core:crypto"
 import "core:crypto"
 import field "core:crypto/_fiat/field_poly1305"
 import field "core:crypto/_fiat/field_poly1305"
 import "core:encoding/endian"
 import "core:encoding/endian"
+import "core:math/bits"
 import "core:mem"
 import "core:mem"
 
 
 // KEY_SIZE is the Poly1305 key size in bytes.
 // KEY_SIZE is the Poly1305 key size in bytes.
@@ -50,7 +51,7 @@ verify :: proc(tag, msg, key: []byte) -> bool {
 Context :: struct {
 Context :: struct {
 	_r:              field.Tight_Field_Element,
 	_r:              field.Tight_Field_Element,
 	_a:              field.Tight_Field_Element,
 	_a:              field.Tight_Field_Element,
-	_s:              field.Tight_Field_Element,
+	_s:              [2]u64,
 	_buffer:         [_BLOCK_SIZE]byte,
 	_buffer:         [_BLOCK_SIZE]byte,
 	_leftover:       int,
 	_leftover:       int,
 	_is_initialized: bool,
 	_is_initialized: bool,
@@ -66,11 +67,12 @@ init :: proc(ctx: ^Context, key: []byte) {
 	// r = le_bytes_to_num(key[0..15])
 	// r = le_bytes_to_num(key[0..15])
 	// r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff)
 	// r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff)
 	tmp_lo := endian.unchecked_get_u64le(key[0:]) & 0x0ffffffc0fffffff
 	tmp_lo := endian.unchecked_get_u64le(key[0:]) & 0x0ffffffc0fffffff
-	tmp_hi := endian.unchecked_get_u64le(key[8:]) & 0xffffffc0ffffffc
+	tmp_hi := endian.unchecked_get_u64le(key[8:]) & 0x0ffffffc0ffffffc
 	field.fe_from_u64s(&ctx._r, tmp_lo, tmp_hi)
 	field.fe_from_u64s(&ctx._r, tmp_lo, tmp_hi)
 
 
 	// s = le_bytes_to_num(key[16..31])
 	// s = le_bytes_to_num(key[16..31])
-	field.fe_from_bytes(&ctx._s, key[16:32], 0)
+	ctx._s[0] = endian.unchecked_get_u64le(key[16:])
+	ctx._s[1] = endian.unchecked_get_u64le(key[24:])
 
 
 	// a = 0
 	// a = 0
 	field.fe_zero(&ctx._a)
 	field.fe_zero(&ctx._a)
@@ -138,14 +140,20 @@ final :: proc(ctx: ^Context, dst: []byte) {
 		_blocks(ctx, ctx._buffer[:], true)
 		_blocks(ctx, ctx._buffer[:], true)
 	}
 	}
 
 
-	// a += s
-	field.fe_add(field.fe_relax_cast(&ctx._a), &ctx._a, &ctx._s) // _a unreduced
-	field.fe_carry(&ctx._a, field.fe_relax_cast(&ctx._a)) // _a reduced
-
-	// return num_to_16_le_bytes(a)
+	// a += s (NOT mod p)
 	tmp: [32]byte = ---
 	tmp: [32]byte = ---
 	field.fe_to_bytes(&tmp, &ctx._a)
 	field.fe_to_bytes(&tmp, &ctx._a)
-	copy_slice(dst, tmp[0:16])
+
+	c: u64
+	lo := endian.unchecked_get_u64le(tmp[0:])
+	hi := endian.unchecked_get_u64le(tmp[8:])
+
+	lo, c = bits.add_u64(lo, ctx._s[0], 0)
+	hi, _ = bits.add_u64(hi, ctx._s[1], c)
+
+	// return num_to_16_le_bytes(a)
+	endian.unchecked_put_u64le(dst[0:], lo)
+	endian.unchecked_put_u64le(dst[8:], hi)
 }
 }
 
 
 // reset sanitizes the Context.  The Context must be re-initialized to
 // reset sanitizes the Context.  The Context must be re-initialized to