summaryrefslogtreecommitdiff
path: root/libgo/go/crypto/elliptic/internal/fiat/p224.go
blob: 4dddeb07a4199b394ad01d910e1d1577b5370f7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated by generate.go. DO NOT EDIT.

package fiat

import (
	"crypto/subtle"
	"errors"
)

// P224Element is an integer modulo 2^224 - 2^96 + 1.
//
// The zero value is a valid zero element.
type P224Element struct {
	// Values are represented internally always in the Montgomery domain, and
	// converted in Bytes and SetBytes.
	x p224MontgomeryDomainFieldElement
}

const p224ElementLen = 28

type p224UntypedFieldElement = [4]uint64

// One sets e = 1, and returns e.
func (e *P224Element) One() *P224Element {
	p224SetOne(&e.x)
	return e
}

// Equal returns 1 if e == t, and zero otherwise.
func (e *P224Element) Equal(t *P224Element) int {
	eBytes := e.Bytes()
	tBytes := t.Bytes()
	return subtle.ConstantTimeCompare(eBytes, tBytes)
}

var p224ZeroEncoding = new(P224Element).Bytes()

// IsZero returns 1 if e == 0, and zero otherwise.
func (e *P224Element) IsZero() int {
	eBytes := e.Bytes()
	return subtle.ConstantTimeCompare(eBytes, p224ZeroEncoding)
}

// Set sets e = t, and returns e.
func (e *P224Element) Set(t *P224Element) *P224Element {
	e.x = t.x
	return e
}

// Bytes returns the 28-byte big-endian encoding of e.
func (e *P224Element) Bytes() []byte {
	// This function is outlined to make the allocations inline in the caller
	// rather than happen on the heap.
	var out [p224ElementLen]byte
	return e.bytes(&out)
}

func (e *P224Element) bytes(out *[p224ElementLen]byte) []byte {
	var tmp p224NonMontgomeryDomainFieldElement
	p224FromMontgomery(&tmp, &e.x)
	p224ToBytes(out, (*p224UntypedFieldElement)(&tmp))
	p224InvertEndianness(out[:])
	return out[:]
}

// p224MinusOneEncoding is the encoding of -1 mod p, so p - 1, the
// highest canonical encoding. It is used by SetBytes to check for non-canonical
// encodings such as p + k, 2p + k, etc.
var p224MinusOneEncoding = new(P224Element).Sub(
	new(P224Element), new(P224Element).One()).Bytes()

// SetBytes sets e = v, where v is a big-endian 28-byte encoding, and returns e.
// If v is not 28 bytes or it encodes a value higher than 2^224 - 2^96 + 1,
// SetBytes returns nil and an error, and e is unchanged.
func (e *P224Element) SetBytes(v []byte) (*P224Element, error) {
	if len(v) != p224ElementLen {
		return nil, errors.New("invalid P224Element encoding")
	}
	for i := range v {
		if v[i] < p224MinusOneEncoding[i] {
			break
		}
		if v[i] > p224MinusOneEncoding[i] {
			return nil, errors.New("invalid P224Element encoding")
		}
	}
	var in [p224ElementLen]byte
	copy(in[:], v)
	p224InvertEndianness(in[:])
	var tmp p224NonMontgomeryDomainFieldElement
	p224FromBytes((*p224UntypedFieldElement)(&tmp), &in)
	p224ToMontgomery(&e.x, &tmp)
	return e, nil
}

// Add sets e = t1 + t2, and returns e.
func (e *P224Element) Add(t1, t2 *P224Element) *P224Element {
	p224Add(&e.x, &t1.x, &t2.x)
	return e
}

// Sub sets e = t1 - t2, and returns e.
func (e *P224Element) Sub(t1, t2 *P224Element) *P224Element {
	p224Sub(&e.x, &t1.x, &t2.x)
	return e
}

// Mul sets e = t1 * t2, and returns e.
func (e *P224Element) Mul(t1, t2 *P224Element) *P224Element {
	p224Mul(&e.x, &t1.x, &t2.x)
	return e
}

// Square sets e = t * t, and returns e.
func (e *P224Element) Square(t *P224Element) *P224Element {
	p224Square(&e.x, &t.x)
	return e
}

// Select sets v to a if cond == 1, and to b if cond == 0.
func (v *P224Element) Select(a, b *P224Element, cond int) *P224Element {
	p224Selectznz((*p224UntypedFieldElement)(&v.x), p224Uint1(cond),
		(*p224UntypedFieldElement)(&b.x), (*p224UntypedFieldElement)(&a.x))
	return v
}

func p224InvertEndianness(v []byte) {
	for i := 0; i < len(v)/2; i++ {
		v[i], v[len(v)-1-i] = v[len(v)-1-i], v[i]
	}
}